damlforge 0.0.13__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- damlforge-0.0.13/.claude/skills/damlforge-vy-lang/SKILL.md +83 -0
- damlforge-0.0.13/.claude/skills/damlforge-vy-lang/reference.md +445 -0
- damlforge-0.0.13/.github/workflows/build-wheel.yml +50 -0
- damlforge-0.0.13/.github/workflows/license-header.yml +19 -0
- damlforge-0.0.13/.github/workflows/publish-pypi.yml +66 -0
- damlforge-0.0.13/.gitignore +78 -0
- damlforge-0.0.13/LICENSE +201 -0
- damlforge-0.0.13/Makefile +89 -0
- damlforge-0.0.13/PKG-INFO +336 -0
- damlforge-0.0.13/README.md +293 -0
- damlforge-0.0.13/damlforge.egg-info/PKG-INFO +336 -0
- damlforge-0.0.13/damlforge.egg-info/SOURCES.txt +390 -0
- damlforge-0.0.13/damlforge.egg-info/dependency_links.txt +1 -0
- damlforge-0.0.13/damlforge.egg-info/entry_points.txt +2 -0
- damlforge-0.0.13/damlforge.egg-info/requires.txt +12 -0
- damlforge-0.0.13/damlforge.egg-info/top_level.txt +1 -0
- damlforge-0.0.13/docs/guide/01-dev-environment.md +376 -0
- damlforge-0.0.13/docs/guide/02-language-fundamentals.md +733 -0
- damlforge-0.0.13/docs/guide/03-compiler-errors.md +765 -0
- damlforge-0.0.13/docs/guide/04-contract-templates.md +255 -0
- damlforge-0.0.13/docs/guide/05-choices.md +441 -0
- damlforge-0.0.13/docs/guide/06-design-patterns.md +413 -0
- damlforge-0.0.13/docs/guide/07-working-with-time.md +307 -0
- damlforge-0.0.13/docs/guide/08-contract-keys.md +254 -0
- damlforge-0.0.13/docs/guide/09-interfaces.md +216 -0
- damlforge-0.0.13/docs/guide/10-building-packaging.md +190 -0
- damlforge-0.0.13/docs/guide/11-variants.md +465 -0
- damlforge-0.0.13/examples/basic/interfaces.vy +11 -0
- damlforge-0.0.13/examples/basic/models.vy +30 -0
- damlforge-0.0.13/examples/basic/recursion.vy +21 -0
- damlforge-0.0.13/examples/basic/simple.vy +104 -0
- damlforge-0.0.13/examples/crowd_loans/daml.yaml +22 -0
- damlforge-0.0.13/examples/crowd_loans/funding_campaign.py +1359 -0
- damlforge-0.0.13/examples/crowd_loans/loan_terms.vy +581 -0
- damlforge-0.0.13/examples/splice-api-token-burn-mint-v1/daml/Splice/Api/Token/burn_mint_v1.vy +40 -0
- damlforge-0.0.13/examples/splice-api-token-burn-mint-v1/daml.yaml +20 -0
- damlforge-0.0.13/examples/splice-util-batched-markers/daml/Splice/Util/FeaturedApp/BatchedMarkersProxy.daml +188 -0
- damlforge-0.0.13/examples/splice-util-batched-markers/daml/Splice/Util/FeaturedApp/batched_markers_proxy.vy +163 -0
- damlforge-0.0.13/examples/splice-util-batched-markers/daml.yaml +12 -0
- damlforge-0.0.13/examples/splice-util-batched-markers-test/daml.yaml +18 -0
- damlforge-0.0.13/examples/splice-util-batched-markers-test/deps/splice-token-standard-v1-test-3.4.8.dar +0 -0
- damlforge-0.0.13/examples/splice-wallet/daml/Splice/Wallet/buy_traffic_request.vy +99 -0
- damlforge-0.0.13/examples/splice-wallet/daml/Splice/Wallet/install.vy +1144 -0
- damlforge-0.0.13/examples/splice-wallet/daml/Splice/Wallet/minting_delegation.vy +201 -0
- damlforge-0.0.13/examples/splice-wallet/daml/Splice/Wallet/top_up_state.vy +40 -0
- damlforge-0.0.13/examples/splice-wallet/daml/Splice/Wallet/transfer_offer.vy +206 -0
- damlforge-0.0.13/examples/splice-wallet/daml/Splice/Wallet/transfer_preapproval.vy +58 -0
- damlforge-0.0.13/examples/splice-wallet/daml.yaml +33 -0
- damlforge-0.0.13/examples/token_standard/token_standard.vy +159 -0
- damlforge-0.0.13/forge/__init__.py +39 -0
- damlforge-0.0.13/forge/__main__.py +21 -0
- damlforge-0.0.13/forge/ast/README.md +122 -0
- damlforge-0.0.13/forge/ast/__init__.py +31 -0
- damlforge-0.0.13/forge/ast/__init__.pyi +7 -0
- damlforge-0.0.13/forge/ast/grammar.lark +334 -0
- damlforge-0.0.13/forge/ast/grammar.py +52 -0
- damlforge-0.0.13/forge/ast/identifiers.py +91 -0
- damlforge-0.0.13/forge/ast/metadata.py +98 -0
- damlforge-0.0.13/forge/ast/nodes.py +1585 -0
- damlforge-0.0.13/forge/ast/nodes.pyi +318 -0
- damlforge-0.0.13/forge/ast/parse.py +568 -0
- damlforge-0.0.13/forge/ast/pre_parser.py +411 -0
- damlforge-0.0.13/forge/ast/utils.py +91 -0
- damlforge-0.0.13/forge/builtin_stubs.py +281 -0
- damlforge-0.0.13/forge/builtins/DA/Action/State/Class.vy +14 -0
- damlforge-0.0.13/forge/builtins/DA/Action/State.vy +17 -0
- damlforge-0.0.13/forge/builtins/DA/Assert.vy +36 -0
- damlforge-0.0.13/forge/builtins/DA/Crypto/Text.vy +178 -0
- damlforge-0.0.13/forge/builtins/DA/Date/Types.vy +31 -0
- damlforge-0.0.13/forge/builtins/DA/Date.vy +67 -0
- damlforge-0.0.13/forge/builtins/DA/Either.vy +61 -0
- damlforge-0.0.13/forge/builtins/DA/Exception/ArithmeticError.vy +6 -0
- damlforge-0.0.13/forge/builtins/DA/Exception/AssertionFailed.vy +6 -0
- damlforge-0.0.13/forge/builtins/DA/Exception/GeneralError.vy +6 -0
- damlforge-0.0.13/forge/builtins/DA/Exception/PreconditionFailed.vy +6 -0
- damlforge-0.0.13/forge/builtins/DA/Internal/Assert.vy +23 -0
- damlforge-0.0.13/forge/builtins/DA/Internal/Compatible.vy +57 -0
- damlforge-0.0.13/forge/builtins/DA/Internal/Date.vy +13 -0
- damlforge-0.0.13/forge/builtins/DA/Internal/Down.vy +10 -0
- damlforge-0.0.13/forge/builtins/DA/Internal/Erased.vy +8 -0
- damlforge-0.0.13/forge/builtins/DA/Internal/Exception.vy +12 -0
- damlforge-0.0.13/forge/builtins/DA/Internal/Fail.vy +11 -0
- damlforge-0.0.13/forge/builtins/DA/Internal/Interface/AnyView.vy +18 -0
- damlforge-0.0.13/forge/builtins/DA/Internal/Interface.vy +54 -0
- damlforge-0.0.13/forge/builtins/DA/Internal/LF.vy +28 -0
- damlforge-0.0.13/forge/builtins/DA/Internal/NatSyn.vy +12 -0
- damlforge-0.0.13/forge/builtins/DA/Internal/Prelude.vy +186 -0
- damlforge-0.0.13/forge/builtins/DA/Internal/PromotedText.vy +12 -0
- damlforge-0.0.13/forge/builtins/DA/Internal/Record.vy +16 -0
- damlforge-0.0.13/forge/builtins/DA/Internal/Template/Functions.vy +130 -0
- damlforge-0.0.13/forge/builtins/DA/Internal/Template.vy +6 -0
- damlforge-0.0.13/forge/builtins/DA/Internal/Time.vy +22 -0
- damlforge-0.0.13/forge/builtins/DA/List/BuiltinOrder.vy +22 -0
- damlforge-0.0.13/forge/builtins/DA/List/Total.vy +21 -0
- damlforge-0.0.13/forge/builtins/DA/List.vy +135 -0
- damlforge-0.0.13/forge/builtins/DA/Logic/Types.vy +35 -0
- damlforge-0.0.13/forge/builtins/DA/Logic.vy +57 -0
- damlforge-0.0.13/forge/builtins/DA/Map.vy +61 -0
- damlforge-0.0.13/forge/builtins/DA/Math.vy +66 -0
- damlforge-0.0.13/forge/builtins/DA/Maybe.vy +46 -0
- damlforge-0.0.13/forge/builtins/DA/Monoid/Types.vy +25 -0
- damlforge-0.0.13/forge/builtins/DA/NonEmpty/Types.vy +11 -0
- damlforge-0.0.13/forge/builtins/DA/NonEmpty.vy +37 -0
- damlforge-0.0.13/forge/builtins/DA/Numeric.vy +113 -0
- damlforge-0.0.13/forge/builtins/DA/Optional.vy +46 -0
- damlforge-0.0.13/forge/builtins/DA/Random/Types.vy +13 -0
- damlforge-0.0.13/forge/builtins/DA/Random.vy +19 -0
- damlforge-0.0.13/forge/builtins/DA/Semigroup/Types.vy +15 -0
- damlforge-0.0.13/forge/builtins/DA/Set/Types.vy +11 -0
- damlforge-0.0.13/forge/builtins/DA/Set.vy +81 -0
- damlforge-0.0.13/forge/builtins/DA/Stack/Types.vy +14 -0
- damlforge-0.0.13/forge/builtins/DA/Stack.vy +33 -0
- damlforge-0.0.13/forge/builtins/DA/Text.vy +192 -0
- damlforge-0.0.13/forge/builtins/DA/TextMap.vy +53 -0
- damlforge-0.0.13/forge/builtins/DA/Time/Types.vy +6 -0
- damlforge-0.0.13/forge/builtins/DA/Time.vy +72 -0
- damlforge-0.0.13/forge/builtins/DA/Tuple.vy +26 -0
- damlforge-0.0.13/forge/builtins/DA/Types.vy +329 -0
- damlforge-0.0.13/forge/builtins/DA/Validation/Types.vy +25 -0
- damlforge-0.0.13/forge/builtins/DA/Validation.vy +34 -0
- damlforge-0.0.13/forge/builtins/GHC/Base.vy +13 -0
- damlforge-0.0.13/forge/builtins/GHC/Classes.vy +43 -0
- damlforge-0.0.13/forge/builtins/GHC/Enum.vy +86 -0
- damlforge-0.0.13/forge/builtins/GHC/Err.vy +10 -0
- damlforge-0.0.13/forge/builtins/GHC/Num.vy +32 -0
- damlforge-0.0.13/forge/builtins/GHC/Show/Text.vy +72 -0
- damlforge-0.0.13/forge/builtins/GHC/Show.vy +38 -0
- damlforge-0.0.13/forge/builtins/GHC/Stack/Types.vy +53 -0
- damlforge-0.0.13/forge/builtins/GHC/Tuple.vy +10 -0
- damlforge-0.0.13/forge/builtins/GHC/Types.vy +10 -0
- damlforge-0.0.13/forge/builtins/Splice/Amulet/CryptoHash.vy +59 -0
- damlforge-0.0.13/forge/builtins/Splice/Amulet/RewardAccountingV2.vy +67 -0
- damlforge-0.0.13/forge/builtins/Splice/Amulet/TokenApiUtils.vy +217 -0
- damlforge-0.0.13/forge/builtins/Splice/Amulet/TwoStepTransfer.vy +43 -0
- damlforge-0.0.13/forge/builtins/Splice/Amulet.vy +442 -0
- damlforge-0.0.13/forge/builtins/Splice/AmuletAllocation.vy +54 -0
- damlforge-0.0.13/forge/builtins/Splice/AmuletAllocationV2.vy +53 -0
- damlforge-0.0.13/forge/builtins/Splice/AmuletConfig.vy +147 -0
- damlforge-0.0.13/forge/builtins/Splice/AmuletEventLog.vy +8 -0
- damlforge-0.0.13/forge/builtins/Splice/AmuletRules.vy +901 -0
- damlforge-0.0.13/forge/builtins/Splice/AmuletTransferInstruction.vy +37 -0
- damlforge-0.0.13/forge/builtins/Splice/Ans/AmuletConversionRateFeed.vy +42 -0
- damlforge-0.0.13/forge/builtins/Splice/Ans.vy +173 -0
- damlforge-0.0.13/forge/builtins/Splice/Api/FeaturedAppRightV1.vy +41 -0
- damlforge-0.0.13/forge/builtins/Splice/Api/FeaturedAppRightV2.vy +41 -0
- damlforge-0.0.13/forge/builtins/Splice/Api/RewardAssignmentV1.vy +36 -0
- damlforge-0.0.13/forge/builtins/Splice/Api/Token/AllocationInstructionV1.vy +92 -0
- damlforge-0.0.13/forge/builtins/Splice/Api/Token/AllocationInstructionV2.vy +132 -0
- damlforge-0.0.13/forge/builtins/Splice/Api/Token/AllocationRequestV1.vy +32 -0
- damlforge-0.0.13/forge/builtins/Splice/Api/Token/AllocationRequestV2.vy +96 -0
- damlforge-0.0.13/forge/builtins/Splice/Api/Token/AllocationV1.vy +91 -0
- damlforge-0.0.13/forge/builtins/Splice/Api/Token/AllocationV2.vy +210 -0
- damlforge-0.0.13/forge/builtins/Splice/Api/Token/BurnMintV1.vy +41 -0
- damlforge-0.0.13/forge/builtins/Splice/Api/Token/HoldingV1.vy +30 -0
- damlforge-0.0.13/forge/builtins/Splice/Api/Token/HoldingV2.vy +36 -0
- damlforge-0.0.13/forge/builtins/Splice/Api/Token/MetadataV1.vy +113 -0
- damlforge-0.0.13/forge/builtins/Splice/Api/Token/Test/DummyHolding.vy +10 -0
- damlforge-0.0.13/forge/builtins/Splice/Api/Token/Test/DummyTwoInterfaces.vy +13 -0
- damlforge-0.0.13/forge/builtins/Splice/Api/Token/TransferEventsV2.vy +42 -0
- damlforge-0.0.13/forge/builtins/Splice/Api/Token/TransferInstructionV1.vy +135 -0
- damlforge-0.0.13/forge/builtins/Splice/Api/Token/TransferInstructionV2.vy +159 -0
- damlforge-0.0.13/forge/builtins/Splice/AppManager/Store.vy +52 -0
- damlforge-0.0.13/forge/builtins/Splice/CometBft.vy +56 -0
- damlforge-0.0.13/forge/builtins/Splice/DSO/AmuletPrice.vy +24 -0
- damlforge-0.0.13/forge/builtins/Splice/DSO/DecentralizedSynchronizer.vy +100 -0
- damlforge-0.0.13/forge/builtins/Splice/DSO/SvState.vy +67 -0
- damlforge-0.0.13/forge/builtins/Splice/DecentralizedSynchronizer.vy +54 -0
- damlforge-0.0.13/forge/builtins/Splice/DsoBootstrap.vy +40 -0
- damlforge-0.0.13/forge/builtins/Splice/DsoRules.vy +1077 -0
- damlforge-0.0.13/forge/builtins/Splice/Expiry.vy +92 -0
- damlforge-0.0.13/forge/builtins/Splice/ExternalPartyAmuletRules.vy +146 -0
- damlforge-0.0.13/forge/builtins/Splice/ExternalPartyConfigState.vy +20 -0
- damlforge-0.0.13/forge/builtins/Splice/Fees.vy +125 -0
- damlforge-0.0.13/forge/builtins/Splice/Issuance.vy +79 -0
- damlforge-0.0.13/forge/builtins/Splice/RelRound.vy +16 -0
- damlforge-0.0.13/forge/builtins/Splice/Round.vy +80 -0
- damlforge-0.0.13/forge/builtins/Splice/Schedule.vy +54 -0
- damlforge-0.0.13/forge/builtins/Splice/Splitwell.vy +238 -0
- damlforge-0.0.13/forge/builtins/Splice/SvOnboarding.vy +53 -0
- damlforge-0.0.13/forge/builtins/Splice/Testing/Apps/TradingApp.vy +78 -0
- damlforge-0.0.13/forge/builtins/Splice/Testing/Apps/TradingAppV2.vy +159 -0
- damlforge-0.0.13/forge/builtins/Splice/Testing/Tokens/TestTokenV1.vy +50 -0
- damlforge-0.0.13/forge/builtins/Splice/Testing/Tokens/TestTokenV2/AccountConfig.vy +212 -0
- damlforge-0.0.13/forge/builtins/Splice/Testing/Tokens/TestTokenV2/Allocation.vy +140 -0
- damlforge-0.0.13/forge/builtins/Splice/Testing/Tokens/TestTokenV2/Holding.vy +20 -0
- damlforge-0.0.13/forge/builtins/Splice/Testing/Tokens/TestTokenV2/Transfer.vy +60 -0
- damlforge-0.0.13/forge/builtins/Splice/Testing/Tokens/TestTokenV2/Util.vy +47 -0
- damlforge-0.0.13/forge/builtins/Splice/Testing/Tokens/TestTokenV2.vy +40 -0
- damlforge-0.0.13/forge/builtins/Splice/TokenStandard/Utils/Internal/Allocations.vy +251 -0
- damlforge-0.0.13/forge/builtins/Splice/TokenStandard/Utils/Internal/Choices.vy +71 -0
- damlforge-0.0.13/forge/builtins/Splice/TokenStandard/Utils/Internal/Conversions.vy +229 -0
- damlforge-0.0.13/forge/builtins/Splice/TokenStandard/Utils/Internal/Events.vy +77 -0
- damlforge-0.0.13/forge/builtins/Splice/TokenStandard/Utils/Internal/Transfers.vy +50 -0
- damlforge-0.0.13/forge/builtins/Splice/TokenStandard/Utils.vy +5 -0
- damlforge-0.0.13/forge/builtins/Splice/Types.vy +25 -0
- damlforge-0.0.13/forge/builtins/Splice/Util/FeaturedApp/BatchedMarkersProxy.vy +47 -0
- damlforge-0.0.13/forge/builtins/Splice/Util/FeaturedApp/DelegateProxy.vy +68 -0
- damlforge-0.0.13/forge/builtins/Splice/Util/FeaturedApp/WalletUserProxy.vy +127 -0
- damlforge-0.0.13/forge/builtins/Splice/Util/Token/Wallet/BatchingUtilityV2.vy +270 -0
- damlforge-0.0.13/forge/builtins/Splice/Util/Token/Wallet/MergeDelegation.vy +130 -0
- damlforge-0.0.13/forge/builtins/Splice/Util.vy +116 -0
- damlforge-0.0.13/forge/builtins/Splice/ValidatorLicense.vy +164 -0
- damlforge-0.0.13/forge/builtins/Splice/ValidatorOnboarding.vy +42 -0
- damlforge-0.0.13/forge/builtins/Splice/Wallet/BuyTrafficRequest.vy +56 -0
- damlforge-0.0.13/forge/builtins/Splice/Wallet/Install.vy +469 -0
- damlforge-0.0.13/forge/builtins/Splice/Wallet/MintingDelegation.vy +83 -0
- damlforge-0.0.13/forge/builtins/Splice/Wallet/Payment.vy +160 -0
- damlforge-0.0.13/forge/builtins/Splice/Wallet/Subscriptions.vy +233 -0
- damlforge-0.0.13/forge/builtins/Splice/Wallet/TopUpState.vy +22 -0
- damlforge-0.0.13/forge/builtins/Splice/Wallet/TransferOffer.vy +114 -0
- damlforge-0.0.13/forge/builtins/Splice/Wallet/TransferPreapproval.vy +27 -0
- damlforge-0.0.13/forge/builtins/__init__.py +618 -0
- damlforge-0.0.13/forge/builtins/daml_lang.py +161 -0
- damlforge-0.0.13/forge/builtins/maps.py +78 -0
- damlforge-0.0.13/forge/cli/__init__.py +14 -0
- damlforge-0.0.13/forge/cli/forge_daml.py +95 -0
- damlforge-0.0.13/forge/cli/forge_dar.py +189 -0
- damlforge-0.0.13/forge/cli/forge_json.py +26 -0
- damlforge-0.0.13/forge/cli/main.py +207 -0
- damlforge-0.0.13/forge/codegen/__init__.py +19 -0
- damlforge-0.0.13/forge/codegen/doc.py +78 -0
- damlforge-0.0.13/forge/codegen/emit.py +1384 -0
- damlforge-0.0.13/forge/codegen/loops.py +24 -0
- damlforge-0.0.13/forge/codegen/maps.py +76 -0
- damlforge-0.0.13/forge/codegen/optional.py +54 -0
- damlforge-0.0.13/forge/codegen/self_mutation.py +358 -0
- damlforge-0.0.13/forge/codegen/sets.py +55 -0
- damlforge-0.0.13/forge/codegen/source_map.py +263 -0
- damlforge-0.0.13/forge/compiler/__init__.py +14 -0
- damlforge-0.0.13/forge/compiler/settings.py +92 -0
- damlforge-0.0.13/forge/daml_versions.py +112 -0
- damlforge-0.0.13/forge/damlforge_git_commithash.txt +1 -0
- damlforge-0.0.13/forge/exceptions.py +459 -0
- damlforge-0.0.13/forge/ir/__init__.py +18 -0
- damlforge-0.0.13/forge/ir/fields.py +84 -0
- damlforge-0.0.13/forge/ir/imports.py +217 -0
- damlforge-0.0.13/forge/ir/lower.py +904 -0
- damlforge-0.0.13/forge/ir/nodes.py +399 -0
- damlforge-0.0.13/forge/ir/normalize.py +853 -0
- damlforge-0.0.13/forge/models/__init__.py +53 -0
- damlforge-0.0.13/forge/models/decorators.py +48 -0
- damlforge-0.0.13/forge/models/error_codes.py +53 -0
- damlforge-0.0.13/forge/models/types.py +30 -0
- damlforge-0.0.13/forge/semantics/__init__.py +40 -0
- damlforge-0.0.13/forge/semantics/analysis/__init__.py +14 -0
- damlforge-0.0.13/forge/semantics/analysis/imports.py +453 -0
- damlforge-0.0.13/forge/semantics/analysis/intrinsics.py +480 -0
- damlforge-0.0.13/forge/semantics/analysis/module.py +360 -0
- damlforge-0.0.13/forge/semantics/analysis/primitive_values.py +320 -0
- damlforge-0.0.13/forge/semantics/analysis/structure.py +767 -0
- damlforge-0.0.13/forge/semantics/analysis/typecheck.py +947 -0
- damlforge-0.0.13/forge/semantics/analysis/types.py +1234 -0
- damlforge-0.0.13/forge/semantics/primitive_specs.py +277 -0
- damlforge-0.0.13/forge/stubgen/__init__.py +78 -0
- damlforge-0.0.13/forge/stubgen/dar.py +86 -0
- damlforge-0.0.13/forge/stubgen/exports.py +46 -0
- damlforge-0.0.13/forge/stubgen/lf2.py +88 -0
- damlforge-0.0.13/forge/stubgen/parties.py +128 -0
- damlforge-0.0.13/forge/stubgen/render.py +571 -0
- damlforge-0.0.13/forge/utils.py +713 -0
- damlforge-0.0.13/forge/version.py +4 -0
- damlforge-0.0.13/forge/warnings.py +75 -0
- damlforge-0.0.13/make.cmd +77 -0
- damlforge-0.0.13/pyproject.toml +140 -0
- damlforge-0.0.13/quicktest.sh +18 -0
- damlforge-0.0.13/setup.cfg +19 -0
- damlforge-0.0.13/setup.py +99 -0
- damlforge-0.0.13/tests/ast/test_call_dict_arg.py +54 -0
- damlforge-0.0.13/tests/ast/test_container_keywords.py +190 -0
- damlforge-0.0.13/tests/builtins/test_daml_lang.py +705 -0
- damlforge-0.0.13/tests/codegen/test_source_map.py +115 -0
- damlforge-0.0.13/tests/compiler/test_codegen.py +594 -0
- damlforge-0.0.13/tests/compiler/test_codegen_examples.py +151 -0
- damlforge-0.0.13/tests/compiler/test_contract_keys.py +132 -0
- damlforge-0.0.13/tests/compiler/test_daml_versions.py +65 -0
- damlforge-0.0.13/tests/compiler/test_diagnostics.py +34 -0
- damlforge-0.0.13/tests/compiler/test_fuzz_crash_regressions.py +400 -0
- damlforge-0.0.13/tests/compiler/test_loop_report_regressions.py +224 -0
- damlforge-0.0.13/tests/compiler/test_self_mutation.py +172 -0
- damlforge-0.0.13/tests/examples/test_token_standard.py +93 -0
- damlforge-0.0.13/tests/ir/test_lower.py +905 -0
- damlforge-0.0.13/tests/ir/test_lower_examples.py +53 -0
- damlforge-0.0.13/tests/models/test_containers.py +89 -0
- damlforge-0.0.13/tests/models/test_decorators.py +102 -0
- damlforge-0.0.13/tests/models/test_types.py +45 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/as_import_not_allowed.vy +12 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/bytes_type_not_allowed.vy +7 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/choice_all_underscore_name_not_allowed.vy +10 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/choice_double_leading_underscore_name_not_allowed.vy +10 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/choice_leading_underscore_name_not_allowed.vy +10 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/choice_missing_consuming.vy +10 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/choice_missing_controller.vy +10 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/choice_name_with_no_letter_not_allowed.vy +10 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/choice_non_literal_consuming.vy +10 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/choice_observer_references_non_field_self_attribute_not_allowed.vy +10 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/choice_observer_references_unrelated_choice_arg_not_allowed.vy +15 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/choice_postconsuming_on_instance.vy +22 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/choice_preconsuming_on_interface.vy +8 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/complex_type_not_allowed.vy +7 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/create_used_without_import_not_allowed.vy +11 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/daml_name_with_no_arguments_not_allowed.vy +12 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/daml_name_with_non_literal_argument_not_allowed.vy +12 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/decorator_used_without_import_not_allowed.vy +10 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/dict_type_not_allowed.vy +7 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/double_imports_not_allowed.vy +13 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/enum_member_lowercase_not_allowed.vy +12 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/enum_member_mixed_case_not_allowed.vy +12 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/enum_member_value_not_allowed.vy +5 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/enum_value_access_unknown_member.vy +16 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/exercise_by_key_without_template_not_allowed.vy +20 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/function_call_with_incompatible_argument_type_not_allowed.vy +15 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/function_call_with_mismatched_list_element_type_not_allowed.vy +17 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/function_call_with_wrong_argument_count_not_allowed.vy +14 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/hidden_ledger_effect.vy +9 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/hidden_ledger_effect_top_level.vy +16 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/ledger_effect_with_args.vy +9 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/missing_import.vy +10 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/multiple_violations.vy +11 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/recursion_single_func.vy +22 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/self_reference_via_template_name_not_allowed.vy +11 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/template_choice_and_method_same_name.vy +18 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/template_duplicate_reserved_declarations.vy +15 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/template_empty_observer.vy +13 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/template_empty_signatory.vy +12 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/template_ensure_arithmetic_expression.vy +8 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/template_ensure_non_boolean_literal.vy +8 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/template_ensure_without_value.vy +7 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/template_key_without_annotation_not_allowed.vy +11 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/template_key_without_maintainer.vy +8 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/template_maintainer_from_field_not_allowed.vy +11 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/template_maintainer_without_key.vy +8 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/template_method_without_choice.vy +14 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/template_missing_signatory.vy +11 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/template_via_decorator_missing_signatory.vy +8 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/to_interface_contract_id_used_without_import_not_allowed.vy +20 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/unknown_decorator_not_allowed.vy +13 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/unknown_map_type_not_allowed.vy +7 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/unresolvable_bare_import_not_allowed.vy +12 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/unresolvable_import_not_allowed.vy +12 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/unresolved_name_used_as_attribute_base_not_allowed.vy +11 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/unresolved_name_used_as_call_target_not_allowed.vy +11 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/view_in_template.vy +10 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/view_used_without_import_not_allowed.vy +17 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/view_with_args.vy +8 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/visible_by_key_on_template_without_key_not_allowed.vy +13 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/wildcard_missing_import_not_allowed.vy +12 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/valid/choice_body_ledger_effect_is_allowed.vy +13 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/valid/choice_postconsuming_on_template_is_allowed.vy +13 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/valid/choice_preconsuming_on_template_is_allowed.vy +13 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/valid/choice_string_consuming_on_template_is_allowed.vy +13 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/valid/choice_with_observer_is_allowed.vy +13 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/valid/compatible_function_call_argument_types_are_allowed.vy +17 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/valid/contract_key_builtins_are_allowed.vy +55 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/valid/daml_name_overrides_choice_name_is_allowed.vy +14 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/valid/enum_value_access_is_allowed.vy +18 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/valid/frozenset_field_is_allowed.vy +9 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/valid/genmap_field_is_allowed.vy +9 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/valid/imported_ledger_builtins_are_allowed.vy +37 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/valid/interface_choice_controller_uses_view_is_allowed.vy +9 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/valid/known_builtin_and_struct_constructor_call_targets_are_allowed.vy +18 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/valid/ledger_effect_marked_is_allowed.vy +12 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/valid/local_variable_used_as_attribute_base_is_allowed.vy +14 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/valid/self_reference_via_another_template_name_is_allowed.vy +23 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/valid/set_field_is_allowed.vy +9 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/valid/template_ensure_boolop_is_allowed.vy +11 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/valid/template_ensure_call_is_allowed.vy +11 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/valid/template_ensure_compare_is_allowed.vy +11 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/valid/template_key_with_maintainer_is_allowed.vy +12 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/valid/template_with_ellipsis.vy +13 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/valid/template_without_ensure_is_allowed.vy +9 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/valid/template_without_key_or_maintainer_is_allowed.vy +9 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/valid/textmap_field_is_allowed.vy +10 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/valid/valid_template.vy +13 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/valid/valid_template_via_decorator.vy +13 -0
- damlforge-0.0.13/tests/semantics/fixtures/structure/valid/view_in_interface_is_allowed.vy +11 -0
- damlforge-0.0.13/tests/semantics/fixtures/type_annotations/invalid/choice_arg_unknown_type.vy +11 -0
- damlforge-0.0.13/tests/semantics/fixtures/type_annotations/invalid/choice_return_unknown_type.vy +11 -0
- damlforge-0.0.13/tests/semantics/fixtures/type_annotations/invalid/function_arg_unknown_type.vy +3 -0
- damlforge-0.0.13/tests/semantics/fixtures/type_annotations/invalid/interface_view_unknown_type.vy +3 -0
- damlforge-0.0.13/tests/semantics/fixtures/type_annotations/invalid/nested_generic_unknown_type.vy +9 -0
- damlforge-0.0.13/tests/semantics/fixtures/type_annotations/invalid/struct_field_unknown_type.vy +3 -0
- damlforge-0.0.13/tests/semantics/fixtures/type_annotations/invalid/template_field_unknown_type.vy +7 -0
- damlforge-0.0.13/tests/semantics/fixtures/type_annotations/valid/generic_field_types_are_allowed.vy +8 -0
- damlforge-0.0.13/tests/semantics/fixtures/type_annotations/valid/local_struct_reference_is_allowed.vy +7 -0
- damlforge-0.0.13/tests/semantics/fixtures/type_annotations/valid/primitive_field_types_are_allowed.vy +11 -0
- damlforge-0.0.13/tests/semantics/test_primitive_policies.py +150 -0
- damlforge-0.0.13/tests/semantics/test_structure.py +378 -0
- damlforge-0.0.13/tests/semantics/test_type_annotations.py +79 -0
- damlforge-0.0.13/tests/semantics/test_type_checking.py +194 -0
- damlforge-0.0.13/tests/stubgen/test_lf2.py +100 -0
- damlforge-0.0.13/tests/test_utils.py +26 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: damlforge-vy-lang
|
|
3
|
+
description: Use when writing, reading, or reviewing .vy source files in the DamlForge compiler (this repo) - a Python/Vyper-syntax DSL that compiles to real Daml/Canton smart contracts. Applies whenever asked to author a Daml template/choice/interface in .vy, translate a .daml file to .vy, or explain DF12xx compiler errors.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# DamlForge .vy Language
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
DamlForge compiles `.vy` files (Python syntax, Vyper-flavored keywords) into real `.daml` source. It is NOT Vyper (no EVM/gas/storage concepts survive) and NOT Python (nothing executes - it's an AST that lowers straight to Daml). Full detail: [reference.md](reference.md).
|
|
11
|
+
|
|
12
|
+
## Current project workflow
|
|
13
|
+
|
|
14
|
+
- Use `python -m forge daml <file-or-directory> -o <directory>` for source generation. A file input produces one `.daml` file and a `.map.json` source map; a directory input covers only `.vy` files directly in that directory.
|
|
15
|
+
- Use `python -m forge dar <project-directory> -o <file.dar>` for a real package build. The project must already have a valid `daml.yaml`; DamlForge recursively compiles `.vy` files below its `source` directory and then invokes DPM.
|
|
16
|
+
- Use `python -m forge stubs <file.dar> -o <directory>` to reconstruct supported declarations as `.vy`. Stub generation requires `pip install 'damlforge[stubgen]'`; a project directory can be supplied instead of a DAR and will be built with DPM.
|
|
17
|
+
- Use `daml test --all` when test coverage must include templates and choices imported from data-dependency DARs. Plain `daml test` can report only the package-local definitions.
|
|
18
|
+
- DPM is resolved from `PATH`, then `~/.dpm/bin/dpm`; pass `--dpm PATH` when necessary. Add `--traceback` while diagnosing compiler failures. `forge daml --no-i` makes the default error-tolerant multi-file compile fail on the first error.
|
|
19
|
+
|
|
20
|
+
## Before writing any .vy file
|
|
21
|
+
|
|
22
|
+
1. Every field/type name in the file must resolve to one of: a Python-native type (including `date`, `datetime`, and `timedelta` imported from Python's `datetime` module), a DamlForge builtin type (`Party`, `Decimal`, `Int`, `ContractId[T]`, `GenMap[K,V]`, `TextMap[T]`), or a `struct`/`template`/`interface`/`flag`/`variant` declared/imported in scope. See reference.md § Type System.
|
|
23
|
+
2. Function and method decorators (`@choice`, `@view`, `@variant_record`, `@DamlName`) must be imported from `forge.models` or `forge.builtins`. The `@template` and `@variant` class markers must be imported from `forge.models` too. Ledger operations (`create`, `fetch`, `exercise`, `archive`, the by-key functions, interface conversions) must be imported from `forge.builtins.daml_lang`. See reference.md § Decorators and § Ledger primitives.
|
|
24
|
+
3. Every `template` needs `signatory`. `key` requires `maintainer` and vice versa; `key` needs a type annotation, `maintainer` is computed from `key` only (`DF1236`), and keys need SDK 3.5 with `--target=2.3` (`DF1234`). Annotate the result of `fetch_by_key`/`lookup_by_key`/`lookup_all_by_key`/`lookup_n_by_key` so Daml can infer the template; `exercise_by_key(T, key, T.Choice(...))` and `visible_by_key(T, key)` take the template first (`DF1235`). `ensure` (if present) must be a `bool`-typed comparison/boolop/call, never bare arithmetic. See reference.md § Template Fields.
|
|
25
|
+
4. Daml update effects are inferred automatically from calls to `fetch`/`exercise`/`create`/`archive`/`*_by_key` and from transitive calls to functions containing those operations. Choices are already update contexts. See reference.md § Ledger Effects.
|
|
26
|
+
5. Never put a `def` inside a `struct` - it is silently dropped, no error. Use a free top-level function instead.
|
|
27
|
+
|
|
28
|
+
Generated stubs may also contain `@no_derive` from `forge.builtins` when the DAR
|
|
29
|
+
does not expose the equality/show instances needed for normal DamlForge derivation.
|
|
30
|
+
Keep that marker when editing a generated stub unless you intentionally want to
|
|
31
|
+
change the generated Daml derivations.
|
|
32
|
+
|
|
33
|
+
## Quick Reference
|
|
34
|
+
|
|
35
|
+
| Concept | `.vy` syntax |
|
|
36
|
+
|---|---|
|
|
37
|
+
| Record type | `struct Foo:` |
|
|
38
|
+
| Contract type | `@template\nclass Foo:` |
|
|
39
|
+
| Interface | `interface Foo(view=FooView):` |
|
|
40
|
+
| Interface impl | `@template\nclass Bar(Foo):` (subclass the interface directly - no `instance` keyword) |
|
|
41
|
+
| Payload variant | `@variant\nclass Result:\n def Ok(value: int): pass` |
|
|
42
|
+
| Named-field variant constructor | `@variant_record` on a constructor method; emits Daml `Constructor with ...` |
|
|
43
|
+
| Payload-free enum | `flag Status:\n PENDING\n PAID` (members MUST be `SCREAMING_CASE`) |
|
|
44
|
+
| Choice | `@choice(controller=..., consuming=True)` |
|
|
45
|
+
| Fetch/exercise/create/archive | `from forge.builtins.daml_lang import create, fetch, ...` - required, `DF1219` otherwise |
|
|
46
|
+
| Optional field | `Optional[X]` - never write `Some(...)`/`from_some(...)` yourself, the compiler inserts it |
|
|
47
|
+
| Current ledger time | `datetime.now()` from Python's `datetime`; DamlForge infers the enclosing function as an update |
|
|
48
|
+
| Calendar date | `date(year, month, day)` from Python's `datetime`; integer months are `1..12` |
|
|
49
|
+
| Date and time | `datetime.combine(date_value, time(hour, minute, second))`; lowers to `DA.Time.time` |
|
|
50
|
+
| Add relative time | `timestamp + timedelta(...)`; lowers to `DA.Time.addRelTime` |
|
|
51
|
+
| Time difference | `later - earlier`; typed datetimes lower to `DA.Time.subTime` |
|
|
52
|
+
| Unix timestamp | `datetime.fromtimestamp(seconds, timezone.utc)`; lowers to `DA.Time.fromUnixMicroseconds` |
|
|
53
|
+
| Relative time | `timedelta(days=..., hours=...)` from Python's `datetime`; lowers to `DA.Time` |
|
|
54
|
+
| Map | `GenMap[K, V]` / `TextMap[V]`, dict literal `{...}`, `m[k]`, `k in m` |
|
|
55
|
+
| Typed for-loop | `for x: T in xs:` (annotation is optional when the iterable type is known) |
|
|
56
|
+
|
|
57
|
+
For date/time values, import Python's standard types directly:
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
from datetime import date, datetime, time, timedelta, timezone
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Never import `Date`, `Timestamp`, or `RelTime` from `forge.models`. They are
|
|
64
|
+
represented by `date`, `datetime`, and `timedelta`. Use `datetime.now()` only
|
|
65
|
+
in Daml update contexts. See reference.md § Type System for constructors,
|
|
66
|
+
arithmetic, and Unix timestamp conversion.
|
|
67
|
+
|
|
68
|
+
## Common Mistakes
|
|
69
|
+
|
|
70
|
+
| Mistake | Fix |
|
|
71
|
+
|---|---|
|
|
72
|
+
| Using `@template`/`@variant`/`@choice`/`@view`/`@variant_record` without importing it | Import it from `forge.models` (`DF1219` otherwise) |
|
|
73
|
+
| Calling `create`/`fetch`/`exercise`/`to_interface_contract_id`/... without importing it | Import it from `forge.builtins.daml_lang` (`DF1219` otherwise); only `len`/`range`/`ceil`/`floor` are import-free |
|
|
74
|
+
| Using `@variant_record` for every constructor | Use it only for Daml named-field (`with`) constructors; omit it for positional constructors |
|
|
75
|
+
| Calling a custom `days(...)` helper | Import `timedelta` from `datetime` and use `timedelta(days=...)`; `years=` is not a Python or Daml fixed-duration unit |
|
|
76
|
+
| Writing `def helper(): ...` inside a `struct` | Move it to a top-level `def`; structs are plain data records |
|
|
77
|
+
| `controller=`/`observer=` referencing a name that isn't a with-arg, a template field, or `self.<field>` | Only reference the choice's own arguments/fields - anything else either resolves to an unrelated same-named field or fails `damlc` with "Ambiguous occurrence" (`DF1224`) |
|
|
78
|
+
| `key` without `maintainer` (or vice versa) | Always declare both together (`DF1210`/`DF1211`) |
|
|
79
|
+
| A bare `def` calling `archive(self)`/`fetch(...)` etc. | No marker is needed; DamlForge infers the function as an update |
|
|
80
|
+
| `from X import Y as Z` | Aliased from-imports are banned; use `import X as Y` (module alias) instead if disambiguation is needed |
|
|
81
|
+
| `dict[K, V]` or a hand-rolled `Map[...]` field | Use `GenMap[K, V]` / `TextMap[V]` |
|
|
82
|
+
|
|
83
|
+
Full syntax, decorator/builtin tables, type system, error-code index, and a worked example: [reference.md](reference.md).
|
|
@@ -0,0 +1,445 @@
|
|
|
1
|
+
# DamlForge `.vy` Language Reference
|
|
2
|
+
|
|
3
|
+
`.vy` files are tokenized Python, re-keyworded by a pre-parser, then lowered straight to Daml source (`forge/ir`, `forge/codegen`). There is no runtime: nothing in a `.vy` file is ever executed by Python. Compile with:
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
python -m forge daml <file_or_dir> -o <out_dir> # .vy -> .daml
|
|
7
|
+
python -m forge dar <project_dir> -o <out.dar> # .vy -> .daml -> real .dar via dpm build
|
|
8
|
+
python -m forge json <file> # .vy -> JSON AST (or read stdin)
|
|
9
|
+
python -m forge stubs <file.dar> -o <out_dir> # DAR -> supported .vy declarations
|
|
10
|
+
# `python -m forge <file_or_dir> -o <out_dir>` (no subcommand) is shorthand for `daml`
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
`forge daml` writes both `<Module>.daml` and `<Module>.map.json`. Directory input
|
|
14
|
+
compiles only `.vy` files directly in that directory. `forge dar` requires an existing
|
|
15
|
+
Daml project with `daml.yaml` fields `name`, `source`, `version`, and a non-empty
|
|
16
|
+
`dependencies` list; it recursively compiles `.vy` files below `source`, writes the
|
|
17
|
+
generated `.daml` files into that source tree, and runs `dpm build`. DPM is resolved
|
|
18
|
+
from `PATH`, then `~/.dpm/bin/dpm`, or can be supplied with `--dpm PATH`.
|
|
19
|
+
|
|
20
|
+
Use `forge daml --no-i` to fail on the first file error instead of continuing with
|
|
21
|
+
the remaining files. Use `--traceback` on any command for the Python traceback.
|
|
22
|
+
|
|
23
|
+
Stub generation accepts a DAR or a Daml project directory. It requires the optional
|
|
24
|
+
`damlforge[stubgen]` extra (for Daml-LF decoding), and `--module MODULE` may be repeated
|
|
25
|
+
to select modules from the main package or any dependency. Unsupported declarations
|
|
26
|
+
are skipped and reported.
|
|
27
|
+
|
|
28
|
+
For Daml tests that need coverage from data-dependency packages, run `daml test --all`;
|
|
29
|
+
the package-local test mode does not include those external definitions in its report.
|
|
30
|
+
|
|
31
|
+
## 1. Container keywords
|
|
32
|
+
|
|
33
|
+
The pre-parser translates these container forms into Python `class` declarations:
|
|
34
|
+
|
|
35
|
+
| `.vy` keyword | Compiles to | Real Daml shape |
|
|
36
|
+
|---|---|---|
|
|
37
|
+
| `struct Foo:` | plain data record | `data Foo = Foo with ...` |
|
|
38
|
+
| `@template` then `class Foo:` | contract template | `template Foo where ...` |
|
|
39
|
+
| `interface Foo(view=V):` | interface | `interface Foo where viewtype V` |
|
|
40
|
+
| `@template` then `class Foo(Bar):` | template implementing interface `Bar` | `template Foo with ... where ... interface instance Bar for Foo where ...` |
|
|
41
|
+
| `flag Foo:` / `enum Foo:` | sum type of nullary constructors | `data Foo = A \| B \| ...` |
|
|
42
|
+
| `@variant` then `class Foo:` | sum type with payload constructors | `data Foo = A Type \| B with ...` |
|
|
43
|
+
|
|
44
|
+
`@template\nclass Foo:` is the only template spelling; bare `template Foo:` is not supported. Likewise, `@variant\nclass Foo:` is the only spelling for a payload variant. Neither class marker needs an import because the pre-parser consumes it before decorator-name analysis. No other decorator combination with bare `class` is legal - plain `class Foo:` and `@anything_else\nclass Foo:` both raise a hard `SyntaxException` at tokenize time.
|
|
45
|
+
|
|
46
|
+
`struct`/`interface`/`event`/`enum` (but not `template`/`flag`) are also reserved identifiers - you cannot name a variable or field `struct`, etc. There is no `instance` keyword - a template declares which interface(s) it implements directly via base classes, like real Python subclassing/ABCs (see §11).
|
|
47
|
+
|
|
48
|
+
`event`/`error` (`EventDef`/`ErrorDef`) parse but are not wired into codegen; the `exception` decorator explicitly raises `NotImplementedError` - none of these three are usable yet.
|
|
49
|
+
|
|
50
|
+
## 2. Type system
|
|
51
|
+
|
|
52
|
+
**Native Python types - always available, no import:** `str`, `int`, `float`, `bool`, `None`, `list[T]`, `tuple[T, ...]`, `set[T]`, `frozenset[T]`. `Optional[T]` needs `from typing import Optional` for the file to remain valid-looking Python, but the compiler itself doesn't require the import.
|
|
53
|
+
|
|
54
|
+
**DamlForge builtin types - recognized unconditionally by the type checker, but conventionally still imported from `forge.models` for readability:** `Party`, `Decimal`, `Int` (a distinct `Int` for real Daml `Int`, vs. Python `int`), `ContractId[T]`, `GenMap[K, V]`, `TextMap[V]`.
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
from datetime import datetime
|
|
58
|
+
|
|
59
|
+
from forge.models import ContractId, Decimal, Optional, Party, TextMap, choice
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**Banned field types:** `dict[...]` and any unrecognized generic like `Map[...]` (`DF1213` - use `GenMap`/`TextMap`), and `bytes`/`bytearray`/`memoryview`/`complex`/`type`/`object`/`slice` (`DF1222` - no Daml equivalent).
|
|
63
|
+
|
|
64
|
+
**Type synonyms the checker treats as equal** when checking call-argument compatibility: `int`↔`Int`, `str`↔`Text`, `float`↔`Decimal`. A bare `X` is compatible where `Optional[X]` is expected (auto-wrapped, see §6). Generic args are checked recursively - `list[A]` is never compatible with `list[B]` unless `A`/`B` match.
|
|
65
|
+
|
|
66
|
+
**Your own types**: any `struct`/`template`/`interface`/`flag` declared in a reachable module is automatically a valid type name - no import needed within the same module, real `from X import Y` needed across `.vy` files.
|
|
67
|
+
|
|
68
|
+
Python's `datetime`, `date`, and `timedelta` map to Daml `Time`, `Date`, and
|
|
69
|
+
`RelTime`:
|
|
70
|
+
|
|
71
|
+
```python
|
|
72
|
+
from datetime import date, datetime, time, timedelta, timezone
|
|
73
|
+
def current_time() -> datetime:
|
|
74
|
+
return datetime.now()
|
|
75
|
+
|
|
76
|
+
def epoch() -> date:
|
|
77
|
+
return date(1970, 1, 1)
|
|
78
|
+
|
|
79
|
+
def start_of_epoch() -> datetime:
|
|
80
|
+
return datetime.combine(epoch(), time())
|
|
81
|
+
|
|
82
|
+
def cooldown(months: int) -> timedelta:
|
|
83
|
+
return timedelta(days=30 * months, hours=12)
|
|
84
|
+
|
|
85
|
+
def deadline(start: datetime) -> datetime:
|
|
86
|
+
return start + timedelta(days=7)
|
|
87
|
+
|
|
88
|
+
def elapsed(later: datetime, earlier: datetime) -> timedelta:
|
|
89
|
+
return later - earlier
|
|
90
|
+
|
|
91
|
+
def from_seconds(seconds: int) -> datetime:
|
|
92
|
+
return datetime.fromtimestamp(seconds, timezone.utc)
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
`datetime.now()` lowers to the Daml update operation `getTime`; DamlForge
|
|
96
|
+
automatically infers the enclosing function as an update. `date(...)` accepts
|
|
97
|
+
Python's integer month numbering (`1` through `12`) and automatically imports
|
|
98
|
+
`DA.Date`. `datetime.combine(date_value, time(...))` lowers to DAML's pure
|
|
99
|
+
`DA.Time.time`; a standalone `time(...)` has no DAML equivalent.
|
|
100
|
+
|
|
101
|
+
Adding a `timedelta` to a `datetime` uses normal Python arithmetic and lowers to
|
|
102
|
+
DAML `addRelTime`; subtracting two datetimes lowers to `subTime`.
|
|
103
|
+
`datetime.fromtimestamp(...)` requires an explicit `timezone.utc` and lowers
|
|
104
|
+
seconds to DAML's microsecond-based `fromUnixMicroseconds`.
|
|
105
|
+
|
|
106
|
+
The compiler supports Python's fixed units: `weeks`, `days`, `hours`, `minutes`,
|
|
107
|
+
`seconds`, `milliseconds`, and `microseconds`. Weeks lower to seven days. Python
|
|
108
|
+
does not support `years=` because a calendar year is not a fixed duration; use
|
|
109
|
+
explicit date/calendar logic when that distinction matters.
|
|
110
|
+
|
|
111
|
+
**Qualified module imports** - use when two real Daml packages export a same-named type (Daml itself would raise "Ambiguous occurrence" on an unqualified double-import):
|
|
112
|
+
|
|
113
|
+
```python
|
|
114
|
+
import Splice.Api.FeaturedAppRightV1 as FeaturedAppRightV1
|
|
115
|
+
import Splice.Api.FeaturedAppRightV2 as FeaturedAppRightV2
|
|
116
|
+
...
|
|
117
|
+
def f(x: FeaturedAppRightV1.FeaturedAppRight): ...
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
`from X import Y as Z` (aliased *from*-import) is banned outright, as is `from X import *`, importing the same name twice, and importing a module/name that doesn't actually resolve - all raise `DF1213`.
|
|
121
|
+
|
|
122
|
+
## 3. Decorators
|
|
123
|
+
|
|
124
|
+
Function and method decorators are ordinary Python objects and must be imported before use. An unimported decorator fails like any other unresolved name (`DF1219`, "not defined"). This includes the `@template` and `@variant` class markers, which are imported from `forge.models`.
|
|
125
|
+
|
|
126
|
+
```python
|
|
127
|
+
from forge.models import choice, variant_record, view
|
|
128
|
+
from forge.builtins import DamlName
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
| Decorator | Where legal | Rules |
|
|
132
|
+
|---|---|---|
|
|
133
|
+
| `@choice(controller=..., consuming=..., observer=...)` | method inside `template`/`interface` | `controller` required (`DF1203`); `consuming` required, must be a literal `True`/`False` or one of `"preconsuming"`/`"consuming"`/`"nonconsuming"`/`"postconsuming"` (`DF1203`); name can't start with `_` (`DF1218`); `"preconsuming"`/`"postconsuming"` banned on interface choice declarations, and on a template's implementation of an interface choice (`DF1208`) |
|
|
134
|
+
| `@view` | method inside `interface`, or a `template` that implements one | no args (`DF1206`); banned inside a `template` with no interface bases (`DF1207`) |
|
|
135
|
+
| `@variant_record` | constructor method inside an `@variant` class | bare only; emits a named-field Daml constructor using `with` instead of a positional payload |
|
|
136
|
+
| `@DamlName("RealName")` | any function/choice | exactly one string-literal positional arg (`DF1221`); overrides the auto-derived Daml-side name |
|
|
137
|
+
| `@template` | immediately before `class Foo:`, nothing else | class marker imported from `forge.models`; see §1 |
|
|
138
|
+
| `@variant` | immediately before `class Foo:`, nothing else | class marker imported from `forge.models`; see §1 and §9 |
|
|
139
|
+
|
|
140
|
+
### `controller=`/`observer=` name rules (`DF1224`)
|
|
141
|
+
|
|
142
|
+
Every bare name inside a choice's `controller=`/`observer=` expression must be one of: that choice's own `with`-arguments, one of the template's own declared fields, or `self`. `self.<attr>` is further checked to be a real field (not `self.signatory` - `signatory` is a Daml typeclass function, not a stored field). This exists because Daml's own name resolution would otherwise silently pick an unrelated same-named field elsewhere in the module, or fail with a confusing `damlc`-time "Ambiguous occurrence" error. This check runs for `template` choices, including a template's implementation of an interface choice (since it lives directly in the template body and has real field access) - a bare `interface`'s own abstract choice declarations are skipped (they have no fields, no `self`, only their own with-arguments).
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
@choice(controller=owner, consuming=True) # owner: template field - OK
|
|
146
|
+
def transfer(self, new_owner: Party) -> bool: ...
|
|
147
|
+
|
|
148
|
+
@choice(controller=owner, consuming=True, observer=new_owner) # new_owner is `transfer`'s
|
|
149
|
+
def rename(self, label: str) -> bool: ... # arg, not `rename`'s - DF1224
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## 4. Ledger primitives - must be imported
|
|
153
|
+
|
|
154
|
+
`fetch`, `exercise`, `create`, `archive`, `lookup_by_key`, `fetch_by_key`, `exercise_by_key`, `visible_by_key`, `lookup_n_by_key`, `lookup_all_by_key`, `view` (interface view extraction, distinct from the `@view` decorator), `from_interface_contract_id`, `to_interface_contract_id`, `to_interface`, `coerce_interface_contract_id`, `stakeholder`, `error`, `reverse` (every `@DamlName` function in `forge/builtins/daml_lang.py`) must be imported from `forge.builtins.daml_lang`. Calling one without importing it fails with `DF1219` ("not defined"). Only `len`/`range`/`ceil`/`floor` are import-free.
|
|
155
|
+
|
|
156
|
+
```python
|
|
157
|
+
from forge.builtins.daml_lang import fetch
|
|
158
|
+
|
|
159
|
+
def f(cid: ContractId[Asset]) -> Asset:
|
|
160
|
+
return fetch(cid)
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Inside an `interface` body, a bare `view` in `controller=`/`observer=` (for example `controller=view.provider`) is the interface's own view value, bound by the compiler like `self`. It needs no import.
|
|
164
|
+
|
|
165
|
+
### Ledger-effect inference
|
|
166
|
+
|
|
167
|
+
DamlForge automatically infers a plain function as an update when its body
|
|
168
|
+
calls an update operation such as `fetch`, `exercise`, `create`, `archive`, or
|
|
169
|
+
`fetch_by_key`. The inference is transitive, so a function that calls another
|
|
170
|
+
inferred update function is also emitted with an update return type:
|
|
171
|
+
|
|
172
|
+
```python
|
|
173
|
+
def replace(new_owner: Party) -> bool:
|
|
174
|
+
archive(self)
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
```python
|
|
178
|
+
def move(new_owner: Party) -> bool:
|
|
179
|
+
replace(new_owner) # also inferred as an update
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Choice bodies are already update contexts and may call ledger operations
|
|
183
|
+
directly. Imported Daml update helpers and declaration-only stubs carry
|
|
184
|
+
compiler metadata so inference can recognize them even though their `.vy`
|
|
185
|
+
declarations have no body to inspect.
|
|
186
|
+
|
|
187
|
+
## 5. Template fields
|
|
188
|
+
|
|
189
|
+
```python
|
|
190
|
+
@template
|
|
191
|
+
class Asset:
|
|
192
|
+
owner: Party
|
|
193
|
+
asset_id: Text
|
|
194
|
+
|
|
195
|
+
signatory: list[Party] = [owner] # required (DF1201 if missing)
|
|
196
|
+
observer: list[Party] = [...] # optional
|
|
197
|
+
key: tuple[Party, Text] = (owner, asset_id) # optional, but...
|
|
198
|
+
maintainer: list[Party] = [owner] # ...requires key, and vice versa (DF1210/DF1211)
|
|
199
|
+
ensure: bool = amount > Decimal(0) # optional; must be bool-typed comparison/boolop/call
|
|
200
|
+
# (not bare arithmetic, not missing a value - DF1212)
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
`signatory`/`observer`/`key`/`maintainer`/`ensure` are special clause names, not ordinary fields - don't reference them via `self.signatory` etc. in choice logic (the compiler flags this as `DF1224`).
|
|
204
|
+
|
|
205
|
+
## 6. `Optional`, `Some`, auto-unwrapping
|
|
206
|
+
|
|
207
|
+
Never write `Some(...)` or `from_some(...)` by hand. Based on a field/return's declared `Optional[X]` type, the compiler automatically wraps a plain `X` value into `Some(X)` on assignment/return, and unwraps `Optional[X]` into `X` where a plain `X` is required. Just write the plain values:
|
|
208
|
+
|
|
209
|
+
```python
|
|
210
|
+
lock: Optional[Lock] = None
|
|
211
|
+
...
|
|
212
|
+
return HoldingView(..., lock=None, ...) # compiler emits `None`
|
|
213
|
+
return HoldingView(..., lock=existing_lock, ...) # if existing_lock: Lock, compiler emits `Some existing_lock`
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## 7. Maps
|
|
217
|
+
|
|
218
|
+
```python
|
|
219
|
+
from forge.models import GenMap, TextMap
|
|
220
|
+
|
|
221
|
+
balances: GenMap[Party, Decimal] = {alice: Decimal(0), bob: Decimal(0)}
|
|
222
|
+
values: TextMap[str] = {}
|
|
223
|
+
|
|
224
|
+
balances[alice] # lookup
|
|
225
|
+
balances[alice] = Decimal(5) # insert/update
|
|
226
|
+
alice in balances # membership
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
`GenMap`/`TextMap` also expose `.insert(k, v)`, `.lookup(k)`, `.member(k)`, `.delete(k)`, `.keys()`, `.values()` if you prefer explicit method calls over subscript/`in` sugar.
|
|
230
|
+
|
|
231
|
+
## 8. Flags (sum types)
|
|
232
|
+
|
|
233
|
+
```python
|
|
234
|
+
flag PeriodPaymentStatus:
|
|
235
|
+
PERIOD_PENDING
|
|
236
|
+
PERIOD_PAID
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
Members **must** be `SCREAMING_CASE` (`DF1217` on lowercase or mixed case). Access via `PeriodPaymentStatus.PERIOD_PAID`, compare with `==`/`!=`. Flags have no payload and no methods.
|
|
240
|
+
|
|
241
|
+
## 9. Variants (payload sum types)
|
|
242
|
+
|
|
243
|
+
Use `@variant` when constructors carry values. Each method declares a
|
|
244
|
+
constructor and its parameters declare the payload:
|
|
245
|
+
|
|
246
|
+
```python
|
|
247
|
+
from datetime import datetime
|
|
248
|
+
|
|
249
|
+
from forge.models import Party, variant_record
|
|
250
|
+
|
|
251
|
+
@variant
|
|
252
|
+
class Result:
|
|
253
|
+
def Accepted(value: Party): pass
|
|
254
|
+
def Cancelled(): pass
|
|
255
|
+
|
|
256
|
+
@variant_record
|
|
257
|
+
def Deferred(reason: str, retry_at: datetime): pass
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
This generates:
|
|
261
|
+
|
|
262
|
+
```daml
|
|
263
|
+
data Result
|
|
264
|
+
= Accepted Party
|
|
265
|
+
| Cancelled
|
|
266
|
+
| Deferred with
|
|
267
|
+
reason : Text
|
|
268
|
+
retry_at : Time
|
|
269
|
+
deriving (Eq, Show, Serializable)
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
An ordinary constructor method is positional: its parameter names are not part
|
|
273
|
+
of the generated Daml API. Mark a constructor with `@variant_record` when the
|
|
274
|
+
original Daml shape uses named `with` fields and those field names must be
|
|
275
|
+
preserved. This distinction applies even to a single-field constructor. A
|
|
276
|
+
constructor with no parameters needs no `@variant_record`.
|
|
277
|
+
|
|
278
|
+
Constructor methods are declarations only and should have `pass` bodies.
|
|
279
|
+
`@variant` and `@variant_record` must both be imported from
|
|
280
|
+
`forge.models`.
|
|
281
|
+
|
|
282
|
+
## 10. Structs
|
|
283
|
+
|
|
284
|
+
Plain data records - fields only:
|
|
285
|
+
|
|
286
|
+
```python
|
|
287
|
+
struct InstrumentId:
|
|
288
|
+
admin: Party
|
|
289
|
+
id: str
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
**No methods.** A `def` inside a `struct` body is currently silently dropped (no error raised) - this mirrors a real gap relative to Vyper, which explicitly rejects struct methods with `StructureException`. Treat "structs can't have methods" as a hard rule and use a free top-level `def` instead:
|
|
293
|
+
|
|
294
|
+
```python
|
|
295
|
+
def update_milestone_if_due(paid_amount: Decimal, milestone: RepaymentMilestone) -> RepaymentMilestone:
|
|
296
|
+
if milestone.paid or paid_amount < milestone.amount:
|
|
297
|
+
return milestone
|
|
298
|
+
return RepaymentMilestone(due_date=milestone.due_date, amount=milestone.amount,
|
|
299
|
+
paid=True, paid_date=milestone.paid_date)
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
## 11. Interfaces - a template implements one via real subclassing
|
|
303
|
+
|
|
304
|
+
There is no `instance` keyword. A `template` declares it implements an `interface` the same way Python declares a class implements an ABC - by listing it as a base:
|
|
305
|
+
|
|
306
|
+
```python
|
|
307
|
+
struct HoldingView:
|
|
308
|
+
owner: Party
|
|
309
|
+
|
|
310
|
+
interface Holding(view=HoldingView):
|
|
311
|
+
@choice(controller=actors, consuming="nonconsuming")
|
|
312
|
+
def withdraw(self, actors: list[Party], extra_args: ExtraArgs) -> bool:
|
|
313
|
+
pass # interface choices are declared once, with `pass` bodies
|
|
314
|
+
|
|
315
|
+
@template
|
|
316
|
+
class SimpleHolding(Holding):
|
|
317
|
+
owner: Party
|
|
318
|
+
issuer: Party
|
|
319
|
+
signatory: list[Party] = [owner, issuer]
|
|
320
|
+
|
|
321
|
+
@view
|
|
322
|
+
def get_view(self) -> HoldingView:
|
|
323
|
+
return HoldingView(owner=self.owner)
|
|
324
|
+
|
|
325
|
+
@choice(controller=actors, consuming="nonconsuming")
|
|
326
|
+
def withdraw(self, actors: list[Party], extra_args: ExtraArgs) -> bool:
|
|
327
|
+
... # real implementation - same field/self access as any other choice
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
Any method inside the template whose name matches one of the interface's own `@choice`-declared names is treated as that interface's implementation (not a separate template choice); everything else stays a normal template choice. A template can implement more than one interface (`@template` followed by `class Foo(A, B):`) - a `@view` method is matched to the right interface by its return type, so implementing two interfaces needs two `@view` methods, one per interface's declared `view=` type.
|
|
331
|
+
|
|
332
|
+
**Compile-time completeness check (`DF1228`)**: a template that lists an interface as a base must implement every one of that interface's `@choice`-declared members by name, and have exactly one `@view` method whose return type matches the interface's `view=` type - both are checked before codegen, not left to fail later inside `damlc`. The base itself must resolve to a real `interface` declaration (`DF1227` otherwise).
|
|
333
|
+
|
|
334
|
+
Under the hood, this compiles to Daml's real interface-choice-delegation mechanism: the `interface` emits the choice once plus an abstract "impl" method signature, and each implementing `template`'s `interface instance ... for ... where` block provides just that method's body - matching how real Daml (and the Splice token standard) actually structures this, not a per-template redeclared choice.
|
|
335
|
+
|
|
336
|
+
If you build interface+implementation in the same `.vy` module (the common case for a self-contained example), add `-Wno-upgrade-interfaces` to your project's `daml.yaml` `build-options` - real Daml warns-as-error about interfaces and implementations sharing a package, since it affects upgradability; this is a project-level Daml build setting, not something `.vy` can express.
|
|
337
|
+
|
|
338
|
+
## 12. Functions, loops, calls
|
|
339
|
+
|
|
340
|
+
Free top-level functions are plain `def`s; call-argument arity (`DF1225`) and type-compatibility (`DF1226`, only for `Name` arguments with a known declared type) are checked for any call to a known top-level `.vy` function.
|
|
341
|
+
|
|
342
|
+
Direct self-recursion is banned (`DF1209`) - a function/choice cannot call itself.
|
|
343
|
+
|
|
344
|
+
For-loops may include a type annotation on the loop variable before `in` (this is `.vy`-specific sugar the pre-parser slurps out, since bare PEP-526 annotations aren't legal there in real Python). The annotation is optional when the iterable type is known:
|
|
345
|
+
|
|
346
|
+
```python
|
|
347
|
+
for milestone: RepaymentMilestone in milestones:
|
|
348
|
+
...
|
|
349
|
+
for _index: int in range(0, count):
|
|
350
|
+
...
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
`len`, `range`, `ceil`, `floor` are always-available builtins (no import) and rename on the Daml side (`len`→`length`, `ceil`→`ceiling`; `floor`/`range` pass through).
|
|
354
|
+
|
|
355
|
+
## 13. Error code index
|
|
356
|
+
|
|
357
|
+
| Code | Meaning |
|
|
358
|
+
|---|---|
|
|
359
|
+
| DF1201 | template missing `signatory` |
|
|
360
|
+
| DF1203 | `@choice` missing `controller` or missing/invalid `consuming` |
|
|
361
|
+
| DF1206 | `@view` given arguments |
|
|
362
|
+
| DF1207 | `@view` used inside a `template` with no interface base |
|
|
363
|
+
| DF1208 | `"preconsuming"`/`"postconsuming"` on an interface choice declaration or implementation |
|
|
364
|
+
| DF1209 | direct self-recursion |
|
|
365
|
+
| DF1210 | `key` without `maintainer` |
|
|
366
|
+
| DF1211 | `maintainer` without `key` |
|
|
367
|
+
| DF1212 | `ensure` missing a value, or not a bool-typed comparison/boolop/call |
|
|
368
|
+
| DF1213 | import errors (wildcard, aliased from-import, duplicate, unresolvable) or a banned field type (`dict`, unknown map) |
|
|
369
|
+
| DF1216 | unknown flag member accessed |
|
|
370
|
+
| DF1217 | flag member not `SCREAMING_CASE` |
|
|
371
|
+
| DF1218 | choice name starts with `_` |
|
|
372
|
+
| DF1219 | name not defined / not in scope |
|
|
373
|
+
| DF1220 | unknown/unrecognized decorator |
|
|
374
|
+
| DF1221 | `@DamlName` given the wrong argument shape |
|
|
375
|
+
| DF1222 | field type with no Daml equivalent (`bytes`, `complex`, ...) |
|
|
376
|
+
| DF1224 | `controller=`/`observer=` references a name that isn't a with-arg/field/`self` |
|
|
377
|
+
| DF1225 | wrong argument count on a known function call |
|
|
378
|
+
| DF1226 | argument type incompatible with a known function's declared parameter type |
|
|
379
|
+
| DF1227 | a `template`'s interface base isn't a plain name, or doesn't resolve to a known `interface` |
|
|
380
|
+
| DF1228 | a `template` implementing an interface is missing a required choice or `@view` implementation |
|
|
381
|
+
|
|
382
|
+
## 14. Worked example
|
|
383
|
+
|
|
384
|
+
```python
|
|
385
|
+
from datetime import datetime
|
|
386
|
+
|
|
387
|
+
from forge.models import ContractId, Decimal, Optional, Party, TextMap, choice, view
|
|
388
|
+
from forge.builtins.daml_lang import archive, create
|
|
389
|
+
|
|
390
|
+
struct InstrumentId:
|
|
391
|
+
admin: Party
|
|
392
|
+
id: str
|
|
393
|
+
|
|
394
|
+
struct Metadata:
|
|
395
|
+
values: TextMap[str]
|
|
396
|
+
|
|
397
|
+
struct HoldingView:
|
|
398
|
+
owner: Party
|
|
399
|
+
instrument_id: InstrumentId
|
|
400
|
+
amount: Decimal
|
|
401
|
+
meta: Metadata
|
|
402
|
+
|
|
403
|
+
interface Holding(view=HoldingView):
|
|
404
|
+
pass
|
|
405
|
+
|
|
406
|
+
@template
|
|
407
|
+
class SimpleHolding(Holding):
|
|
408
|
+
owner: Party
|
|
409
|
+
issuer: Party
|
|
410
|
+
amount: Decimal
|
|
411
|
+
instrument_id: InstrumentId
|
|
412
|
+
|
|
413
|
+
signatory: list[Party] = [owner, issuer]
|
|
414
|
+
|
|
415
|
+
@view
|
|
416
|
+
def get_view(self) -> HoldingView:
|
|
417
|
+
return HoldingView(
|
|
418
|
+
owner=self.owner,
|
|
419
|
+
instrument_id=self.instrument_id,
|
|
420
|
+
amount=self.amount,
|
|
421
|
+
meta=Metadata(values={}),
|
|
422
|
+
)
|
|
423
|
+
|
|
424
|
+
@template
|
|
425
|
+
class PendingTransfer:
|
|
426
|
+
sender: Party
|
|
427
|
+
receiver: Party
|
|
428
|
+
amount: Decimal
|
|
429
|
+
instrument_id: InstrumentId
|
|
430
|
+
|
|
431
|
+
signatory: list[Party] = [sender]
|
|
432
|
+
observer: list[Party] = [receiver]
|
|
433
|
+
|
|
434
|
+
@choice(controller=receiver, consuming=True)
|
|
435
|
+
def accept(self) -> ContractId[SimpleHolding]:
|
|
436
|
+
assert self.amount > Decimal(0), "transfer amount must be positive"
|
|
437
|
+
return create(SimpleHolding(
|
|
438
|
+
owner=self.receiver,
|
|
439
|
+
issuer=self.sender,
|
|
440
|
+
amount=self.amount,
|
|
441
|
+
instrument_id=self.instrument_id,
|
|
442
|
+
))
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
Full source: `examples/token_standard/token_standard.vy` (verified against real `dpm build`). `examples/crowd_loans/` is the largest real example, exercising `flag`, `GenMap`, nested `for` loops, and cross-package Splice imports.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
name: Build wheel on tag
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- 'v*.*.*'
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: write
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
build:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
with:
|
|
17
|
+
fetch-depth: 0
|
|
18
|
+
fetch-tags: true
|
|
19
|
+
|
|
20
|
+
- uses: actions/setup-python@v5
|
|
21
|
+
with:
|
|
22
|
+
python-version: '3.12'
|
|
23
|
+
|
|
24
|
+
- name: Install build tooling
|
|
25
|
+
run: python -m pip install --upgrade pip build twine
|
|
26
|
+
|
|
27
|
+
- name: Build sdist and wheel
|
|
28
|
+
run: python -m build
|
|
29
|
+
|
|
30
|
+
- name: Verify package metadata
|
|
31
|
+
run: twine check dist/*
|
|
32
|
+
|
|
33
|
+
- name: Upload build artifact
|
|
34
|
+
uses: actions/upload-artifact@v4
|
|
35
|
+
with:
|
|
36
|
+
name: forge-${{ github.ref_name }}
|
|
37
|
+
path: dist/*
|
|
38
|
+
retention-days: 90
|
|
39
|
+
|
|
40
|
+
- name: Attach wheel to GitHub Release
|
|
41
|
+
env:
|
|
42
|
+
GH_TOKEN: ${{ github.token }}
|
|
43
|
+
run: |
|
|
44
|
+
gh release create "${{ github.ref_name }}" dist/* \
|
|
45
|
+
--repo "${{ github.repository }}" \
|
|
46
|
+
--title "${{ github.ref_name }}" \
|
|
47
|
+
--generate-notes \
|
|
48
|
+
|| gh release upload "${{ github.ref_name }}" dist/* \
|
|
49
|
+
--repo "${{ github.repository }}" \
|
|
50
|
+
--clobber
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
name: License header
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
pull_request:
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
license-check:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
|
|
18
|
+
- name: Check Apache-2.0 license headers
|
|
19
|
+
run: make license-check
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
inputs:
|
|
6
|
+
version:
|
|
7
|
+
description: 'Version to publish, for example 0.1.0'
|
|
8
|
+
required: true
|
|
9
|
+
type: string
|
|
10
|
+
|
|
11
|
+
permissions:
|
|
12
|
+
contents: read
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
build:
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
steps:
|
|
18
|
+
- name: Validate version
|
|
19
|
+
env:
|
|
20
|
+
VERSION: ${{ inputs.version }}
|
|
21
|
+
run: |
|
|
22
|
+
if ! echo "$VERSION" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+((a|b|rc)[0-9]+|\.post[0-9]+|\.dev[0-9]+)?$'; then
|
|
23
|
+
echo "Invalid PEP 440 version: $VERSION"
|
|
24
|
+
exit 1
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
- uses: actions/checkout@v4
|
|
28
|
+
with:
|
|
29
|
+
fetch-depth: 0
|
|
30
|
+
|
|
31
|
+
- uses: actions/setup-python@v5
|
|
32
|
+
with:
|
|
33
|
+
python-version: '3.12'
|
|
34
|
+
|
|
35
|
+
- name: Install build tooling
|
|
36
|
+
run: python -m pip install --upgrade pip build twine
|
|
37
|
+
|
|
38
|
+
- name: Build sdist and wheel
|
|
39
|
+
env:
|
|
40
|
+
SETUPTOOLS_SCM_PRETEND_VERSION: ${{ inputs.version }}
|
|
41
|
+
run: python -m build
|
|
42
|
+
|
|
43
|
+
- name: Verify package metadata
|
|
44
|
+
run: twine check --strict dist/*
|
|
45
|
+
|
|
46
|
+
- uses: actions/upload-artifact@v4
|
|
47
|
+
with:
|
|
48
|
+
name: damlforge-${{ inputs.version }}
|
|
49
|
+
path: dist/*
|
|
50
|
+
|
|
51
|
+
publish:
|
|
52
|
+
needs: build
|
|
53
|
+
runs-on: ubuntu-latest
|
|
54
|
+
environment:
|
|
55
|
+
name: pypi
|
|
56
|
+
url: https://pypi.org/project/damlforge/${{ inputs.version }}/
|
|
57
|
+
permissions:
|
|
58
|
+
id-token: write
|
|
59
|
+
steps:
|
|
60
|
+
- uses: actions/download-artifact@v4
|
|
61
|
+
with:
|
|
62
|
+
name: damlforge-${{ inputs.version }}
|
|
63
|
+
path: dist/
|
|
64
|
+
|
|
65
|
+
- name: Publish to PyPI
|
|
66
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|