Compare commits

...

1372 Commits

Author SHA1 Message Date
waalge 5a8ef1aef0 add: template from docs 2024-11-23 17:05:42 +00:00
Matthias Benkort 94ff20253b
Merge pull request #1059 from waalge/waalge/bump-flake-1-82-0
bump flake deps
2024-11-20 11:05:38 +01:00
waalge 57311d123c bump flake deps 2024-11-20 09:45:28 +00:00
KtorZ e2fb28b4ce
chore: Release 2024-11-19 15:55:23 +01:00
KtorZ 66e39898a1
Fix release date in CHANGELOG. 2024-11-19 15:54:24 +01:00
KtorZ e12d7e807d
Move JSON-schema help for check behind dedicated flag
1. A new option `show_json_schema` which, when enabled, will print the JSON schema of the command output if the target isn't an ANSI-capable terminal.
   2. Some modifications to the help message and error handling for the new option `show_json_schema`.

   This is now done to avoid flooding the help screen with an entire
   JSON schema. Plus, it makes the schema more easily exportable as an
   actual JSON schema.
2024-11-19 15:48:39 +01:00
KtorZ 7a93c55d0b
Minor fixes on the telemetry output for terminal. 2024-11-19 15:00:03 +01:00
KtorZ b5047d623a
Update to pallas=0.31.0 2024-11-19 14:53:36 +01:00
KtorZ c740e4639f
Update CHANGELOG 2024-11-19 13:20:24 +01:00
microproofs eec08fcbd9
Fix scoped path for list with tail cases only plus wild card fallback 2024-11-18 12:22:08 -05:00
microproofs 18054eed1a
chore: Release 2024-11-13 15:17:53 -05:00
microproofs dc38186f33
Update changelog for 1.1.6 2024-11-13 15:17:39 -05:00
Kasey 4ea6fdffe8
Aiken UPLC Optimization overhaul (#1052)
* Refactor and structuring optimizations to be less computationally heavy

* Forgot to commit the new file containing the optimization do over

* Point to correct functions in shrinker2

* Split out inline_constr_ops since it adds in builtins that can then be swept up by the builtin force reduction

* Fix: issue where identity reducer was always returning true

* Forward inlining on lambdas produces better results. This is due to a forward pass being able to apply an argument that may have no_inline at the top where as vice-versa would reduce the arg first.

* Clippy and test fixes

* Clear no_inlines when inlining a function

* Convert shrinker2 to replace shrinker and update tests
2024-11-13 15:08:36 -05:00
KtorZ 10c1b46bf7
Bump minimum rust version everywhere to 1.70.0 2024-11-13 19:38:57 +01:00
KtorZ 5960065a03
Fix validator selection for apply, address and policy command
Before this commit, we would require those target a specific handler,
  whereas they are in fact global to the entire validator.

  So now, we recover the behaviour from before where we default to the
  only available validator when there's no ambiguity.

  Note that this also solves the need for repeatedly applying parameters
  to each handler of a parameterized validator. The command now
  rightfully apply parameters to each corresponding handler.
2024-11-13 19:36:30 +01:00
KtorZ a51f7285c1
Make blueprint files configurable in and out
Closes #1055.
2024-11-13 18:15:09 +01:00
KtorZ c523b0153d
Merge branch 'json-check-output-2' 2024-11-13 15:09:06 +01:00
KtorZ 51a8ddcc0b
Document test output JSON schema through '--help'
The help manual is getting a bit large, but fortunately, we can resort
  to a simpler/more compact version using `-h`.
2024-11-13 14:59:20 +01:00
KtorZ da982510dc
Rework JSON output for tests
- Ensure consistency between overall summary and individual summaries.
  - Remove 'max_*' properties, since they are only padding numbers used
    for formatting the terminal output.
  - Rename a few fields to be closer to the existing naming (name ->
    title, memory -> mem, etc..)
  - Remove duplicated outputs
  - Re-order fields such that summaries come first
2024-11-13 13:12:42 +01:00
KtorZ fafb89d838
Prevent ANSI colors & styles to appear in JSON output. 2024-11-13 12:52:12 +01:00
KtorZ d24a71ee04
Define new event target for JSON, and revert option passing
For the program to be consistent, the 'EventListener' target that we
  pass to a Project should be responsible for the output format.
  Otherwise, we are contingent on developers to remember passing the
  option at call-site. Plus, it overloads the project code with an extra
  boolean option.

  Instead, since the behaviour is solely driven by the execution
  context, we can instantiate a different event target upfront, and
  simply hold on to it throughout the program.

  As a nice side-effect, we can gently re-organize the code to keep the
  terminal printing logic and the json printing logic separate.
2024-11-13 11:07:25 +01:00
Riley-Kilgore 1a75568027
Added target awareness and fixed property based test json output 2024-11-13 11:07:24 +01:00
Riley-Kilgore d1a1d0ec01
Remove unused args in fmt_test_json 2024-11-13 11:05:13 +01:00
Riley-Kilgore 8ac09025f5
Cherry picked cef3276521ba005fa30af46130dba2836347b1ae 2024-11-13 11:05:13 +01:00
microproofs cd42f51f1a
Finish up tests for decision-tree modification 2024-11-08 14:11:34 -05:00
microproofs 634b2e0f79
Next test 2024-11-02 17:16:03 -04:00
microproofs d350bc1935
Change another test 2024-11-02 14:45:58 -04:00
microproofs 362eb75329
Continue updating tests 2024-11-01 19:34:58 -04:00
microproofs e87d7a1101
Fixing unit tests 2024-11-01 19:34:57 -04:00
microproofs d39d70a5d8
More clippy fix 2024-11-01 19:34:56 -04:00
microproofs 1227a8a7db
Clippy fix 2024-11-01 19:34:55 -04:00
microproofs 6b04a78e78
Removing unneeded Air terms and reduce by about 800 lines 2024-11-01 19:34:54 -04:00
microproofs 1bc15f78ea
Finished up remaining touches to the implementation. Now I need to finish unit tests and add a few more 2024-11-01 19:34:54 -04:00
microproofs a4aaf4d2d7
Last issue from acceptance tests 2024-11-01 19:34:53 -04:00
microproofs 27bf40260e
Fix pairs not being unwrapped when wrapped as fields 2024-11-01 19:34:53 -04:00
microproofs 25e4b42cd0
Fix more tests and issues 2024-11-01 19:34:53 -04:00
microproofs 6e94d502a7
Fix more tests and issues 2024-11-01 19:34:53 -04:00
microproofs 7655a6ecbe
Fix test issues 2024-11-01 19:34:52 -04:00
microproofs b4d142ca9d
Fix assigns sometimes having free uniques 2024-11-01 19:34:52 -04:00
microproofs fa203ba9a2
Done with list pattern translation. Now to fix up tests 2024-11-01 19:34:52 -04:00
microproofs 8591bedc1e
Finish up list pattern translation to air 2024-11-01 19:34:52 -04:00
microproofs 1a15440d24
Checkpoint for today 2024-11-01 19:34:52 -04:00
microproofs 9dbe66bc0c
Producing uplc now. Just need to finish ListSwitch 2024-11-01 19:34:51 -04:00
microproofs 342676f530
Continue work on integrating the decision tree into code gen 2024-11-01 19:34:51 -04:00
microproofs 61184fbb86
Use Stick breaking set to track previously encountered values for each DecisionTree switch case 2024-11-01 19:34:51 -04:00
microproofs 5eac774443
Commit latest changes so far 2024-11-01 19:34:50 -04:00
microproofs 753b41dc99
Done with hoisting. Now to use it in gen_uplc. I hate RcDoc btw :'/ 2024-11-01 19:34:50 -04:00
microproofs 9601c1034b
Leave todo message for tomorrow 2024-11-01 19:34:49 -04:00
microproofs 7966cc0165
Finish up decision tree and rework it a bit to closely follow how the paper handles wild card patterns 2024-11-01 19:34:48 -04:00
microproofs 3b3fcb666f
Finish with adding constrs 2024-11-01 19:34:48 -04:00
microproofs ecf4592be1
Pass in interner and data types map into decision tree builder 2024-11-01 19:34:47 -04:00
microproofs 64f7886b23
Finished up creating the decision tree for lists. Only constr left. 2024-11-01 19:34:47 -04:00
microproofs b340de2cfd
Incremental commit for dealing with list tails 2024-11-01 19:34:47 -04:00
microproofs ca161d8a68
Continue work on handling lists with tails pattern matching 2024-11-01 19:34:46 -04:00
microproofs def268d966
Now working for all kinds of patterns except for constr 2024-11-01 19:34:46 -04:00
microproofs 9369cbc1a3
Remove some warnings 2024-11-01 19:34:46 -04:00
microproofs 43e859f1ba
Rework Decision Trees to use path to find the subject to test 2024-11-01 19:34:46 -04:00
microproofs 20385a7ecd
Handle tuples and pairs properly now 2024-11-01 19:34:45 -04:00
microproofs 97ee1a8ba6
Start working on using a decision tree for when expr. Also fmt fix. Other Stuff 2024-11-01 19:34:45 -04:00
KtorZ 2489e0fdd0
Fix aiken docs constant generation
Fixes #1048.
2024-10-29 14:15:31 +01:00
KtorZ 2b7ca0e4a1
Avoid unsafe unwrap of line_numbers, gracefully handle non-existing matches
Fixes #1044.
2024-10-25 11:37:50 +02:00
KtorZ 93d0191489
Fix latest clippy warnings. 2024-10-25 11:27:28 +02:00
KtorZ e97fe332b1
Rename --filter_traces to --trace_filter
It has somehow always annoyed me that we have --trace_level (with 'trace' first) and --filter_traces (with traces, plural and last). Given that these two options are almost always used together, the inconsistency is frustrating.
2024-10-25 11:08:05 +02:00
KtorZ 8e90a933c6
Add better METAVAR info to some command-line flags. 2024-10-25 11:04:46 +02:00
KtorZ 7c4e044423
Rename --blueprint-input to --in
The context is indeed sufficient as pointed by @nemo83; no need to make the cli needlessly verbose.
2024-10-25 11:04:46 +02:00
Matthias Benkort f42cd83f10
Merge pull request #1047 from aiken-lang/riley/update-changelog
Updated Changelog
2024-10-25 10:42:53 +02:00
Riley-Kilgore ab39eb82ce Updated changelog again, forgot to put my name 2024-10-24 14:31:48 -07:00
Riley-Kilgore 413932d86b Updated Changelog 2024-10-24 11:47:34 -07:00
Riley-Kilgore 8d8f91b76e Add blueprint file input as option for blueprint apply 2024-10-24 14:01:48 -04:00
microproofs a7741ec286
chore: Release 2024-10-19 13:45:54 -04:00
microproofs 3e076dd895
Update changelog for 1.1.5 2024-10-19 13:44:22 -04:00
KtorZ b3e6c3ab6b
Fill-in CHANGELOG. 2024-10-19 11:04:18 +02:00
KtorZ b04bb40532
Merge branch 'integer-to-bytearray-cost-fix' 2024-10-19 11:03:37 +02:00
KtorZ 365b3bf5bf
Remove dead-code and clarify note. 2024-10-19 11:00:46 +02:00
KtorZ 7f13fca1a4
Revert "Add acceptance tests #114"
This reverts commit a18af83786. The test
case has proven to be an ill-formed scenario with a genuine infinite
recursion.
2024-10-19 10:52:37 +02:00
KtorZ 4b95db4f88
Fix data-type reification from Void 2024-10-19 10:50:44 +02:00
KtorZ 523b270a8f
Adjust telemetry output log. 2024-10-19 10:40:30 +02:00
microproofs 53685dd1d5
Update cost model to properly calculate integer_to_bytearray
Also fix conformance tests to match plutus
2024-10-18 13:07:51 -04:00
microproofs 9dd3ead3df
IntegerToByteString takes in the second param itself 2024-10-17 20:01:01 -04:00
KtorZ a18af83786
Add acceptance tests #114
Demonstrate what seems to be the creation of an infinite recursion in the produced UPLC.
2024-10-13 13:40:25 +02:00
microproofs 5fd349f571
Remove an unused opcode 2024-10-08 20:32:56 -04:00
microproofs 5d4b3e69b9
Revert "Start working on using a decision tree for when expr. Also fmt fix"
This reverts commit e8f74985d5.
2024-10-08 13:33:05 -04:00
microproofs e8f74985d5
Start working on using a decision tree for when expr. Also fmt fix 2024-10-08 13:30:29 -04:00
KtorZ c7ae161a39
Mention quirks about gnu/musl linux artifact in the release guidelines. 2024-10-02 12:08:01 +02:00
KtorZ 79d0e45099
Don't mark openssl dependencies as optional on musl. 2024-10-02 11:32:17 +02:00
KtorZ f4dbe1624a
Use target_os = linux instead. 2024-10-02 10:59:50 +02:00
KtorZ 19fe1d37e7
Make bundling of ssl conditionned by target environment instead of feature flag. 2024-10-02 10:51:21 +02:00
KtorZ b0cad2bf1d
Update cargo-dist to v0.22.1
Necessary to make use of the custom github build steps.
2024-10-02 10:27:00 +02:00
KtorZ 5204831bac
Fix superfluous toml key in Cargo.toml. 2024-10-02 10:14:27 +02:00
KtorZ 538181f145
Move custom musl build instructions under generic cargo-dist configs. 2024-10-02 10:12:18 +02:00
KtorZ 31819fe197
Define custom build setup for musl target. 2024-10-02 10:05:39 +02:00
microproofs 356d845a9a
chore: Release 2024-10-01 16:14:25 -04:00
microproofs e4e8ca8a6d
Update changelog 2024-10-01 16:13:33 -04:00
microproofs c8731c98c7
Remove prints 2024-10-01 16:09:44 -04:00
microproofs 5fe6e3f77b
Finish simplification changes 2024-10-01 15:57:54 -04:00
microproofs c6c5cddead
Fix ordering of params on standard functions 2024-10-01 13:32:27 -04:00
microproofs 2bbc699a25
Refactor some code to make a define_const AirTree function 2024-10-01 13:32:27 -04:00
KtorZ 513ca27717
Generate empty redeemer for `else` handler, to keep full compliance with the blueprint spec 2024-10-01 19:03:34 +02:00
KtorZ e8d97028ad
Prevent constant evaluating to generic/unbound functions
Constants are like tiny programs, so they are bound by the same rules
  as validators and other programs. In fact, functions are slightly more
  flexible in that they allow generic constant expressions like
  `List<a>`.

  Yet, there is no way to contain such generic structure that contain
  inhabitants in a way that satisfies the type-checker. In the example
  of `List<a>`, the only inhabitant of that type that we can construct
  is the empty list. Anything else would require holding onto some
  generic value.

  In addition, we can't force literal values into generic annotation, as
  something like:

  ```
  const foo: List<a> = [1, 2, 3]
  ```

  wouldn't type-check either since the right-side would unify to
  `List<Int>`. And again, the only right-hand side that can type-check
  is the empty list without any inhabitant.

  The added restriction on generic function is necessary because while
  we allow constants to return lambda, we cannot (easily) generate UPLC
  that is generic in its argument. By the time we generate UPLC, the
  underlying types have to be known.
2024-10-01 18:37:40 +02:00
KtorZ 51b6b77db8
Build LSP projects with verbose tracing level
Without that, the language server might trigger awkward warnings about
  unused imports due to trace stripping. So it's better to compile/check
  projects in the language server in the most expanded form.
2024-10-01 16:12:41 +02:00
KtorZ 0060804d1a
Fix redundant warning when destructuring validator params
This is not a "proper" fix as it simply get rid of the warning
  altogether (whether you use or not the destructured values).

  The reason for removing the warning entirely is because (1) it's
  simpler, but more so (2) there's no impact on the final code produced
  _anyway_. Redundant let bindings are already removed by the compiler;
  and while it's an implicit behaviour that requires a proper warning
  when it's coming from a user-defined assignment; here the redundant
  assignment is introduced by the compiler to begin with as another
  implicit behavior!

  So we have an implicit behaviour triggering a warning on another
  implicit behaviour. Truth is, there's no impact in having those
  parameters destructured and unused. So since users are already not
  aware that this results in an implicit let assignment being inserted
  in place for them; there's no need for the warning at all.
2024-10-01 13:17:00 +02:00
KtorZ 5737556efc
Fix compiler crash around dangling expect/let in traces
Fixes #1029.
2024-10-01 12:24:31 +02:00
KtorZ 9533903acc
Prepare CHANGELOG for v1.1.4 2024-10-01 11:20:07 +02:00
Kasey d5f8d3ab78
Cost model fixes with tests (#1030)
* Finish V1 corrections and fixes to initialize cost model

* Finish V2 corrections to be inline with mainnet today
2024-09-29 22:55:18 -04:00
Riley-Kilgore 92f5bf529f Generate address on else and spend validators; uses title 2024-09-24 11:55:10 -04:00
Riley-Kilgore 7c6f3278ba Fixed single character patterns using double quotes 2024-09-24 11:54:05 -04:00
KtorZ 9a29f4e876
Tweak cargo-dist config to produce static binaries for linux. 2024-09-23 12:22:06 +02:00
KtorZ a35d4f383f
Also add musl tools as system dependencies. 2024-09-23 11:08:04 +02:00
KtorZ bdab4d99b4
Install necessary system dependencies for musl target. 2024-09-23 11:03:40 +02:00
KtorZ b6e5bf68c5
Bundle openssl with musl build. 2024-09-23 10:56:45 +02:00
KtorZ 466dfca4f2
Install musl as target in CI workflow. 2024-09-23 10:54:27 +02:00
KtorZ 555bbc7a48
attempt building statically linked binary with musl. 2024-09-23 10:53:02 +02:00
KtorZ ac9c71e32a
Try to bundle openssl with the Aiken binary to avoid core dumps on Linux 2024-09-22 18:12:26 +02:00
microproofs 3d77b5c378
chore: Release 2024-09-20 14:05:15 -04:00
microproofs e8cf43d7ec
Format fix 2024-09-20 13:52:09 -04:00
microproofs d3e95bd000
Changelog release change 2024-09-20 13:49:45 -04:00
microproofs eb37ed0da5
Clippy fix 2024-09-20 13:47:56 -04:00
microproofs 4f1de2d3b5
Add test for flat error when encoding bls constant 2024-09-20 13:41:58 -04:00
microproofs c3af748b76
Update changelog 2024-09-20 12:53:34 -04:00
microproofs fa2aa0a3e8
When we find bls constants in UPLC convert them to their a hoisted compressed form with an uncompress call 2024-09-20 12:31:36 -04:00
KtorZ a8b37820e8
Fix incorrect warning about unused variable when softcasting without explicit right-pattern.
See note added in code for a rationale.
2024-09-20 15:09:00 +02:00
Matthias Benkort 7155b4e45d
Merge pull request #1023 from solidsnakedev/main
Add wrap constructor to V1/V2 StakeCredential
2024-09-20 14:47:08 +02:00
microproofs 3fddab4724
Add test for hard cast and soft cast on same type 2024-09-19 23:48:06 -04:00
microproofs 18e79db4b2
Fix edge case with traces off and usage of softcast and hardcast on the same type 2024-09-19 22:29:19 -04:00
KtorZ 83ac723a50
Fix extraneous space added after multiline alternative patterns 2024-09-19 20:24:59 +02:00
KtorZ dd77fa7e53
Mention cost model fixes in CHANGELOG. 2024-09-19 20:20:30 +02:00
KtorZ 3f149ab346
Provide intermediate feedback during property test runs.
Avoid the interface to hang for several seconds without feedback when counterexamples are being simplified. This sends a heads-up to the user to indicate that a research of a counter example is going on.
2024-09-19 20:19:49 +02:00
KtorZ 91843b2c0e
Tweak error output for failed data reification. 2024-09-19 20:18:53 +02:00
microproofs 43182721f5
Update PlutusV1 cost model 2024-09-19 10:36:36 -04:00
microproofs b50fa91d4c Finish updating v2 models 2024-09-18 12:06:36 -04:00
microproofs b26e16e319 Start updating v2 cost models 2024-09-18 12:06:36 -04:00
KtorZ 6b145d5594
- 2024-09-18 17:29:31 +02:00
solidsnakedev 75b5332288 fix: Add wrap constructor to V1/V2 stake_credential when Purpose is Rewarding 2024-09-17 19:45:39 -06:00
KtorZ 47a15cf8b2
Fix formatting of long multiline if/is expressions. 2024-09-15 14:59:47 +02:00
KtorZ 12c0d0bc04
Fix formatter adding extra unnecessary newlines after literal lists clause values or assignments. 2024-09-15 14:40:40 +02:00
KtorZ d6c728c0f6
Fix link_tree generation when re-inserting the same modules. 2024-09-14 16:30:28 +02:00
microproofs 7047c7720e
chore: Release 2024-09-13 16:52:20 -04:00
microproofs 0f8cb19ede
Update Changelog for release 2024-09-13 16:49:37 -04:00
KtorZ a9a7a4f977
Fix few formatter annoyances. 2024-09-13 18:53:26 +02:00
KtorZ 799546b654
Show strings as UTF-8 text string during type reification
Instead of defaulting to hex-encoded bytearrays.
2024-09-13 18:34:54 +02:00
KtorZ 9cf908d07f
Fix type reification of Data 2024-09-13 18:34:54 +02:00
KtorZ 4fb13af49f
Fix type reification of PRNG. 2024-09-13 18:34:53 +02:00
microproofs debbae4fda
Update Changelog 2024-09-13 12:09:11 -04:00
Matthias Benkort a1045352d7
Merge pull request #1018 from solidsnakedev/main
fix: Plutus V3 NoDatum
2024-09-13 09:29:55 +02:00
microproofs 16e222e997
Clippy fixes 2024-09-12 19:34:40 -04:00
microproofs 3f2de2665d
Clippy fixes 2024-09-12 19:13:31 -04:00
microproofs 8d13b0b706
Add acceptance test 112 2024-09-12 19:06:46 -04:00
microproofs 362ca2544f
Fixed remaining issue when all parameters passed in to a recursive function were static.
Also fixed issue where modifying the calls in the airtree lead to an out of bounds index.
2024-09-12 17:03:48 -04:00
microproofs 30e66be568
Fix soft casting case 2024-09-12 17:03:48 -04:00
microproofs 49ef3a740c
Cargo tests now pass 2024-09-12 17:03:48 -04:00
microproofs 7c52094b15
Making progress on using interning in gen_uplc
Done interning for uniqueness. Now to fix the static optimization

Remove unused function

Fixing issues. Have a few remaining tests
2024-09-12 17:03:36 -04:00
KtorZ 6413f2c1cc
Make 'simple_spend_no_datum' acceptance test more to-the-point
This new acceptance test is really meant to check for the behavior surrounding the optional datum. So I've added an extra expect on the received datum, and kept only assertions that were about or related to the datum.
2024-09-12 17:21:09 +02:00
KtorZ 8a3bbfc89a
Simplify optional datum extraction by removing duplication 2024-09-12 17:19:17 +02:00
solidsnakedev defce9be4e fix: Plutus V3 NoDatum - Error: missing required inline datum or datum hash in script input 2024-09-11 15:25:20 -06:00
KtorZ 0905146140
chore: Release 2024-09-10 13:25:04 +02:00
KtorZ 74d197077d
Mention Riley contribution in CHANGELOG. 2024-09-10 13:23:16 +02:00
KtorZ 7741be64f8
Fix validator's fallback handler generation
Fixes #1015.
2024-09-10 10:48:06 +02:00
Riley-Kilgore 5879dcfd4c Fix import completions 2024-09-09 12:52:56 -04:00
KtorZ 616dec8f03
Fix formatter getting rid of curly braces around multi-line constants. 2024-09-08 16:23:41 +02:00
KtorZ 0c0369ad61
Fix needed parentheses under trace-if-false disappearing when formatting. 2024-09-08 16:21:45 +02:00
KtorZ b6d99142f9
Fix formatting of multi-line alternative patterns. 2024-09-08 13:11:53 +02:00
KtorZ 8db4a60986
(re)format aiken sources in the repository. 2024-09-07 18:25:21 +02:00
KtorZ 28916c1ef9
Show relative path by default instead of absolute
The absolute path is long and doesn't really provide much information.
  Plus, it's inconsistent with the behavior on a specified path.
2024-09-07 18:24:50 +02:00
KtorZ 943d90a99e
Fix invalid interpolation in error message. 2024-09-07 18:23:35 +02:00
KtorZ b7ea6ea391
Fix list-pattern formatting 2024-09-07 14:50:47 +02:00
KtorZ 5ec147e6c7
Mention config in generated README & generate env folder
Also, get rid of the extra lib/{package_name} directory which is rarely relevant.
2024-09-06 14:15:44 +02:00
KtorZ 04fb11084c
Fix dark colorscheme for dark. 2024-09-06 13:31:19 +02:00
KtorZ 19e30b10f9
Fix #1013 2024-09-06 12:28:12 +02:00
KtorZ 888b7e34c6
Drop debug line that stayed in source code x_x 2024-09-06 12:15:55 +02:00
Matthias Benkort 1f692bc93e
Update CHANGELOG.md 2024-09-03 23:30:18 +02:00
rvcas be31a7ce38
chore: Release 2024-09-03 17:01:41 -04:00
rvcas 20ac89fc33
chore: reset version 2024-09-03 17:01:24 -04:00
microproofs 140cb02be0 Generic test now passes 2024-09-03 16:21:53 -04:00
KtorZ 6a438bc8cd Fix missing locations from generated handler code. 2024-09-03 16:21:53 -04:00
microproofs 2f33c4a8f4 Push up test failing due to missing messages 2024-09-03 16:21:53 -04:00
microproofs 8933688c68 Rest of the tests to push up 2024-09-03 16:21:53 -04:00
microproofs c370a4aa6a Pushing up tests that test both trace and non-trace uplc 2024-09-03 16:21:53 -04:00
microproofs a6bc0f7157 Fix positioning on unwrap_void 2024-09-03 16:21:53 -04:00
microproofs 2be76d7cda Use Delay error directly when casting from data without traces 2024-09-03 16:21:53 -04:00
Matthias Benkort 575f0f9a9a
Merge pull request #1007 from waalge/waalge/bump-flake
bump flake
2024-09-03 19:00:54 +02:00
waalge 0a8f1f4930 bump flake 2024-09-03 16:20:50 +00:00
KtorZ f60df16bc2
Preserve type-aliases during blueprint generation. 2024-09-03 16:39:50 +02:00
KtorZ 007b85b864
Warn for any ignored file during source parsing
Not only for files with a .ak extension.
2024-09-03 15:28:09 +02:00
KtorZ 038f6ecbfd
Detect and report duplicate module names during parsing
Funny enough, we thought about that but only across packages. Now, the
  situation gets a little tricky because of folder structure, it's easy
  to define a module "foo" in `env`, `lib` and/or `validators`. From the
  compiler's perspective, they all have the same name.
2024-09-03 15:24:01 +02:00
KtorZ f8be81baa5
Fix README 'aiken new' example. 2024-09-01 19:11:11 +02:00
KtorZ 9f6daa8cd5
Refresh gift_card and hello_world examples. 2024-09-01 18:22:43 +02:00
KtorZ 7bfc01413b
Add missing parser snapshots. 2024-09-01 18:12:46 +02:00
KtorZ ddfe01ee88
Merge branch 'acceptance-test-111' 2024-09-01 18:11:55 +02:00
KtorZ 53af366b59
Ensure uniqueness of intermediate variables in expect_type_assign
For recursive structures like Tuples, the span itself isn't enough to
  ensure uniqueness of elements (in particular tuples) holding elements
  of the same type.
2024-09-01 18:10:15 +02:00
KtorZ 8d60f08f65
Add acceptance test 111
Seems like nested tuples are inferred wrongly when type-casted.

  ```
  type mismatch
     Expected (list a)
          Got integer
  ```
2024-08-31 00:03:46 +02:00
KtorZ 6d0fe560e2
Provide UPLC machine error as trace context on test failure 2024-08-31 00:01:54 +02:00
KtorZ fed464278d
Allow field access on 'else'. 2024-08-31 00:01:46 +02:00
KtorZ 7aefa85de1
Handle importing validator handler into test module. 2024-08-30 22:43:10 +02:00
KtorZ 5dfa3e7cca
Add label annotation where missing in type-checker errors. 2024-08-30 18:41:25 +02:00
KtorZ 5414fd8f04
Fill-in CHANGELOG for zero-arg / super-const. 2024-08-30 18:41:06 +02:00
KtorZ 75c059bf65
Fix module constant usage warnings. 2024-08-30 18:24:35 +02:00
KtorZ 55d381fbfc
Merge branch 'supercharge-constants' 2024-08-30 15:45:04 +02:00
KtorZ e3e889f875
Update benchmarks. 2024-08-30 15:45:00 +02:00
KtorZ a06383d333
Use const instead of zero-arg functions in few code-gen tests. 2024-08-30 14:47:22 +02:00
KtorZ ef89691331
Ensure code-gen's Program version/semantic matches Plutus version 2024-08-30 14:45:02 +02:00
microproofs 4a8bec4caa
Fixing gen uplc tests 2024-08-29 16:30:31 +02:00
microproofs e772ff1787
Missed some zero parameter check 2024-08-29 16:30:30 +02:00
KtorZ 6c2e3272da
Re-implement and extend docs formatter for constants 2024-08-29 16:25:35 +02:00
KtorZ 71f90ad49f
Fix constant definition parser.
Wouldn't allow a proper sequence of results. Now it does.
2024-08-29 16:25:12 +02:00
KtorZ a909e9eb0a
Add acceptance_tests/109 to illustrate new config/constants capabilities. 2024-08-29 16:25:12 +02:00
KtorZ 38e8c6264d
Do not trigger warnings for exported configurations. 2024-08-29 16:25:12 +02:00
KtorZ 9063549f2e
Re-use expr formatter for constants. 2024-08-29 16:25:12 +02:00
microproofs f35afe8d65
Implement SimpleExpr logic for configuration parsing
We can now use boolean, lists & all in configuration.
2024-08-29 16:25:10 +02:00
microproofs f674f9ee97
hoist functions to super constants too 2024-08-29 16:24:14 +02:00
KtorZ cd0a9440e8
Allow any expression as constants
This is only a start. It compiles, but with a few TODOs left open. In particular, it doesn't currently handle constants depending on other constants or functions; nor does it hoist constants.
2024-08-29 16:24:12 +02:00
KtorZ 79cf0b8d97
Fix test_framework tests trying to implement function on foreign type. 2024-08-29 13:49:09 +02:00
KtorZ c21466831c
Bump versions to 1.1.0, in anticipation. 2024-08-29 09:12:37 +02:00
KtorZ e31c6de04e
Adjust module organization to facilitate resurrection of the playground.
The playground doesn't / cannot depend on aiken-project because that becomes a gigantic pain. So instead, we try to keep essential stuff inside aiken-lang when possible.
2024-08-29 09:12:37 +02:00
KtorZ 8bccbd9e00
Update acceptance tests and script context tests to latest stdlib. 2024-08-28 17:41:32 +02:00
KtorZ 745f14ccb2
Adjust doc to support blockquote alerts. 2024-08-28 15:28:49 +02:00
rvcas 6bbc6a8f2f
chore: fix the issue in gift card 2024-08-27 19:12:44 -04:00
rvcas d337e601cb
chore: add a test for by name with params 2024-08-27 18:10:46 -04:00
Matthias Benkort 9943c2cc7a
Merge pull request #977 from aiken-lang/rvcas/validators_v3
Implement PlutusV3 Validators
2024-08-27 20:31:25 +02:00
KtorZ b78aee2acc
Use pallas==0.30.1 2024-08-27 20:17:56 +02:00
KtorZ efeda9a998
Prevent non-default fallback on exhaustive validator
Technically, we always need a fallback just because the way the UPLC
  is going to work. The last case in the handler pattern matching is
  always going to be else ...

  We could optimize that away and when the validator is exhaustive, make
  the last handler the fallback. Yet, it's really a micro optimization
  that saves us one extra if/else. So the sake of getting things
  working, we always assume that there's a fallback but, with the extra
  condition that when the validator is exhaustive (i.e. there's a
  handler covering all purposes), the fallback HAS TO BE the default
  fallback (i.e. (_) => fail).

  This allows us to gracefully format it out, and also raise an error in
  case where there's an extraneous custom fallback.
2024-08-27 20:16:45 +02:00
KtorZ 48535636ed
Fix remaining acceptance tests to be V3-compatible 2024-08-27 19:19:25 +02:00
KtorZ d615b4f889
Fix incongruous panic when annotation is missing from Datum.
It's fine for the argument to not be annotated; in which case we
  simply default back to an `Option<Data>`.
2024-08-27 18:55:18 +02:00
KtorZ 4003343444
Fix default annotation for spend's optional datum and mint argument.
When there's no type annotation in a validator handler signature, we
  provide default annotation to help the type-checker. However, for
  spend's datum and mint policy_id, those annotations mustn't be `Data`,
  but rather Option<Data> and Bytearray.

  Without that, when no annotation are provided, the compiler infer
  invalid types and fails with incongruous errors.
2024-08-27 18:42:10 +02:00
KtorZ 0510ca58f7
Implement record access syntax for validator handlers.
This is a little trick which detects record access and replace them
  with a simple var. The var itself is the validator handler name,
  though since it contains dots, it cannot be referred to by users
  explicitly. Yet fundamentally, it is semantically equivalent to just
  calling the function by its name.

  Note that this commit also removes the weird backdoor for allowing
  importing validators in modules starting with `tests`. Allowing
  validators handler to be used in importable module requires more work
  and is arguably useful; so we will wait until someone complain and
  reconsider the proper way to do it.
2024-08-27 17:16:15 +02:00
KtorZ ee8f608c0b
Omit validator return annotation when formatting
Unless it is NOT bool as it deviates from the default and while wrong, we want to preserve it to provide a good error.
2024-08-27 14:53:07 +02:00
KtorZ d74e36d0bc
Introduce 'Never' type as a safe alternative to always None options
Unfortunately, as documented in:

  https://github.com/IntersectMBO/cardano-ledger/issues/4571

  Some Option fields in the script context certificates are going to
  remain set to None, at least until the next Hard fork. There's a risk
  that people permanently lock their funds if they expect deposits on
  registration credentials to ever be `Some`.

  So, we introduce a special type that emulate an `Option` that can only
  ever be `None`. We call it `Never` and it is the first type of this
  kind (i.e. with constructors indexes not starting at 0).
2024-08-27 14:40:39 +02:00
rvcas ff25fbd970
chore: acceptance tests v3 syntax 2024-08-26 15:56:49 -04:00
rvcas b57f840cad
chore: use correct arguments in gift card validators 2024-08-26 15:45:37 -04:00
rvcas c87f459ce7
chore: convert gift card tutorial to v3 2024-08-26 15:41:01 -04:00
KtorZ 3521a8c921
Start adjusting acceptance tests to the new Plutus V3 syntax. 2024-08-25 17:12:36 +02:00
KtorZ af9a785d65
Provide default annotation to validators (incl. fallback)
Without that, we may encounter weird error messages when writing
  validators without an explicit `else`. Since we automatically fill it
  with a `fail`; without annotation, it unifies to a generic parameter.

  The existing check that would look for the body being an error term is
  ill-advised as it doesn't work as soon as one adds tracing, or make
  the validator a parameterized validator. Plus, it may simply trigger
  the wrong behavior as one can now annotate a validator with _whatever_
  and get pass the type-checker by plucking a `fail` keyword as body.
2024-08-25 17:12:11 +02:00
KtorZ 1198d7a5ae
Adjust hello world example to new Plutus V3 syntax. 2024-08-25 16:29:24 +02:00
KtorZ 0c9ea196be
Format uplc crate 2024-08-25 16:20:45 +02:00
KtorZ e9edd20c21
Fix gen_uplc tests revolving around validators.
Fucking hell.

  I got rid of the 'opaque_value_in_datum' test since it is no longer
  relevant (we now forbid the presence of opaque types in the ABI).
2024-08-25 16:20:09 +02:00
KtorZ 52a39629b7
Add UPLC test for always_true mint validator.
Mainly to have a trivial example with just the validator boilerplate code.
2024-08-25 16:20:08 +02:00
KtorZ 8c2fdf9ad4
Use dot to separate purpose from validator name in blueprint
The rationale is two folds:

  1. It's more consistent with how we already separate the validator
  name from its module.

  2. Because `_` may be present in Aiken's validator's name, it is hard
     to read and I am afraid it could potentially conflict later on. So
     it's better to use a separator that cannot appear in validator
     names.
2024-08-25 16:20:08 +02:00
KtorZ ed55f03aa2
Fix remaining blueprint test.
Probably an oversight when we reworked them.
2024-08-25 16:20:08 +02:00
KtorZ 442010d056
Fix generation of fallback validator
This must only happen in case all other validator succeed; otherwise
  we might generate invalid validators.
2024-08-25 16:20:08 +02:00
rvcas 73522296aa
chore: accept updated snapshot 2024-08-25 16:20:08 +02:00
rvcas ff1464b462
feat: annotated data for option datum 2024-08-25 16:20:08 +02:00
rvcas d8723c5497
feat: use __fallback in bluprint for the else 2024-08-25 16:20:07 +02:00
rvcas 4589c51cd3
feat: enforcement that spend first arg is option 2024-08-25 16:20:07 +02:00
rvcas c57009bf99
chore: fix some tests that now correctly fail due to arity checks 2024-08-25 16:20:07 +02:00
KtorZ c706d6072d
Fix few blueprint generation tests
Some remains invalid, in particular:

  - We need to handle the annotated Data case, which we still parse
    correctly but do nothing about any longer.

  - There's also a strange behavior with opaque type turned public?
2024-08-25 16:20:07 +02:00
KtorZ f9acbd3bcb
DRY handlers generation from validator 2024-08-25 16:20:07 +02:00
KtorZ 047f422d0d
remove v2 script contexts acceptance tests.
V2 is dead. Long live V3.
2024-08-25 16:20:07 +02:00
KtorZ 6a6bf6f65f
Handle (though discard) first script purpose argument of publish and propose. 2024-08-25 16:20:07 +02:00
KtorZ 5943d94c6c
Finish re-working machine errors display. 2024-08-25 16:20:06 +02:00
KtorZ fe205e360f
Update remaining script context e2e tests. 2024-08-25 16:20:06 +02:00
KtorZ 7ec3f2e8df
DRY builtins types creation to ensure proper consistency. 2024-08-25 16:20:06 +02:00
rvcas 5b61a75088
feat: handler withdraw purpose 2024-08-25 16:20:06 +02:00
rvcas be7c0c8012
fix: withdraw kinda 2024-08-25 16:20:06 +02:00
microproofs f86d550ca0
Fix type for mint scriptinfo 2024-08-25 16:20:06 +02:00
rvcas 3aa9e0c4b7
chore: run fmt on mint 2024-08-25 16:20:05 +02:00
rvcas 3fac7002d4
feat: switch mint to new def 2024-08-25 16:20:05 +02:00
microproofs 953ee6b5d1
Fix ordering for ScriptInfo type 2024-08-25 16:20:05 +02:00
rvcas b9456b5946
fix: wrap_validator_condition needs to happen earlier 2024-08-25 16:20:05 +02:00
rvcas e174532bfd
chore: add more redacted values to machine errors 2024-08-25 16:20:05 +02:00
rvcas 79099675d4
fix: free unique on purpose arg 2024-08-25 16:20:05 +02:00
rvcas c2c4bddfb3
feat: new check for valid purpose names 2024-08-25 16:20:05 +02:00
KtorZ 5cf0a4d294
Fix validator arity check
For now, this panics, but ideally, we should return a "unknown
  purpose" error when we cannot map the name to an arity.
2024-08-25 16:20:04 +02:00
KtorZ 823492c27b
Adjust v3 script context end-to-end tests to work with new syntax. 2024-08-25 16:20:04 +02:00
KtorZ 972e9bd763
Define ScriptPurpose & ScriptContext types in prelude, fix codegen new v3 wrapper. 2024-08-25 16:20:04 +02:00
rvcas 03a348040b
chore: convert hello_world to v3 2024-08-25 16:20:04 +02:00
rvcas 90d75d4a13
fix: redeemer could be missing 2024-08-25 16:20:04 +02:00
rvcas 00b8a39236
fix: private type leaks 2024-08-25 16:20:04 +02:00
rvcas 79840248c0
fix: more parse errors in some tests 2024-08-25 16:20:04 +02:00
rvcas f94e40daf4
fix: more test and issues with scoping/names 2024-08-25 16:20:03 +02:00
rvcas cf3180996a
fix: map fallback name if present to else 2024-08-25 16:20:03 +02:00
rvcas 00907c2bcc
fix: format snapshot tests 2024-08-25 16:20:03 +02:00
rvcas 7f26db401c
feat: handler implicit some and none 2024-08-25 16:20:03 +02:00
rvcas 6b8be61b6e
test: new snapshots for parsing v3 validators 2024-08-25 16:20:03 +02:00
rvcas 0d8d80e5a7
feat: transform TypedValidator in a function of handlers 2024-08-25 16:20:03 +02:00
rvcas 466a4f0b39
feat: adjust blueprint stuff to be aware of handlers 2024-08-25 16:20:02 +02:00
rvcas 471bbe2175
feat: append validator name to handlers 2024-08-25 16:20:02 +02:00
rvcas b984f0455a
feat: return a vec instead of Option 2024-08-25 16:20:02 +02:00
rvcas 4287fa3f4a
feat: new formatting for validators v3 2024-08-25 16:20:02 +02:00
rvcas 9e866a5ec1
fix: make sure that fallback gets it's own scope with params 2024-08-25 16:20:02 +02:00
rvcas 1d9034573b
feat: impl infer for new validators 2024-08-25 16:20:02 +02:00
rvcas fff90f7df5
feat: fix inference comp issues 2024-08-25 16:20:02 +02:00
rvcas 0de5cbc74e
feat: implement new validator parsing 2024-08-25 16:20:01 +02:00
jmhrpr c98e32d3e9
optional costmodel in eval p2 raw 2024-08-24 18:28:08 +02:00
KtorZ 8dfaa1bf90
Fix parsing of v3 cost model
Closes #1002.
2024-08-24 18:26:37 +02:00
KtorZ a71d7c260c
Fix doc_test examples for 'common_prefix' 2024-08-23 16:17:54 +02:00
KtorZ c92b260260
Fix gen_uplc tests following: 0f905045 2024-08-23 16:17:27 +02:00
KtorZ c3b287507e
Fix link_tree test following 0ff12b92 2024-08-23 16:10:07 +02:00
KtorZ 05a3d5fb2a
Revert "Switch back to pallas crates release now that 0.30.0 is out."
This reverts commit 7435dfd0e5.
2024-08-23 16:07:11 +02:00
KtorZ 842001dc0d
Merge branch 'desugar-last-assignment' 2024-08-23 16:04:49 +02:00
KtorZ 70e760cbaa
Fill-in CHANGELOG regarding last expect and tests now accepting Void. 2024-08-23 16:04:40 +02:00
KtorZ 9aa9070f56
Revise desugaring following feedback
- We now consistently desugar an expect in the last position as
    `Void`. Regardless of the pattern. Desugaring to a boolean value is
    deemed too confusing.

  - This commit also removes the desugaring for let-binding. It's only
    ever allowed for _expect_ which then behaves like a side effect.

  - We also now allow tests to return either `Bool` or `Void`. A test
    that returns `Void` is treated the same as a test returning `True`.
2024-08-23 16:04:40 +02:00
KtorZ fbe6f02fd1
Allow assignment as last expression
This is debatable, but I would argue that it's been sufficiently
  annoying for people and such a low-hanging fruit that we ought to do
  something about it.

  The strategy here is simple: when we find a sequence of expression
  that ends with an assignment (let or expect), we can simply desugar it
  into two expressions: the assignment followed by either `Void` or a
  boolean.

  The latter is used when the assignment pattern is itself a boolean;
  the next boolean becomes the expected value. The former, `Void`, is
  used for everything else. So said differently, any assignment
  implicitly _returns Void_, except for boolean which return the actual
  patterned bool.

  <table>
  <thead><tr><th>expression</th><th>desugar into</th></tr></thead>
  <tbody>
  <tr>
  <td>

  ```aiken
  fn expect_bool(data: Data) -> Void {
    expect _: Bool = data
  }
  ```
  </td>
  <td>

  ```aiken
  fn expect_bool(data: Data) -> Void {
    expect _: Bool = data
    Void
  }
  ```
  </td>
  </tr>
  <tr>
  <td>

  ```aiken
  fn weird_maths() -> Bool {
    expect 1 == 2
  }
  ```
  </td>
  <td>

  ```aiken
  fn weird_maths() -> Bool {
    expect True = 1 == 2
    True
  }
  ```
  </td>
  </tr>
  </tbody>
  </table>
2024-08-23 16:04:39 +02:00
KtorZ 7435dfd0e5
Switch back to pallas crates release now that 0.30.0 is out. 2024-08-23 15:59:05 +02:00
KtorZ d1ee90a3a0
Update CHANGELOG.md 2024-08-23 10:41:20 +02:00
KtorZ 0f905045e7
Rename mk_nil_data, mk_pair_data & mk_nil_pair_data builtins. 2024-08-23 10:39:37 +02:00
KtorZ 6e67fe837b
Keep constants and types sorted; only functions are unsorted. 2024-08-23 10:30:18 +02:00
KtorZ c3e39301e2
Re-format source code using cargo fmt. 2024-08-22 16:42:41 +02:00
KtorZ 39c1b5a68a
Merge branch 'generated-docs-improvements' 2024-08-22 16:41:54 +02:00
KtorZ b479a289cf
Implement source linker and add URL to source code in generated docs.
Long overdue.
2024-08-22 16:37:48 +02:00
KtorZ 44e42d608d
Allow hidden modules, not generating any documentation.
This is useful when splitting module for dependencies, yet without the desire to expose internal constructors and types. This merely skips the documentation generation; but doesn't prevent the hidden module from being accessible.
2024-08-22 15:47:00 +02:00
KtorZ 7eee3ce63c
Fix CLI output colors when generating documentation. 2024-08-22 15:47:00 +02:00
KtorZ 10c829edfa
Parse and display documentation section headers.
The idea is pretty simple, we'll just look for lines starting with Markdown heading sections, and render them in the documentation. They appear both in the sidebar, and within the generated docs themselves in between functions. This, coupled with the order preservation of the declaration in a module should make the generated docs significantly more elegant to organize and present.
2024-08-22 15:47:00 +02:00
KtorZ 0ff12b9246
Better module hierarchy and style for generated docs.
This commit also reverse the order of the sections in the sidebar such
  that modules are now placed last.
2024-08-22 15:43:55 +02:00
KtorZ 8b869c0a32
Do not sort functions, types and constants in generated docs
The rationale is to let them in the order they are defined, so that
  library authors have some freedom in how they present information. On
  top of that, we'll also now parse specifi comments as section headers
  that will be inserted in the sidebar when present.
2024-08-22 15:08:46 +02:00
Matthias Benkort 0b6b672149
Merge pull request #984 from aiken-lang/acceptance_107
Introduce acceptance test 107 illustrating compiler crash
2024-08-21 14:43:59 +02:00
KtorZ 35b7066163
Introduce acceptance test 107 illustrating compiler crash
```
  crates/aiken-lang/src/gen_uplc.rs:4515:30

      internal error: entered unreachable code: Shouldn't call anything other than var or apply

      Lambda {
          parameter_name: Name {
              text: "__no_inline__",
              unique: Unique(
                  0,
              ),
          },
          body: Var(
              Name {
                  text: "tests_new_list_unbound",
                  unique: Unique(
                      0,
                  ),
              },
          ),
      }
  ```
2024-08-21 14:43:08 +02:00
KtorZ 802e8272c5
Properly display constructor arguments documentation, if any. 2024-08-20 09:31:41 +02:00
Matthias Benkort 2bb2f11090
Update CHANGELOG.md 2024-08-14 10:03:42 +02:00
KtorZ 32e6705423
Merge branch 'tx-simulate-plutus-v3' 2024-08-14 03:17:14 +02:00
KtorZ 520ceff83d
Do not ignore ctx/inputs.cbor; it is used/needed by the test runner. 2024-08-14 03:09:45 +02:00
KtorZ b104356fb9
(temporarily) make script context tests more verbose. 2024-08-14 03:02:40 +02:00
KtorZ 42784965d2
Implement new costing function for {divide,quotient,mod,remainder}_integer
As well as fixing a couple of other issues thanks to conformance
  tests. Some functions like multiply_integer or verify_ed25519_signature
  have also slightly changed their costing function.
2024-08-14 02:50:05 +02:00
KtorZ 2cb87f4f8f
Add PlutusV3 conformance tests and also control budgets
There were some odd discrepancy for `integerToByteString` on the mem
  side. Either 1 or about 1000 mem units off; which I couldn't quite
  figure out. Yet, it proves useful to validate builtin at large and
  ensure we have a valid cost model for v3.
2024-08-14 02:42:04 +02:00
KtorZ f879f6d183
Fix script context translations for withdrawals and validity intervals. 2024-08-13 23:43:47 +02:00
KtorZ fe5c5650a1
Tweak .gitattributes to exclude insta snapshots from stats (and provide better diffing). 2024-08-13 17:17:41 +02:00
KtorZ 5067aad0d8
Fix 'Pair' formatter inside forced unbroken components. 2024-08-13 17:05:41 +02:00
KtorZ 7501538053
Add script context translations for voting purpose. 2024-08-13 16:24:01 +02:00
KtorZ bfc93bf076
Add script context translation for new Conway certificates 2024-08-13 10:56:29 +02:00
KtorZ f244b9c496
Add support for protocol parameters (except cost models)
We can now simulate transactions with protocol parameters voting
  procedures. Cost models remain to be done, though.
2024-08-13 10:56:29 +02:00
KtorZ 50dad1fdfe
Test proposal procedures through Aiken. 2024-08-13 10:56:29 +02:00
KtorZ cfca0da4e9
Add (partial) support for simulating contract with proposal procedures
This covers every proposal procedures but protocol parameters, this
  one is yet to be done. It spans over 30+ fields, and felt like it is a
  big enough piece to tackle it on its own.
2024-08-13 10:56:29 +02:00
KtorZ 6b6bace8a5
test 'mint' purpose and script context creation.
Alongside a bunch of other stuff from the coverage list. In
  particular, the mint transaction contains:

  - reference inputs
  - multiple outputs, with assets, and type-0, type-1 and type-6
    addresses.
  - an output with a datum hash
  - an output with an inline script
  - carries an extra datum witness, preimage of the embedded hash
  - mint, with 2 policies purposely ordered wrongly, with 1 and 2
    assets purposely ordered wrong. One of the mint is actually a
    burn (i.e. negative quantity)
2024-08-13 10:56:29 +02:00
KtorZ eea8dc7d0a
Support multi-validator in script context accept test. 2024-08-13 10:56:28 +02:00
KtorZ b158469144
Improve / fix machine and uplc error reporting. 2024-08-13 10:56:28 +02:00
KtorZ f56b9bbbc7
Rename function variable in parser
Better reflect its actual semantic. The name probably slipped through a wrong copy pasting.
2024-08-13 10:56:28 +02:00
KtorZ 62b1b932f9
Write down first e2e script context test for v3. 2024-08-13 10:56:28 +02:00
KtorZ 821f7bd8c7
Fix ToPlutusData serializer for V3
This is intense, as we still want to preserve the serializer for V1 &
  V2, and I've tried as much as possible to avoid polluting the
  application layer with many enum types such as:

  ```
  pub enum TxOut {
    V1(TransactionOutput),
    V2(TransactionOutput),
    V3(TransactionOutput),
  }
  ```

  Those types make working with the script context cumbersome, and are
  only truly required to provide different serialisation strategies. So
  instead, we keep one top-level `TxInfo V1/V2/V3` type, and we ensure
  to pass serialization strategies as type wrappers.

  This way, the strategy propagates through the structure up until it's
  eliminated when it reaches the relevant types.

  All-in-all, this strikes a correct balance between maintainability and
  repetition; and it makes it possible to define _different but mostly
  identical_ encoders for the various versions.

  With it, I've been able to successfully encode a V3 script context and
  match it against one produced using the Haskell libraries. More to
  come.
2024-08-13 10:55:23 +02:00
KtorZ f848bad3f2
define UPLC machine default cost models for Plutus V3. 2024-08-13 10:55:23 +02:00
KtorZ fdf7a81288
implement a strict subset of PlutusV3 transaction info
More specifically, that is simply mimicking the script context from
  v2, minus the new governance features.
2024-08-13 10:55:23 +02:00
KtorZ c454dc72eb
Actually decode Conway transaction in 'aiken tx simulate' 2024-08-13 10:55:22 +02:00
KtorZ 508d88035b
Fix Plutus v3 validator hash calculation in blueprint. 2024-08-13 10:55:22 +02:00
KtorZ 445ffc483d
Further remove todos for v3, and reduce duplication in transaction evaluation 2024-08-13 10:55:22 +02:00
KtorZ ff4a480242
Upgrade pallas to v0.0.29, and start support for simulating transactions carrying Plutus v3 scripts. 2024-08-13 10:55:22 +02:00
KtorZ 0dec4dc533
Move script context e2e tests under a nested 'v2' directory.
And rework scripts to run them in anticipation of new v3 contexts.
2024-08-13 10:55:21 +02:00
Riley-Kilgore cab58e5aab One other place 2024-08-12 17:57:54 -04:00
Riley-Kilgore 213ad48de7 Fixed span calculation for backpassing (sort of) 2024-08-12 17:57:54 -04:00
Matthias Benkort eb4a43719c
Merge pull request #998 from aiken-lang/riley/misc-hover
Added more granularity to find_node for Fn
2024-08-12 02:16:38 +02:00
Matthias Benkort 3b94717c58
Merge pull request #996 from aiken-lang/acceptance-scenario-108
Illustrate new failing scenario with multi-arg function identifiers
2024-08-10 16:05:01 +02:00
Riley-Kilgore 52c8ca6cee Added fix to Fn find_node 2024-08-08 17:15:28 -07:00
microproofs 72059eacee
Fix: Recursion issue where the static param optimization on recursive functions that were passed as arguments to other functions 2024-08-08 19:36:16 -04:00
KtorZ 6e4a16d8e0
Illustrate new failing scenario with multi-arg function identifiers
As far as I could tell, this behavior is only observed when the arity
  of the function is higher than 1. It's fine for single-arg functions
  somehow.
2024-08-08 14:52:19 -04:00
KtorZ 59bc9e04ad
Box large elements in project errors. 2024-08-08 14:52:19 -04:00
KtorZ b36250d183
Provide better errors on unknown type in cyclic definitions.
Let's consider the following case:

  ```
  type Var =
    Integer

  type Vars =
    List<Var>
  ```

  This incorrectly reports an infinite cycle; due to the inability to
  properly type-check `Var` which is also a dependent var of `Vars`. Yet
  the real issue here being that `Integer` is an unknown type.

  This commit also upgrades miette to 7.2.0, so that we can also display
  a better error output when the problem is actually a cycle.
2024-08-08 14:52:14 -04:00
microproofs 6fd9b34b92 Running examples as doc tests is not gonna work 2024-08-08 00:39:44 -04:00
microproofs 53c461294b Fix example that was throwing an error 2024-08-08 00:39:44 -04:00
microproofs 31627897d7 Fix example that was throwing an error 2024-08-08 00:39:44 -04:00
microproofs 0800901135 Fix clippy 2024-08-08 00:39:44 -04:00
microproofs 51fd503317 warning fix 2024-08-08 00:39:44 -04:00
microproofs 0a1992acd2 Run acceptance tests 2024-08-08 00:39:44 -04:00
microproofs 224f31b1d7 Fixed last gen_uplc test 2024-08-08 00:39:44 -04:00
microproofs 56ff4ec678 Fixing other tests 2024-08-08 00:39:44 -04:00
microproofs 7ad5491ea9 Fix major uplc test 2024-08-08 00:39:44 -04:00
microproofs 33370b8637 Fix minor issues found when testing 2024-08-08 00:39:44 -04:00
microproofs 4249ef2509 Fix extra delay in a test 2024-08-08 00:39:44 -04:00
KtorZ f5c4e185d4 Redact compiledCode & hash in generated blueprint tests
The point of those tests is to ensure that blueprints are generated
  properly, irrespective of the generated code. It is annoying to
  constantly get those test failing every time we introduce an
  optimization or something that would slightly change the generated
  UPLC.
2024-08-08 00:39:44 -04:00
microproofs 8a461d5bd5 Few minor changes, clippy fixes, and test fixes 2024-08-08 00:39:44 -04:00
microproofs 4cf81a19b1 Update most of the tests and builder functions to use the new delay_branch_functions 2024-08-08 00:39:44 -04:00
microproofs d7e9fef4d3 Create new helper functions to take care of force and delaying branch terms 2024-08-08 00:39:44 -04:00
KtorZ 23a3134642 Rework choose_data_xxx API to include force/delay inside functions. 2024-08-08 00:39:44 -04:00
microproofs d23a5b2f11 Fix test for expect_head_cast_data_with_tail 2024-08-08 00:39:44 -04:00
KtorZ 8b30f064a2 Make gen_uplc test output more readable + start debugging expect_head_cast_with_tail 2024-08-08 00:39:44 -04:00
KtorZ 021679b8ac Force unwrap_xxx_or inside function body
Otherwise, it becomes the responsibility of the caller to force the result; which may be easily forgotten.
2024-08-08 00:39:44 -04:00
microproofs a132a2e486 Fix unwrap issues 2024-08-08 00:39:44 -04:00
KtorZ 93a141bfa4 Test and fix 'unwrap_void_or' 2024-08-08 00:39:44 -04:00
KtorZ 49ddcccd12 Revert checking for negative constr on bool
It is impossible to serialize/deserialize a Data with a negative
  constructor. So the only way this can happen is by programmatically
  construct a value using builtin constr_data.

  While possible, it is entirely at the responsibility of the
  programmer, but not malleable from an attacker who can only provide
  values as 'Data' (and thus, must be decoded like others).
2024-08-08 00:39:44 -04:00
KtorZ aefbc6e1b9 Define a safer API for unwrap_xxx_or and choose_data_xxx
Cloning a 'Term' is potentially dangerous, so we don't want this to
  happen by mistake. So instead, we pass in var names and turn them into
  terms when necessary.
2024-08-08 00:39:44 -04:00
KtorZ 846c16087e Test (and fix) unwrap_or helpers. 2024-08-08 00:39:44 -04:00
KtorZ ea8003af8f Fix bool soft-casting.
While the ledger doesn't allow deserializing negative constr value,
  they are still possible at the machine level. So, we better make sure
  that we don't make assumptions regarding this.
2024-08-08 00:39:44 -04:00
KtorZ 9610237616 Refactor unknown_data_to_type, break down into smaller functions. 2024-08-08 00:39:44 -04:00
KtorZ c3a61706b5 Factor out common UPLC logic for converting Data to Bool. 2024-08-08 00:39:44 -04:00
microproofs 05504b9762 Fix out of order expect check. Also fix no_inline error in code gen. @acceptance_107 2024-08-08 00:39:44 -04:00
microproofs 663695558c Fix remaining errors and now onto testing 2024-08-08 00:39:44 -04:00
microproofs 0be5229f1c Only 2 errors and todos left to finish 2024-08-08 00:39:44 -04:00
microproofs 6ba9a312f0 Work through all but constr case for expect_type_assign
TODO: constr case for expect_type_assign
TODO: soft_cast opcode uplc codegen
TODO: fix PairAccessor opcode uplc codegen
2024-08-08 00:39:44 -04:00
microproofs dd5badd884 Start work on revamping assignment so we can handle soft casting properly 2024-08-08 00:39:44 -04:00
KtorZ 9ea54afd12 Add on more example illustrating if/is issue. 2024-08-08 00:39:44 -04:00
KtorZ a6c5dbb5ad Thread down if/is pattern assignment type down to code-generation.
This isn't sufficient however, as the 'assignment' helper handling
  code generation doesn't perform any check when patterns are vars. This
  is curious, and need to be investigated further.
2024-08-08 00:39:44 -04:00
KtorZ c4abf2e8f4 Add acceptance test 106 showing issue with if/is implicit casting. 2024-08-08 00:39:44 -04:00
KtorZ aa872846bb
Re-generate insta snapshots, remove obsolete snapshots. 2024-08-06 19:25:35 +02:00
KtorZ 9d8fdf787c
Improve formatter on long-lines, in particular bin-ops. 2024-08-06 19:25:35 +02:00
KtorZ 91e0e2493a
Provide better errors on unknown type in cyclic definitions.
Let's consider the following case:

  ```
  type Var =
    Integer

  type Vars =
    List<Var>
  ```

  This incorrectly reports an infinite cycle; due to the inability to
  properly type-check `Var` which is also a dependent var of `Vars`. Yet
  the real issue here being that `Integer` is an unknown type.

  This commit also upgrades miette to 7.2.0, so that we can also display
  a better error output when the problem is actually a cycle.
2024-08-06 19:24:48 +02:00
KtorZ 1ae6640cd0
Make alternative clause parser more flexible.
The spirit here is to make it easier to discover this syntax. People
  have different intuition about it and the single pipe may not be the
  most obvious one.

  It is however the recommended syntax, and the formatter will rewrite
  any of the other to it.
2024-08-06 11:31:11 +02:00
KtorZ 8c121f6d97
Document 'export' and provide better errors on module not found. 2024-08-06 11:09:05 +02:00
KtorZ e3b1cf1093
Rework CHANGELOG to reflect reality.
We never released 1.0.30, so it's a bit misleading to have an entry for it in the CHANGELOG. So I merged its content with the ongoing release which is likely to be 1.1.0
2024-08-06 10:50:15 +02:00
Matthias Benkort e6bb13def6
Merge pull request #994 from aiken-lang/conditional-modules
Conditional configuration & environment
2024-08-06 09:05:11 +02:00
Riley-Kilgore 5160ab49de Use char instead of str 2024-08-05 16:27:37 -04:00
Riley-Kilgore 9296516f5a Fixed hyphen in filename breaking LSP 2024-08-05 16:27:37 -04:00
KtorZ a07f8cbc58
Fill-in CHANGELOG. 2024-08-04 14:48:03 +02:00
KtorZ ec7f659539
Allow bytes to be defined as plain strings, or with specified encoding.
The syntax is as follows:

  { "bytes" = "...", "encoding" = "<encoding>" }

  The following encoding are accepted:

  "utf8", "utf-8", "hex", "base16"

  Note: the duplicates are only there to make it easier for people to
  discover them by accident. When "hex" (resp. "base16") is specified,
  the bytes string will be decoded and must be a valid hex string.
2024-08-04 14:48:03 +02:00
KtorZ 6454266b06
Allow simple expressions as configuration in aiken.toml
This is currently extremely limited as it only supports (UTF-8)
  bytearrays and integers. We should seek to at least support hex bytes
  sequences, as well as bools, lists and possibly options.

  For the latter, we the rework on constant outlined in #992 is
  necessary.
2024-08-04 14:48:03 +02:00
KtorZ 6de1d91104
Create dedicated error when environment isn't found.
This is less confusing that getting an 'UnknownModule' error reporting
  even a different module name than the one actually being important
  ('env').

  Also, this commit fixes a few errors found in the type-checker
  when reporting 'UnknownModule' errors. About half the time, we would
  actually attached _imported modules_ instead of _importable modules_
  to the error, making the neighboring suggestion quite worse (nay
  useless).
2024-08-04 14:48:03 +02:00
KtorZ 2dca0c4185
Ensure env modules dependencies are properly handled.
We figure out dependencies by looking at 'use' definition in parsed
  modules. However, in the case of environment modules, we must consider
  all of them when seeing "use env". Without that, the env modules are
  simply compiled in parallel and may not yet have been compiled when
  they are needed as actual dependencies.
2024-08-04 10:33:58 +02:00
KtorZ fbe2f82582
Thread down environment module from cli down to the type-checker
We simply provide a flag with a free-form output which acts as
  the module to lookup in the 'env' folder. The strategy is to replace
  the environment module name on-the-fly when a user tries to import
  'env'.

  If the environment isn't found, an 'UnknownModule' error is raised
  (which I will slightly adjust in a following commits to something more
  related to environment)

  There are few important consequences to this design which may not seem
  immediately obvious:

  1. We parse and type-check every env modules, even if they aren't
     used. This ensures that code doesn't break with a compilation error
     simply because people forgot to type-check a given env.

     Note that compilation could still fail because the env module
     itself could provide an invalid API. So it only prevents each
     modules to be independently wrong when taken in isolation.

  2. Technically, this also means that one can import env modules in
     other env modules by their names. I don't know if it's a good or
     bad idea at this point but it doesn't really do any wrong;
     dependencies and cycles are handlded all-the-same.
2024-08-04 10:27:32 +02:00
KtorZ c9d0da0c22
Parse sources of conditional env modules.
Do nothing about it yet, but trigger an error if env/default.ak is
  missing; but only if there's any module at all under env.
2024-08-03 17:42:55 +02:00
KtorZ 4645257e62
Prune pallas dependencies.
Using 'pallas' as a dependency brings utxo-rpc other annoying dependencies such as _tokyo_. This not only makes the overall build longer, but it also prevents it to even work when targetting wasm.
2024-08-03 14:14:49 +02:00
Matthias Benkort 09c065d332
Merge pull request #991 from aiken-lang/pattern-match-bytearrays
Allow pattern-matching on bytearrays
2024-08-03 14:09:12 +02:00
KtorZ f14dfdf8e1
Allow pattern-matching on bytearrays
- Doesn't allow pattern-matching on G1/G2 elements and strings,
    because the use cases for those is unclear and it adds complexity to
    the feature.

  - We still _parse_ patterns on G1/G2 elements and strings, but emit an
    error in those cases.

  - The syntax is the same as for bytearray literals (i.e. supports hex,
    utf-8 strings or plain arrays of bytes).
2024-08-03 13:51:36 +02:00
KtorZ ea032c90f2
Add missing CHANGELOG entries. 2024-08-02 12:08:25 +02:00
KtorZ 86aed1baa5 Enable 'mk_pair_data' builtin. 2024-08-02 00:17:16 -04:00
KtorZ 643e43f8aa Fix zero-arg builtins invokations.
There are currently two zero-arg builtins:

  - mkNilData
  - mkNilPairData

  And while they have strictly speaking no arguments, the VM still
  requires that they are called with an extra unit argument applied.
2024-08-02 00:17:16 -04:00
KtorZ 1c58da4d86 Support mk_cons builtin
While this builtin is readily available through the Aiken syntax
  `[head, ..tail]`, there's no reason to not support its builtin form
  even though we may not encourage its usage. For completeness and to
  avoid bad surprises, it is now supported.

  Fixes #964.
2024-08-02 00:17:16 -04:00
KtorZ bf5a406ffb Remove clause guards.
Closes #886.
2024-08-02 00:16:27 -04:00
KtorZ b28d4a6e9f
Add input reference to ReferenceInputNotFound error.
Fixes #974.
2024-08-01 15:29:39 +02:00
KtorZ 34d5bc71b1
Add one more edge-case test for multiline. 2024-08-01 15:21:53 +02:00
KtorZ 91aa435f37
Fix 'multiline' truncating last character of each line.
Fixes #987.
2024-08-01 15:20:43 +02:00
KtorZ b8bb480bff
Fix 'aiken new' workflow template 2024-07-26 13:56:26 +02:00
rvcas 4645fd3e28
chore: Release 2024-07-25 08:28:15 -04:00
rvcas 732147b36a
chore: remove msi installer 2024-07-25 08:26:45 -04:00
KtorZ 53b5a5ccee
Screw windows too, until next non-alpha. 2024-07-25 12:24:47 +02:00
KtorZ 9dc4c915f3
Manually set windows version. 2024-07-25 12:07:27 +02:00
KtorZ 9e08f9b4e6
Re-add wix file for Windows release. 2024-07-25 11:48:27 +02:00
KtorZ 26c3e95a06
screw musl targets, for now. 2024-07-25 11:29:52 +02:00
KtorZ 28c1922600
Also include pkg-config for musl build. 2024-07-25 10:23:30 +02:00
KtorZ d36edb4e01
Add libssl-dev build dependency for musl target. 2024-07-25 10:17:29 +02:00
KtorZ 49190b485a
chore: Release 2024-07-25 09:58:06 +02:00
KtorZ 327449e320
Update CHANGELOG, bump date, document latest fixes & optimizations 2024-07-25 09:54:03 +02:00
Matthias Benkort 594a304190
Merge pull request #980 from aiken-lang/multivalidator-plus-optimization
Mutlivalidator is now an opcode to help minimize validator size
2024-07-25 09:47:47 +02:00
Matthias Benkort 63863c948f
Merge pull request #979 from aiken-lang/fix_casting_inference
Fix pattern inference and annotation requirements.
2024-07-25 09:40:27 +02:00
microproofs c286ada08d
clippy fix 2024-07-24 11:29:55 -04:00
microproofs 1001e83374
Updated acceptance test runs 2024-07-24 10:34:29 -04:00
microproofs dfce9c1d96
feat: Add multivalidator as an AIR tree opcode.
feat: Add uplc eval optimization
2024-07-24 10:00:08 -04:00
KtorZ 67493ad847
Fix casting inferrence on patterns
The original goal for this commit was to allow casting from Data on
  patterns without annotation. For example, given some custom type
  'OrderDatum':

  ```
  expect OrderDatum { requested_handle, destination, .. }: OrderDatum = datum
  ```

  would work fine, but:

  ```
  expect OrderDatum { requested_handle, destination, .. } = datum
  ```

  Yet, the annotation feels unnecessary at this point because type can
  be inferred from the pattern itself. So this commit allows, whenever
  possible (ie when the pattern is neither a discard nor a var), to
  infer the type from a pattern.

  Along the way, I also found a couple of weird behaviours surrounding
  this kind of assignments, in particular in combination with let. I'll
  highlight those in the next PR (#979).
2024-07-24 12:42:24 +02:00
KtorZ 987a5fa779
Set a date for v1.0.30-alpha release. 2024-07-24 09:39:48 +02:00
rvcas 06ac851458
chore: update changelog 2024-07-23 11:20:42 -04:00
Matthias Benkort 967c264bfe
Merge pull request #978 from aiken-lang/supercharge_traces
Supercharge traces
2024-07-23 08:53:46 +02:00
KtorZ 89890f3b4b
Fill-in CHANGELOG 2024-07-19 12:44:12 +02:00
KtorZ 30ddfa23d9
Provide better parse errors in trace when using comma instead of colon. 2024-07-19 12:28:08 +02:00
KtorZ 2922c0aa6f
Display expected patterns/tokens in parse error when applicable.
We've never been using those 'expected' tokens captured during
  parsing, which is lame because they contain useful information!

  This is much better than merely showing our infamous

    "Try removing it!"
2024-07-19 12:28:08 +02:00
KtorZ d6fd37c80e
Rework 'compact' mode for traces
- Trace-if-false are now completely discarded in compact mode.

  - Only the label (i.e. first trace argument) is preserved.

  - When compiling with tracing _compact_, the first label MUST unify to
    a string. This shouldn't be an issue generally speaking and would
    enforce that traces follow the pattern

    ```
    label: arg_0[, arg_1, ..., arg_n]
    ```

  Note that what isn't obvious with these changes is that we now support
  what the "emit" keyword was trying to achieve; as we compile now with
  user-defined traces only, and in compact mode to only keep event
  labels in the final contract; while allowing larger payloads with
  verbose tracing.
2024-07-19 12:28:08 +02:00
KtorZ a9d782e206
re-introduce code-gen patch, but with a test.
Actually, this has been a bug for a long time it seems. Calling any
  prelude functions using a qualified import would result in a codegen
  crash. Whoopsie.

  This is now fixed as shown by the regression test.
2024-07-19 12:28:07 +02:00
KtorZ 5afcc9b0c1
Remove unnecessary code_gen patch.
This is a little weird but, prelude functions are handled slightly
  differently.
2024-07-19 12:28:07 +02:00
KtorZ f8236817fe
Allow serialisable (Data-able) arguments to trace
Somehow, we have to patch some function in gen_uplc because of the
  module name. I have to look further into this because it isn't normal.
2024-07-19 12:28:07 +02:00
KtorZ beb5ac4643
Add 'diagnostic' to the prelude, as well as companion functions.
This is not fully satisfactory as it pollutes a bit the prelude. Ideally, those functions should only be visible
  and usable by the underlying trace code. But for now, we'll just go with it.
2024-07-19 12:28:07 +02:00
KtorZ 754ed07408
Type-check variadic traces & desugarize them. 2024-07-18 10:02:23 +02:00
KtorZ f9719af23e
Allow variadic arguments in trace
Although, doesn't do anything with them yet. The idea is to simplify
  the use of trace to make it a lot more useful than it currently is.
2024-07-18 10:01:34 +02:00
KtorZ 976262c2e6
Allow discard in expect.
Fixes #967.
2024-07-17 18:11:09 +02:00
KtorZ 61a991cb23
Merge branch 'benchmark-knights' 2024-07-17 13:01:32 +02:00
KtorZ 46b82fac86
Split benchmarks out of acceptance tests job. 2024-07-17 13:01:17 +02:00
KtorZ e074037838
Move benchmarks one level up. 2024-07-17 13:00:57 +02:00
KtorZ 30d3898b5b
Add Rust cache to continuous integration workflow. 2024-07-17 12:56:41 +02:00
KtorZ 52974aed75
Add clausify benchmark. 2024-07-17 12:53:19 +02:00
KtorZ 20e606e645
Add benchmarks to continuous integration workflow. 2024-07-17 12:53:18 +02:00
Matthias Benkort 28d2ee7186
Delete examples/benchmarks/.github/workflows/tests.yml 2024-07-17 12:52:29 +02:00
KtorZ f14dab9547
Collect results from previous versions in a README. 2024-07-17 12:52:29 +02:00
KtorZ 5b0a1716b5
Fix mk_starts and second_last in knights benchmarks.
mk_starts was not yielding enough values. It's originally a translation of a double list comprehension in Haskell, which cannot simply be translated to a map2. The latter combine elements two by two, but the former works through all possible permutations.
2024-07-17 12:52:29 +02:00
KtorZ 65afb11546
Implement quicksort on chess board.
Note that it might be easier / cheaper to serialize and compare bytes?
2024-07-17 12:52:29 +02:00
KtorZ f2ff9a2ee3
Review knights benchmark and update dependencies. 2024-07-17 12:52:29 +02:00
microproofs 1d16cbf386
more benchmark work 2024-07-17 12:52:29 +02:00
microproofs c62821e02a
continue porting over knights example 2024-07-17 12:52:29 +02:00
microproofs 8f825f68b1
commit new example for benchmarking 2024-07-17 12:52:28 +02:00
KtorZ fe7d744946
Split continuous workflow in three jobs.
Doing all steps sequentially is starting to get long. Several of those checks are unrelated and can be done in parallel.
2024-07-16 17:41:14 +02:00
KtorZ 0145237bbe
Version wix boilerplate. 2024-07-16 17:33:49 +02:00
KtorZ e9f7e96970
Update cargo-dist setup and generated artifacts. 2024-07-16 17:30:11 +02:00
Matthias Benkort c52ba9c873
Merge pull request #971 from rober-m/main
Solved: Nix expression broken in Darwin
2024-07-02 15:46:23 +02:00
Robertino fef3626498
Fix: Nix expression doesn't work in Darwin 2024-07-02 11:51:46 +01:00
KtorZ 5da7db355f
Use ubuntu-22.04 for linux releases, and add musl target.
This should fix the openssl linking issue, as well as provide an alternative linux build that should be fully static.
2024-07-01 17:34:13 +02:00
Matthias Benkort 8b86ee8219
Merge pull request #962 from waalge/w/bump-nix
bump nix: use rustc 1.79, add analyzer to devshell
2024-07-01 15:43:09 +02:00
rvcas 5bdea11cc1 fix: add a new assignment kind instead of using a boolean 2024-06-25 18:50:00 -04:00
microproofs f1cfc84e67 Fix tree traversal node selection for a few of the enum variants 2024-06-25 18:50:00 -04:00
microproofs 9907dd6c64 Fix unit tests 2024-06-25 18:50:00 -04:00
microproofs 4bd9125b86 Fix delay of arguments to be exactly the same as codegen tests 2024-06-25 18:50:00 -04:00
microproofs f695276bf7 Fix codegen tree traversal to be updated for the otherwise field and future proof the traversal function 2024-06-25 18:50:00 -04:00
microproofs b5ac5bc949 Add current fixed tests and start working on codegen fix 2024-06-25 18:50:00 -04:00
microproofs f0f1296906 Fix more tests 2024-06-25 18:50:00 -04:00
microproofs cc9df04093 Fix missing delay in list_access_to_uplc. Also fix one of the unit tests. 2024-06-25 18:50:00 -04:00
microproofs 41b941e0e3 Fix castfromData in record access cases 2024-06-25 18:50:00 -04:00
KtorZ 00d1927dad Add few more test cases for the parser and type-checker. 2024-06-25 18:50:00 -04:00
rvcas aeb079334e chore: this test doesn't make sense anymore 2024-06-25 18:50:00 -04:00
rvcas 8f343abaa1 chore: add new snapshots 2024-06-25 18:50:00 -04:00
microproofs e09f6bbc87 delay otherwise branch to prevent premature errors 2024-06-25 18:50:00 -04:00
microproofs df939e20ce missed a Air Op Code and updated how we pass in otherwise for assignment 2024-06-25 18:50:00 -04:00
rvcas 7da35d5d73 chore: add acceptance tests for if/is 2024-06-25 18:50:00 -04:00
rvcas 579abb7d3d fix: no need to check exhaustiveness during if/is 2024-06-25 18:50:00 -04:00
rvcas 5024bd3f9c feat: code gen support for if/is
Co-authored-by: Kasey White <kwhitemsg@gmail.com>
2024-06-25 18:50:00 -04:00
rvcas 1b8805825b feat: impl if/is
This commit introduces a new feature into
the parser, typechecker, and formatter.
The work for code gen will be in the next commit.

I was able to leverage some existing infrastructure
by making using of `AssignmentPattern`. A new field
`is` was introduced into `IfBranch`. This field holds
a generic `Option<Is>` meaning a new generic has to be
introduced into `IfBranch`. When used in `UntypedExpr`,
`IfBranch` must use `AssignmentPattern`. When used in
`TypedExpr`, `IfBranch` must use `TypedPattern`.

The parser was updated such that we can support this
kind of psuedo grammar:

`if <expr:condition> [is [<pattern>: ]<annotation>]`

This can be read as, when parsing an `if` expression,
always expect an expression after the keyword `if`. And then
optionally there may be this `is` stuff, and within that you
may optionally expect a pattern followed by a colon. We will
always expect an annotation.

This first expression is still saved as the field
`condition` in `IfBranch`. If `pattern` is not there
AND `expr:condition` is `UntypedExpr::Var` we can set
the pattern to be `Pattern::Var` with the same name. From
there shadowing should allow this syntax sugar to feel
kinda magical within the `IfBranch` block that follow.

The typechecker doesn't need to be aware of the sugar
described above. The typechecker looks at `branch.is`
and if it's `Some(is)` then it'll use `infer_assignment`
for some help. Because of the way that `is` can inject
variables into the scope of the branch's block and since
it's basically just like how `expect` works minus the error
we get to re-use that helper method.

It's important to note that in the typechecker, if `is`
is `Some(_)` then we do not enforce that `condition` is
of type `Bool`. This is because the bool itself will be
whether or not the `is` itself holds true given a PlutusData
payload.

When `is` is None, we do exactly what was being done
previously so that plain `if` expressions remain unaffected
with no semantic changes.

The formatter had to be made aware of the new changes with
some simple changes that need no further explanation.
2024-06-25 18:50:00 -04:00
rvcas b2c42febaf chore: move if_branch to helper parser 2024-06-25 18:50:00 -04:00
Dima S d99c014bf7 chore: correct the usage of a legacy numeric constant 2024-06-25 17:49:36 -04:00
Dima S 1e195156d7 chore(ci): Bump actions/checkout from 3 to 4 2024-06-25 17:49:36 -04:00
waalge 372b186103 nix use rustc 1.79. Add analyzer to devshell 2024-06-19 15:18:18 +00:00
rvcas de870e2529
feat: warning on compiler version mismatch 2024-06-13 20:26:44 -04:00
KtorZ 0ebffa2b9e
Fix few error messages. 2024-06-13 14:54:47 +02:00
Matthias Benkort 3ddd088780
Merge pull request #955 from aiken-lang/allow-complete-patterns-in-args
Allow complete patterns in args
2024-06-07 16:10:06 +02:00
KtorZ 858dfccc82
Authorize complete patterns as function args.
This is mainly a syntactic trick/sugar, but it's been pretty annoying
  to me for a while that we can't simply pattern-match/destructure
  single-variant constructors directly from the args list. A classic
  example is when writing property tests:

  ```ak
  test foo(params via both(bytearray(), int())) {
    let (bytes, ix) = params
    ...
  }
  ```

  Now can be replaced simply with:

  ```
  test foo((bytes, ix) via both(bytearray(), int())) {
    ...
  }
  ```

  If feels natural, especially coming from the JavaScript, Haskell or
  Rust worlds and is mostly convenient. Behind the scene, the compiler
  does nothing more than re-writing the AST as the first form, with
  pre-generated arg names. Then, we fully rely on the existing
  type-checking capabilities and thus, works in a seamless way as if we
  were just pattern matching inline.
2024-06-07 15:42:25 +02:00
KtorZ b6da42baf2
Bump 'is_validator_param' up from 'ArgName' to '...Arg'
There's no reasons for this to be a property of only ArgName::Named to begin with. And now, with the extra indirection introduced for arg_name, it may leads to subtle issues when patterns args are used in validators.
2024-06-07 11:32:05 +02:00
KtorZ 4d42c6cb19
Introduce 'ArgBy' to allow defining function arg not only by name. 2024-06-07 11:17:16 +02:00
KtorZ 257bd23019
update changelog 2024-06-06 11:21:17 +02:00
KtorZ 216dab99d4
chore: Release 2024-06-06 11:19:34 +02:00
KtorZ 87f4ed359b
Update changelog: set a release date. 2024-06-06 11:19:33 +02:00
Matthias Benkort 71ed844db0
Merge pull request #952 from aiken-lang/auto-merge-imports 2024-06-05 10:11:12 +02:00
KtorZ d7ec2131ef
Automatically merge import lines from same module.
I slightly altered the way we parse import definitions to ensure we
  merge imports from the same modules (that aren't aliased) together.

  This prevents an annoying warning with duplicated import lines and
  makes it just more convenient overall.

  As a trade-off, we can no longer interleave import definitions with
  other definitions. This should be a minor setback only since the
  formatter was already ensuring that all import definitions would be
  grouped at the top.

  ---

  Note that, I originally attempted to implement this in the formatter
  instead of the parser. As it felt more appropriate there. However, the
  formatter operates on (unmutable) borrowed definitions, which makes it
  annoyingly hard to perform any AST manipulations. The `Document`
  returns by the format carries a lifetime that prevents the creation of
  intermediate local values.

  So instead, slightly tweaking the parser felt like the right thing to
  do.
2024-06-04 10:48:42 +02:00
KtorZ 7f4ca60d9a
refresh README. 2024-05-31 09:48:14 +02:00
Matthias Benkort 00cd7ce97f
Update README.md 2024-05-31 09:23:49 +02:00
Matthias Benkort 5e1908897f
Update README.md 2024-05-31 09:22:01 +02:00
KtorZ 2070576e46
New LSP quickfix for 'use let' warning. 2024-05-30 19:30:41 +02:00
KtorZ e9e26b969a
Preserve warning display rework, but without breaking the LSP quickfixes. 2024-05-30 19:20:11 +02:00
KtorZ 649e5163fc
Fix parsing of single hex-digits. 2024-05-30 17:19:48 +02:00
KtorZ 5694d9f9cb
Introduce 'fail once' and alter behavior of 'fail' keyword for properties. 2024-05-30 17:18:50 +02:00
Matthias Benkort 28515e70ec
Merge pull request #950 from hadelive/k256-error
Fix k256 error does not implement clone
2024-05-30 13:42:57 +02:00
Matthias Benkort 4c1bee5091
Merge pull request #949 from hadelive/minimal-pallas-deps
Minimal pallas dependencies
2024-05-30 13:42:45 +02:00
hade 740e140c89
fix: custom k256 error 2024-05-30 16:13:51 +07:00
hade b367ec2113
fix: fmt check 2024-05-30 16:09:32 +07:00
hade ad3c9f24b7
chore: minimal pallas dependencies 2024-05-30 15:09:05 +07:00
rvcas c9a15194a0
chore: some dist settings 2024-05-23 21:38:47 -04:00
rvcas cb8f51d7a5
chore: remove npm flow 2024-05-23 21:27:36 -04:00
rvcas 2f9f554e78
feat: npm publish flow 2024-05-23 21:16:13 -04:00
rvcas cb4c01f46b
chore: remove msi and update cargo dist 2024-05-23 21:07:44 -04:00
rvcas 338fc0eba6
chore: Release 2024-05-23 16:45:10 -04:00
rvcas 2605dc6aa4
chore: update changelog 2024-05-23 16:44:50 -04:00
rvcas ed73df302a
fix: completions should not work on windows 2024-05-23 16:43:56 -04:00
rvcas ff50d4d2cf
chore: Release 2024-05-23 16:23:59 -04:00
rvcas 3f46559dbe
chore: update changelog 2024-05-23 16:21:16 -04:00
microproofs 2c8abe4a69 update changelog 2024-05-23 16:15:30 -04:00
microproofs 59cfa209d7 change uplc version number based on plutus version 2024-05-23 15:04:59 -04:00
KtorZ e2bc3a9fc4
Update blueprint generation to work with Pairs.
Closes #938.
2024-05-23 18:15:46 +02:00
KtorZ c48f15a957
revert #903 'feat: Emit keyword'
While we agree on the idea of having some ways of emitting events, the
  design hasn't been completely fleshed out and it is unclear whether
  events should have a well-defined format independent of the framework
  / compiler and what this format should be.

  So we need more time discussing and agreeing about what use case we
  are actually trying to solve with that.

  Irrespective of that, some cleanup was also needed on the UPLC side
  anyway since the PR introduced a lot of needless duplications.
2024-05-23 17:22:12 +02:00
KtorZ e1f39ae539
Oversight: fix missing 'AList' -> 'Pairs' conversion. 2024-05-23 17:08:33 +02:00
KtorZ 5ce30b2632
Rename AList -> Pairs due to popular demand. 2024-05-23 16:45:40 +02:00
KtorZ 8e0f32a577
Fix negative evaluation costs
Whoopsie.
2024-05-23 11:21:47 +02:00
microproofs 3d06129d9b add test for curry optimization that is a reduced case of #945 2024-05-22 15:46:32 -04:00
rvcas c3ad52b50f
feat: add compiler version to aiken.toml 2024-05-22 15:35:57 -04:00
microproofs d6cc450ce4 The actual issue with #945 is that the curry builtin reducer could sometimes place fully applied builtins that could evaluate and fail above where they were actually used. This happened with builtins that were called with the same constants enough times for the curry builtin to try hoist to a higher scope. This is now fixed by detecting which builtins are safe to evaluate in advance before we hoist fully applied builtins 2024-05-22 15:22:31 -04:00
rvcas c1a913f420
fix(config): add default for plutus version 2024-05-22 13:59:56 -04:00
rvcas 7f38b55c1c
fix: comments in record patterns closes #946 2024-05-22 12:26:36 -04:00
microproofs c16bd06e97 make sure traverse_uplc_with_helper is always passing the arg to lambda before running the with function.
Breaks #945 again
2024-05-22 11:58:05 -04:00
rvcas edf82f773c
chore: update snapshots 2024-05-22 11:30:02 -04:00
rvcas f5c4f4cb37
chore(plutus_version): use a cuter name in the config field 2024-05-21 17:13:12 -04:00
microproofs 489eff7f5b Closes #945
Switch to depth first optimization passes instead of breadth first for inlining. Need to think more on how to do breadth first optimization passes
2024-05-21 17:12:57 -04:00
rvcas e28b0df840
fix: add v3 mapping for builtin semantics relates to #907 2024-05-21 17:06:18 -04:00
rvcas 050d003b27
feat: use plutus version in convert command
relates to #907
2024-05-21 17:05:02 -04:00
rvcas f306f1715a
feat: use plutus version in address command
relates to #907
2024-05-21 17:04:25 -04:00
rvcas 3bc3792aa3
feat: add plutus version to aiken.toml
relates to #907
2024-05-21 17:02:20 -04:00
rvcas 4ca73c4cdf
fix: closes #898
This is the best we can do for this without
rearchitecting when we rewrite backpassing to
plain ol' assignments. In this case, if we see
a var and there is no annotation (thus probably not a cast),
then it's safe to rewrite to a `let` instead of an `expect`.
This way, we don't get a warning that is **unfixable**.
We are not trying to solve every little warning edge
case with this fix. We simply just can't allow there
to be a warning that the user can't make go away through
some means. All other edge cases like pattern matching on
a single contructor type with expect warnings can be fixed
via other means.
2024-05-21 15:21:24 -04:00
microproofs c1c2cd97b7 New test 103 and clippy fixes 2024-05-21 11:56:12 -04:00
KtorZ a3c14d881d
Merge branch 'fix/scope-when-backtracking' 2024-05-16 23:43:00 +02:00
KtorZ 7ff6eba869
Prefer '.clone_from' over mutating a clone.
Clippy says it's more efficient. I trust clippy. Clippy good.
2024-05-16 23:42:53 +02:00
KtorZ ea3e79c132
Renamed 'unseed' -> 'not_yet_inferred' 2024-05-16 23:33:23 +02:00
KtorZ 27b3536f09
Also preserve warnings when resetting scope for backtracking.
This is crucial as some checks regarding variable usages depends on
  warnings; so we may accidentally remove variables from the AST as a
  consequence of backtracking for deep inferrence.
2024-05-16 23:20:52 +02:00
KtorZ e87063824c
Fix pretty-printing of recursive type-alias causing stack overflow.
Fixes #942.
2024-05-16 17:20:26 +02:00
KtorZ eadf709411
Fix scope management issue when deep-inferring callee.
Fixes #941.

  However, this currently breaks the stdlib somehow with some FreeUnique on the shrinker step of the optimizer.
2024-05-15 13:18:51 +02:00
KtorZ b546e42766
FML. 2024-05-14 15:27:08 +02:00
KtorZ 8881a88ae3
Also fix multi-validator for gift_card. 2024-05-14 13:28:24 +02:00
KtorZ 1ed4fa1c69
Show warning when ignoring modules + restyle warnings slightly
Fixes #916.
2024-05-14 13:27:19 +02:00
KtorZ 81219cfbdd
Check for data-type serialisability after generic instantiation
Fixes #939.
2024-05-14 10:58:58 +02:00
KtorZ 26ef25ba8d
Make comparison of non-serialisable types illegal.
Fixes #940.
2024-05-14 10:45:15 +02:00
KtorZ ff0407a245
Fix stdlib adjustment in gift_card. 2024-05-14 10:44:48 +02:00
KtorZ 6d7b851c70
Fix 077 after yet-another-breaking-change in stdlib. 2024-05-10 19:05:00 +02:00
KtorZ c5de9adcd3
Add some log output / feedback to completion --install 2024-05-10 17:31:48 +02:00
rvcas c86978b5ac
fix: clippy and add docs to the new flag 2024-05-10 10:51:29 -04:00
Dima S 8a6957dfd0 Update fresh 2024-05-10 10:37:35 -04:00
KtorZ 8c67be55ce
Fixes #921: top-level Miller-loop needs not to be serialisable
This is a bit tricky, but in a similar way where we allow functions to
  be returned by functions, this must also work for MillerLoopResult.
2024-05-10 13:52:23 +02:00
KtorZ 83c0566afb
Merge remote-tracking branch 'freexploit/add-completion-install' 2024-05-10 13:11:10 +02:00
rvcas 392b54aa0e
chore: update readme links 2024-05-08 23:02:02 -04:00
rvcas 4cbde9942a
chore: goodbye old friend 2024-05-08 22:52:19 -04:00
Christopher Valerio 6df1fcb9b0
Merge branch 'aiken-lang:main' into add-completion-install 2024-05-08 10:03:34 -06:00
rvcas f8ce46d0f4 chore(ci): run cargo dist init 2024-05-08 11:05:30 -04:00
microproofs 30436a8a9c update changelog 2024-05-06 15:17:01 -04:00
microproofs 893e9c9855 activate test 75 2024-05-06 15:17:01 -04:00
microproofs 878298cc8e don't use generic data type lookup when you have a Record Variant as a function 2024-05-06 15:17:01 -04:00
KtorZ 967f4348ed Add new acceptance test 101 capturing type mismatch at runtime. 2024-05-06 15:17:01 -04:00
KtorZ 0a660c6a21 Add new acceptance test illustrating need for fn call ordering 2024-05-06 15:17:01 -04:00
KtorZ 99c35a6459 Add now-necessary type-annotations in tests 2024-05-06 15:17:01 -04:00
KtorZ a124bdbb05 Infer callee first in function call
The current inferrence system walks expressions from "top to bottom".
  Starting from definitions higher in the source file, and down. When a
  call is encountered, we use the information known for the callee
  definition we have at the moment it is inferred.

  This causes interesting issues in the case where the callee doesn't
  have annotations and in only partially known. For example:

  ```
  pub fn list(fuzzer: Option<a>) -> Option<List<a>> {
    inner(fuzzer, [])
  }

  fn inner(fuzzer, xs) -> Option<List<b>> {
    when fuzzer is {
      None -> Some(xs)
      Some(x) -> Some([x, ..xs])
    }
  }
  ```

  In this small program, we infer `list` first and run into `inner`.
  Yet, the arguments for `inner` are not annotated, so since we haven't
  inferred `inner` yet, we will create two unbound variables.

  And naturally, we will link the type of `[]` to being of the same type
  as `xs` -- which is still unbound at this point. The return type of
  `inner` is given by the annotation, so all-in-all, the unification
  will work without ever having to commit to a type of `[]`.

  It is only later, when `inner` is inferred, that we will generalise
  the unbound type of `xs` to a generic which the same as `b` in the
  annotation. At this point, `[]` is also typed with this same generic,
  which has a different id than `a` in `list` since it comes from
  another type definition.

  This is unfortunate and will cause issues down the line for the code
  generation. The problem doesn't occur when `inner`'s arguments are
  properly annotated or, when `inner` is actually inferred first.

  Hence, I saw two possible avenues for fixing this problem:

  1. Detect the presence of 'uncongruous generics' in definitions after
     they've all been inferred, and raise a user error asking for more
     annotations.

  2. Infer definitions in dependency order, with definitions used in
     other inferred first.

  This commit does (2) (although it may still be a good idea to do (1)
  eventually) since it offers a much better user experience. One way to
  do (2) is to construct a dependency graph between function calls, and
  ensure perform a topological sort.

  Building such graph is, however, quite tricky as it requires walking
  through the AST while maintaining scope etc. which is more-or-less
  already what the inferrence step is doing; so it feels like double
  work.

  Thus instead, this commit tries to do a deep-first inferrence and
  "pause" inferrence of definitions when encountering a call to fully
  infer the callee first. To achieve this properly, we must ensure that
  we do not infer the same definition again, so we "remember" already
  inferred definitions in the environment now.
2024-05-06 15:17:01 -04:00
KtorZ 7b71389519 Change pretty-printing of unbound variable to '?'
Until now, we would pretty-print unbound variable the same way we would pretty-print generics. This turned out to be very confusing when debugging, as they have a quite different semantic and it helps to visualize unbound types in definitions.
2024-05-06 15:17:01 -04:00
KtorZ ef70c6b8a8 Re-use generic id across builtin type-definitions.
This was somehow wrong and corrected by codegen later on, but we should be re-using the same generic id across an entire definition if the variable refers to the same element.
2024-05-06 15:17:01 -04:00
KtorZ 1070347203 Panic when encountering unknown generics.
This should not happen; if it does, it's an error from the type-checker. So instead of silently swallowing the error and adopting a behavior which is only _sometimes_ right, it is better to fail loudly and investigate.
2024-05-06 15:17:01 -04:00
microproofs b2661ef90a Better error message for compile time evaluation 2024-05-06 11:58:32 -04:00
microproofs 68f1dcc65d Add comment as a reminder to future me 2024-05-06 11:48:10 -04:00
microproofs 0e9baf4944 test should fail 2024-05-06 11:35:55 -04:00
microproofs 2f61f59b60 Closes #909 2024-05-06 11:35:05 -04:00
microproofs 14903f7352 update gift card example 2024-05-04 16:08:08 -04:00
microproofs b669db8516 update tests 2024-05-04 15:58:14 -04:00
microproofs b3d0c3ec04 fix: fixing tests to account for the new stdlib main. Also added test 75 but commented out for now until a fix is merged 2024-05-04 14:26:06 -04:00
microproofs a44ed4c1a8 Change prelude Map to AList 2024-05-04 14:04:12 -04:00
KtorZ b1f0dfdacd Implement parser & formatter for Pair annotations. 2024-05-04 14:04:12 -04:00
microproofs d8d2fb0ebc fix example error 2024-05-04 14:04:12 -04:00
microproofs 58779401e8 fix: formatting was eating the space in pair after the , 2024-05-04 14:04:12 -04:00
microproofs fc0e88018e Chore:
Refactor get_uplc_type to account for constr types that don't exactly resolve to a uplc type
Check arg_stack in uplc generator has only 1 argument at the end of the generation
warning fixes
2024-05-04 14:04:12 -04:00
KtorZ 1091eba3c3 Review & fix acceptance tests
Temporarily using the 'specialize-dict-key' branch from the stdlib
  which makes use of Pair where relevant. Once this is merged back into
  'main' we should update the acceptance test toml files to keep getting
  them automatically upgraded.

  This commit also fixes an oversight in the reification of data-types
  now properly distinguishing between pairs and 2-tuples.

  Co-authored-by: Microproofs <kasey.white@cardanofoundation.org>
2024-05-04 14:04:12 -04:00
KtorZ 03a5a9293c Replace snapshot test for export recursive function
This test contains a pattern match on a 2-tuple, which induced a
  slight code change in UPLC as expected.
2024-05-04 14:04:12 -04:00
KtorZ 7cb548a749 Fix ordinal index on pairs 2024-05-04 14:04:12 -04:00
KtorZ 2cb2c7fa1f Add dedicated 'Pair' typed and untyped expression
Before this commit, we would parse 'Pair' as a user-defined
  data-types, and thus piggybacking on that whole record system. While
  perhaps handy for some things, it's also semantically wrong and
  induces a lot more complexity in codegen which now needs to
  systematically distinguish every data-type access between pairs, and
  others.

  So it's better to have it as a separate expression, and handle it
  similar to tuples (since it's fundamentally a 2-tuple with a special
  serialization).
2024-05-04 14:04:12 -04:00
KtorZ 390bccd406 Fix blueprint validator test snapshot. 2024-05-04 14:04:12 -04:00
KtorZ 92a1da69d9 Add (possibly temporary) assertion on record access in codegen 2024-05-04 14:04:12 -04:00
KtorZ 3dd94983bd Revert "fixing more pair issues"
This reverts commit b76cc7436294cd73e7bbaf656c76a8f8b0ad56a9.
2024-05-04 14:04:12 -04:00
microproofs 46c7cb797a fixing more pair issues 2024-05-04 14:04:12 -04:00
microproofs ebe415cfc9 fix errors 2024-05-04 14:04:12 -04:00
KtorZ 5c59b816ea Add parser for 'Pair' pattern
And a few more tests along the way for others. Note that it is important here that we try to parse for a 'Pair' BEFORE we try to parse for a constructor pattern. Because the latter would swallow any Pair pattern.
2024-05-04 14:04:12 -04:00
KtorZ 91a7e77ab4 Add 'Pair' pattern and rework internals to use it.
Currently, pattern-matching on 'Pair' is handled by treating Pair as a
  record, which comes as slightly odd given that it isn't actually a
  record and isn't user-defined. Thus now, every use of a record must
  distinguish between Pairs and other kind of records -- which screams
  for another variant constructor instead.

  We cannot use `Tuple` either for this, because then we have no ways to
  tell 2-tuples apart from pairs, which is the whole point here. So the
  most sensical thing to do is to define a new pattern `Pair` which is
  akin to tuples, but simpler since we know the number of elements and
  it's always 2.
2024-05-04 14:04:12 -04:00
KtorZ 897b5d1d7e Ensure type-aliases pretty-printing also work with Pair. 2024-05-04 14:04:12 -04:00
KtorZ 3020af7cd7 Revert 'unify' implementation back to its more elegant form
And add support for Pair.
2024-05-04 14:04:12 -04:00
KtorZ cbf3ef2854 Add new Prelude alias: 'Map' 2024-05-04 14:04:12 -04:00
microproofs d7574e738f fix: remaining cargo tests 2024-05-04 14:04:12 -04:00
microproofs 999e408a28 fix some more tests 2024-05-04 14:04:12 -04:00
microproofs 7b5ad961e2 fix: found issue with record access on Pairs 2024-05-04 14:04:12 -04:00
microproofs cb1ca84dad fixing more tests 2024-05-04 14:04:12 -04:00
microproofs 30dd1f60e7 small simplification 2024-05-04 14:04:12 -04:00
microproofs 75b076552c feat: Do a major overhaul on how we check types to allow for match patterns instead of if statements
Also fix one more test
2024-05-04 14:04:12 -04:00
microproofs 3c332ca42a Few more places in codegen where we need to be able to deal with Pair records 2024-05-04 14:04:12 -04:00
microproofs 26f68c2fb4 fix: found various unify and type issues while running tests 2024-05-04 14:04:12 -04:00
microproofs fd226be51f add Pair type to prelude 2024-05-04 14:04:12 -04:00
microproofs a8c8cf41cf Finishing up codegen changes for pair 2024-05-04 14:04:12 -04:00
microproofs 963d275bb8 continue progress on pair adding 2024-05-04 14:04:12 -04:00
microproofs 21b60896f0 remove wild card match from tree functions
Start working on supporting Pair clauses
2024-05-04 14:04:12 -04:00
microproofs f950ae7d3d WIP: add new opcodes to Air and AirTree and update parts of codegen to handle the new pair type 2024-05-04 14:04:12 -04:00
microproofs 9e78f0fc2a update for latest main 2024-05-04 14:04:12 -04:00
microproofs 61a021f9e3 update pair to handle alias 2024-05-04 14:04:12 -04:00
microproofs d05d8e7de6 Start working on separating pairs from 2 tuples in Aiken
co-authored-by: KtorZ <matthias.benkort@gmail.com>
2024-05-04 14:04:12 -04:00
rvcas a9c8054819
chore: update license
Co-authored-by: Kasey White <kwhitemsg@gmail.com>
Co-authored-by: KtorZ <matthias.benkort@gmail.com>
2024-05-01 22:10:47 -04:00
KtorZ db8eb6a108
Provide more context for some panics
Actually ran into them both, will open issues about those in a bit.
2024-05-01 12:04:47 +02:00
KtorZ 925a11be69
Check for args length when comparing types. Duh!
Fixes #917.
2024-05-01 10:48:15 +02:00
Christopher Valerio 24560e9acd
fix: fixing bash messages 2024-04-28 17:21:19 -06:00
Christopher Valerio 6c052f44a1
fix: Adding better error messages 2024-04-28 17:18:37 -06:00
Christopher Valerio 3c66da75d6
Improving errors 2024-04-28 17:13:48 -06:00
Christopher Valerio 9d4c09c722
fix: Removing debugging flag 2024-04-28 17:04:47 -06:00
Christopher Valerio 0b2786e335
feat: aikup install completions scripts linux only 2024-04-28 17:04:47 -06:00
Christopher Valerio 063f3d0835
feat: Adding installation for fish and bash 2024-04-28 17:04:46 -06:00
Christopher Valerio c5faffe946
feat: adding oh-my-zsh support 2024-04-28 17:04:46 -06:00
Christopher Valerio 949f16f34a
rebase from main 2024-04-28 17:04:40 -06:00
microproofs 945a3f743b feat: builtin wrapper reduction optimization 2024-04-26 19:24:04 +02:00
rvcas 4f99c81dee
chore: update changelog 2024-04-12 21:43:28 -04:00
Micah Kendall ff4ddfbe1b Simplifying PR per reviewers request 2024-04-12 21:40:27 -04:00
Micah Kendall d39dbd6697 fmt 2024-04-12 21:40:27 -04:00
Micah Kendall d25b8f91c7 feat: Emit keyword 2024-04-12 21:40:27 -04:00
rvcas 23713ce6fa
chore: update changelog 2024-04-09 11:48:32 -04:00
rvcas 17ddbfaafa chore: remove dbg 2024-04-08 14:30:07 -04:00
rvcas 5fc338a1eb test: add some snapshot tests for export type 2024-04-08 14:30:07 -04:00
rvcas 5cb1e23008 fix: program generate should only run after params and args are validated 2024-04-08 14:30:07 -04:00
rvcas cac119338d feat(blueprint): a memoized program that only runs code gen every other time 2024-04-08 14:30:07 -04:00
rvcas aa3896e92a feat(export): allow trace levels to be controlled 2024-04-08 14:30:07 -04:00
rvcas 79ccc55499 feat(cli): print Export json to stdout
Co-authored-by: Kasey White <kwhitemsg@gmail.com>
2024-04-08 14:30:07 -04:00
rvcas dac3308620 feat(Project::export): use Export::from_function and transpose
Co-authored-by: Kasey White <kwhitemsg@gmail.com>
2024-04-08 14:30:07 -04:00
rvcas 8ed930ac5a feat: implement Export object based on blueprint
Co-authored-by: Kasey White <kwhitemsg@gmail.com>
2024-04-08 14:30:07 -04:00
rvcas 3cdb21ad6b feat(blueprint): make a helper public 2024-04-08 14:30:07 -04:00
rvcas a11b1fa56a chore: cleanup validator creator method 2024-04-08 14:30:07 -04:00
rvcas 9322020a5e feat(blueprint): re-export Error 2024-04-08 14:30:07 -04:00
rvcas f50f7e42db feat(project): create export type
Co-authored-by: Kasey White <kwhitemsg@gmail.com>
2024-04-08 14:30:07 -04:00
rvcas 9d49be46b8 chore: add some docs to the uplc crate 2024-04-08 14:30:07 -04:00
rvcas 033cc26313 fix: with_project no longer needs a seed 2024-04-08 14:30:07 -04:00
rvcas 1d462314c4 feat: use new generate_raw function 2024-04-08 14:30:07 -04:00
rvcas 7d67f1497c feat(export): implement basic command functionality 2024-04-08 14:30:07 -04:00
rvcas b63bd9b9e0 feat(cli): add empty export commands 2024-04-08 14:30:07 -04:00
dependabot[bot] 2abf626e25 chore(deps): bump h2 from 0.3.24 to 0.3.26
Bumps [h2](https://github.com/hyperium/h2) from 0.3.24 to 0.3.26.
- [Release notes](https://github.com/hyperium/h2/releases)
- [Changelog](https://github.com/hyperium/h2/blob/v0.3.26/CHANGELOG.md)
- [Commits](https://github.com/hyperium/h2/compare/v0.3.24...v0.3.26)

---
updated-dependencies:
- dependency-name: h2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-08 12:26:51 -04:00
rvcas fdbe811bf1
chore: update changelog 2024-04-02 19:49:30 -04:00
rvcas b27fcf38e5
fix(check): collapse_links on tuple_index access closes #905 2024-04-02 19:45:16 -04:00
rvcas 7c5b9aa35e
feat(lsp): find_node for TypedArgVia 2024-04-02 19:22:19 -04:00
rvcas d22ee6e086
chore: remove useless clone 2024-04-02 19:04:33 -04:00
rvcas 0ba6d23efa
chore: update changelog 2024-04-02 17:56:53 -04:00
rvcas e02bc2a58a
feat(lsp): find_node should traverse tail of list 2024-04-02 17:55:04 -04:00
rvcas 98bd61a0cd
chore: update changelog 2024-03-29 11:38:22 -04:00
rvcas b5f27026e2
fix: confusing public validator closes #902 2024-03-29 11:32:04 -04:00
rvcas ce2c723d0c
chore: remove some dbg macros 2024-03-29 11:28:22 -04:00
microproofs 21b1e29f09 chore: clippy fix 2024-03-27 16:39:52 -04:00
microproofs a6003c3be9 chore: push changes in blueprint snapshot test 2024-03-27 15:57:29 -04:00
microproofs a5a0734629 fix: casting a field type to Data with expect and traces on was assuming the raw Data was of type constr 2024-03-27 15:52:23 -04:00
rvcas 075668b52e
chore: Release 2024-03-25 22:09:37 -04:00
rvcas 54a89d3e69
chore: update changelog 2024-03-25 22:05:25 -04:00
KtorZ a3f7b48ec3 Allow downcasting to data in piped function calls.
We have been a bit too strict on disallowing 'allow_cast' propagations. This is really only problematic for nested elements like Tuple's elements or App's args. However, for linked and unbound var it is probably okay, and it certainly is as well for function arguments.
2024-03-25 11:57:13 -04:00
KtorZ 4e8042fd06
chore: Release 2024-03-22 16:10:17 +01:00
KtorZ eee1d1bf1e
Fix release date for v1.0.25-alpha. 2024-03-22 16:07:29 +01:00
KtorZ 96387e3437
Fixes #767
Co-authored-by: @rvcas <x@rvcas.dev>
2024-03-22 16:05:32 +01:00
rvcas 80858387f6
chore: update changelog 2024-03-21 20:20:31 -04:00
rvcas a09069b828
fix: binop associativity formatting
it seems we can fix this by changing which side
gets subtracted by 1 depending on the op associativity.
BinOp::Or & BinOp::And are right associative while the
other bin ops are left associative.

closes #893

Co-authored-by: Kasey White <kwhitemsg@gmail.com>
2024-03-21 20:12:49 -04:00
KtorZ 0f9dbfd874
Fixes #883. 2024-03-21 18:20:19 +01:00
rvcas ee280bc309 fix: only allow casting on top level Data 2024-03-21 11:59:34 -04:00
rvcas c20ff6b160 fix: contains_opaque was never intended to be used for type equality 2024-03-21 11:59:34 -04:00
KtorZ 5cec2544b3 Nonsensical prints to be removed. 2024-03-21 11:59:34 -04:00
KtorZ 25e9db4f6c Rename t1 -> lhs, t2 -> rhs in unify. 2024-03-21 11:59:34 -04:00
KtorZ dc9bab4f5c Add extra test case. 2024-03-21 11:59:34 -04:00
KtorZ bee2b712de Fixes #881. 2024-03-21 11:59:34 -04:00
rvcas 4f8e900aac
fix: Discard not taken into account in backpassing
closes #890

Co-authored-by: Kasey White <kwhitemsg@gmail.com>
2024-03-20 17:53:17 -04:00
rvcas 898ef74457
fix: spans for backpassing args
closes #882

Co-authored-by: Kasey White <kwhitemsg@gmail.com>
2024-03-20 17:27:17 -04:00
microproofs 8495f98c1d remove print 2024-03-17 16:26:10 -04:00
microproofs 61936cb91e fix(codegen): Add tracing when checking for a constr vs another primitive 2024-03-17 16:25:17 -04:00
KtorZ d1ba8db889
Do not generate documentation for empty modules. 2024-03-15 21:40:57 +01:00
KtorZ 6515efeb73
Implementing remaining shrinking strategies.
This makes the search for counterexample slower in some cases by 30-40% with the hope of finding better counterexamples. We might want to add a flag '--simplification-level' to the command-line to let users decide on the level of simplifications.
2024-03-15 13:36:05 +01:00
Matthias Benkort b09e0316fa
Merge pull request #877 from aiken-lang/dependencies-pruning
Only compile modules the project depends on
2024-03-15 00:25:00 +01:00
KtorZ 9986bc6bfd
Remove duplication between docs & compile
And move some logic out of project/lib to be near the CheckedModule
  instead. The project API is already quite heavy and long, so making it
  more lightweight is generally what we want to tend to.
2024-03-15 00:05:39 +01:00
KtorZ 1caed3e87c
Use BTreeSet instead of HashSet whenever possible. 2024-03-14 23:08:39 +01:00
Matthias Benkort 3f254dbe6b
Merge pull request #875 from aiken-lang/rvcas/expect_opaque
block expects on opaque types
2024-03-14 19:43:47 +01:00
KtorZ fd50473a32
Only compile modules the project depends on
This changes ensure that we only compile modules from dependencies
  that are used (or transitively used) in the project. This allows to
  discard entire compilation steps at a module level, for modules that
  we do not use.

  The main goal of this change isn't performances. It's about making
  dependencies management slightly easier in the time we decide whether
  and how we want to manage transitive dependencies in Aiken.

  A concrete case here is aiken-lang/stdlib, which will soon depend on
  aiken-lang/fuzz. However, we do not want to require every single
  project depending on stdlib to also require fuzz. So instead, we want
  to seggregate fuzz API from stdlib in separate module, and only
  compile those if they appear in the pruned dependency graph.

  While the goal isn't performances, here are some benchmarks analyzing
  the performances of deps pruning on a simple project depends on a few
  modules from stdlib:

	Benchmark 1: ./aiken-without-deps-pruning check scratchpad
	  Time (mean ± σ):     190.3 ms ± 101.1 ms    [User: 584.5 ms, System: 14.2 ms]
	  Range (min … max):   153.0 ms … 477.7 ms    10 runs

	Benchmark 2: ./aiken-with-deps-pruning check scratchpad
	  Time (mean ± σ):     162.3 ms ±  46.3 ms    [User: 572.6 ms, System: 14.0 ms]
	  Range (min … max):   142.8 ms … 293.7 ms    10 runs

  As we can see, this change seems to have an overall positive impact on
  the compilation time.
2024-03-14 19:41:50 +01:00
KtorZ 038c5b2d34
Rewrite run_n_times to not be recursive but mutates arguments.
We reach a stack-overflow for n > 2000 otherwise. Mutation works well here and is a valid use-case.
2024-03-14 14:18:38 +01:00
KtorZ cdf564fc9d
Expand 'ExpectOnOpaqueType' error help and label. 2024-03-14 11:20:34 +01:00
KtorZ 0343aeca34
Fix remaining insta snapshots. 2024-03-14 11:06:53 +01:00
KtorZ 3055c5ef52
Do not allow casting when rhs or lhs contain an opaque type.
Also slightly extended the check test 'framework' to allow registering side-dependency and using them from another module. This allows to check the interplay between opaque type from within and outside of their host module.
2024-03-14 11:00:17 +01:00
rvcas 191a3e9134
chore: weird thing from rebase 2024-03-13 20:21:33 -04:00
rvcas e71470747f
feat: fix some tests and add a failing one 2024-03-13 20:18:56 -04:00
KtorZ 9127dcdd6e
Add note on the type-casting check. 2024-03-13 20:18:56 -04:00
KtorZ 8f31b45e36
Fix allow_casting condition in unification
We should allow casting from any type to any type. Or at the very least, allow it for well-known types like List.
2024-03-13 20:18:56 -04:00
KtorZ f10cf73905
Rework 'is_opaque' to also check for inner types.
Also removed the duplication in infer_assignment and moved the check down.
2024-03-13 20:18:56 -04:00
KtorZ 22b618116e
rename function argument for clarity
is_assignment was a bit confusing to me since we do actually categorize expect as 'assignment'. So this is more about whether this is a *let* assignment. Hence 'is_let'.
2024-03-13 20:18:55 -04:00
KtorZ 502a13756a
remove irrelevant comment. 2024-03-13 20:18:55 -04:00
KtorZ 961806617f
Add more failing tests for expecting on into opaque types. 2024-03-13 20:18:55 -04:00
KtorZ 3820d2af14
Remove potentially problematic use of ".." in pattern-match
Discard pattern are _dangerous_ is used recklessly. The problem comes
  from maintenance and when adding new fields. We usually don't get any
  compiler warnings which may lead to missing spots and confusing
  behaviors.

  So I have, in some cases, inline discard to explicitly list all
  fields. That's a bit more cumbersome to write but hopefully will catch
  a few things for us in the future.
2024-03-13 20:18:51 -04:00
rvcas 7af4ef53ab
feat: block expects on opaque types 2024-03-13 20:17:54 -04:00
microproofs 1d72838f83 fix: awkward assignment formatting
Co-authored-by: Lucas Rosa <x@rvcas.dev>
2024-03-13 19:10:06 -04:00
microproofs b16880a170 feat(annotation): not passing annotation into lambda when backpassing
Co-authored-by: Lucas Rosa <x@rvcas.dev>
2024-03-13 19:08:53 -04:00
rvcas cc99eceda8 chore: update changelog 2024-03-12 08:10:33 -04:00
rvcas 5840ce34af chore: commit an ignore we can all use without accidentally commiting test files/folders 2024-03-12 08:10:33 -04:00
rvcas 7b32d4ae30 chore: add a test for formatting assignment patterns 2024-03-12 08:10:33 -04:00
rvcas 945b4155cd fix(assignment-patterns): allow trailing 2024-03-12 08:10:33 -04:00
rvcas 97247ce949 chore: assignment patterns refactor tuple into struct 2024-03-12 08:10:33 -04:00
rvcas b6b52ba508 feat(backpassing): implements multi patterns
The main trick here was transforming Assignment
to contain `Vec<UntypedPattern, Option<Annotation>>`
in a field called patterns. This then meant that I
could remove the `pattern` and `annotation` field
from `Assignment`. The parser handles `=` and `<-`
just fine because in the future `=` with multi
patterns will mean some kind of optimization on tuples.
But, since we don't have that optimization yet, when
someone uses multi patterns with an `=` there will be an
error returned from the type checker right where `infer_seq`
looks for `backpassing`. From there the rest of the work
was in `Project::backpassing` where I only needed to rework
some things to work with a list of patterns instead of just one.
2024-03-12 08:10:33 -04:00
Matthias Benkort f02b9b0f0c
Merge pull request #871 from aiken-lang/backpassing
Backpassing
2024-03-11 01:06:17 +01:00
KtorZ 4fbb4fe2db
Handle fuzzer failing unexpected
We shouldn't panic here but bubble the error up to the user to inform
  them about a possibly ill-formed fuzzer.

  Fixes #864.
2024-03-11 01:04:46 +01:00
KtorZ 7e8e959251
Fix spans and error reporting for backpassing. 2024-03-11 00:20:29 +01:00
KtorZ a57dcf3307
Allow backpassing with expect. 2024-03-11 00:20:29 +01:00
KtorZ 435dd0d213
Refactor AssignmentKind to allow backpassing on both let and expect.
The 3rd kind of assignment kind (Bind) is gone and now reflected through a boolean parameter. Note that this parameter is completely erased by the type-checker so that the rest of the pipeline (i.e. code-generation) doesn't have to make any assumption. They simply can't see a backpassing let or expect.
2024-03-11 00:16:23 +01:00
KtorZ df898bf239
Rework monadic-bind into function backpassing.
This is more holistic and less awkward than having monadic bind working only with some pre-defined type. Backpassing work with _any_ function, and can be implemented relatively easily by rewriting the AST on-the-fly.

  Also, it is far easier to explain than trying to explain what a monadic bind is, how its behavior differs from type to type and why it isn't generally available for any monadic type.
2024-03-11 00:16:22 +01:00
KtorZ 1f530f3b24
Experiment with monadic bind. 2024-03-11 00:16:22 +01:00
KtorZ 0e0bed3c9d
Collect traces from last prop-test run on failure 2024-03-10 19:24:25 +01:00
KtorZ d4069148c7
Remove UnitTestResult's output field
Dead-code. Also renamed 'logs' to 'traces'.
2024-03-10 19:00:01 +01:00
KtorZ be7d07fa99
Always show test traces (unless manually turned off with flag)
On both failures and success.
2024-03-10 18:53:11 +01:00
KtorZ c169596c76
preserve type-aliases from annotations on calls. 2024-03-10 00:38:03 +01:00
KtorZ 191e4d47b3
Remove dead-code: 'Layer' 2024-03-09 23:14:44 +01:00
Matthias Benkort ec18127191
Merge pull request #869 from aiken-lang/non-serialisable-types
Forbid non-serializable inhabitants in compound data-types.
2024-03-09 22:39:41 +01:00
KtorZ 80a9393db7
Add --include-dependencies to 'aiken docs'
Fixes #867.
2024-03-09 22:35:38 +01:00
KtorZ ee54266d1f
Forbid non-serializable inhabitants in compound data-types. 2024-03-09 22:25:51 +01:00
KtorZ 37627e3527
Fix indentation of pipelines. 2024-03-09 20:44:51 +01:00
KtorZ 6ba74125c7
Remove extra newlines in test report and only print coverage on success. 2024-03-09 20:32:42 +01:00
microproofs cf86a20256 update Changelog 2024-03-09 13:27:32 -05:00
microproofs c7dcb2c256 Add tests for zero arg cyclic functions and renamed function aliases 2024-03-09 13:23:27 -05:00
KtorZ 22b86a5f82
Add --max-success for running more or less prop runs on demand. 2024-03-09 19:17:57 +01:00
KtorZ d581183cc6
Fix formatter discarding nul bytes. 2024-03-09 18:59:35 +01:00
microproofs b761d6a76d fix: function aliases were leading to free uniques 2024-03-09 12:46:12 -05:00
microproofs bffa678178 fix: mutually recursive zero arg functions needed to have their function bodies delayed 2024-03-09 10:04:30 -05:00
Matthias Benkort 7f0df40b4e
Merge pull request #862 from SundaeSwap-finance/pi/summary-check-count
Include the number of tests / checks run as part of the summary
2024-03-09 13:10:16 +01:00
microproofs c51741cc35 fix: mutually recursive zero arg function calls were reaching an unreachable 2024-03-08 22:58:03 -05:00
Pi Lanningham ebd6c3a56e Cargo fmt 2024-03-08 20:43:27 -05:00
Pi Lanningham ace58e368c Correctly report the checks count
It might be slightly cleaner and more extensible to change  to return a summary, potentially even making  track the tests, coverage, etc. so it can be serialized to JSON. But, for now, this is much simpler, and the approach that KtorZ suggested.
2024-03-08 20:40:50 -05:00
KtorZ 77faee672e
cargo fmt --all 2024-03-09 01:28:48 +01:00
KtorZ bbe7c0bc01
report prop test coverage labels on success. 2024-03-09 01:28:29 +01:00
KtorZ 96da70149d
Count labels in properties.
We'll piggyback on the tracing capabilities of the VM to provide labelling for prop tests. To ensure we do not interfere with normal traces, we only count traces that starts with a NUL byte as label. That convention is assumed to be known of the companion fuzz library that should then provide the labelling capabilities as a dedicated function.
2024-03-09 01:28:29 +01:00
KtorZ d6cc9bdfbe
Allow implicit discard when right-hand side is Void.
This is the most intuitive/expected behavior. Otherwise, it forces a pointless let-binding to 'Void' or into a discard.
2024-03-09 01:28:29 +01:00
rvcas d73f8fd6c2 chore: update changelog 2024-03-08 19:19:07 -05:00
rvcas cb0ae0c074 feat: impl some conversion methods on CheckedModule 2024-03-08 19:19:07 -05:00
rvcas d55b7844f0 feat: impl serde for TypeAliasAnnotation 2024-03-08 19:19:07 -05:00
rvcas 2b5ed95df5 feat: serialize as cbor 2024-03-08 19:19:07 -05:00
rvcas 836e853827 fix: bring back vec1 2024-03-08 19:19:07 -05:00
rvcas 9d99b509b2 chore: this should be gone 2024-03-08 19:19:07 -05:00
rvcas fe6710935d feat: impl serde on errythang 2024-03-08 19:19:07 -05:00
Pi Lanningham e944f10372 Add an optional check count; when we run a command that runs tests, we can set this to Some(x) and it'll print in the summary 2024-03-08 17:36:32 -05:00
rvcas 49ca7e1f75
chore: update changelog 2024-03-08 16:21:48 -05:00
KtorZ a9d596f4cb
Memoize simplification steps during property-based shrinking.
I've been benchmarking that through the shrink of 'large' lists, and the cache brings about 1.5x speed increase. For small and simple cases, the cache as no visible effects (positive or negative).
2024-03-08 18:58:51 +01:00
microproofs c906501836 add one more test 2024-03-08 12:25:26 -05:00
microproofs 64f580bb82 one more change to the changelog 2024-03-08 12:19:18 -05:00
microproofs 9636a4de03 update changelog 2024-03-08 11:18:50 -05:00
Matthias Benkort bc161f761b
Merge pull request #860 from aiken-lang/preserve-type-aliases
Preserve type-aliases in (pretty-printed) type annotations
2024-03-08 16:41:44 +01:00
KtorZ a578728a94
Resolve type aliases based on inferred types.
Before this commit, we would always show the 'declared form' of type aliases, with their generic, non-instantiated parameters. This now tries to unify the annotation with the underlying inferred type to provide even better alias pretty printing.
2024-03-08 16:01:21 +01:00
KtorZ ed9f5c6ef7
Preserve TypeAlias in types for better context/feedback. 2024-03-08 15:59:33 +01:00
KtorZ 877d10ef22
Use inferred Fuzzer inner type for unify error when possible. 2024-03-08 15:57:41 +01:00
microproofs eb07365e73 fix tests 2024-03-08 00:12:44 -05:00
microproofs 94f383762c step up the optimizations a bit more by inlining a small function 2024-03-08 00:12:44 -05:00
microproofs bf429fbdbf remove unused import 2024-03-08 00:12:44 -05:00
microproofs dcec8ecfe6 remove unused special function 2024-03-08 00:12:44 -05:00
microproofs 541d96f558 remove comment line 2024-03-08 00:12:44 -05:00
microproofs 275db2fd11 update tests 2024-03-08 00:12:44 -05:00
microproofs ae396c0224 Fix opaque type destructuring in code gen 2024-03-08 00:12:44 -05:00
microproofs 1edd1a1fa3 change currying to happen with 3 or more occurrences 2024-03-08 00:12:44 -05:00
microproofs e9122de061 more identity reduce testing 2024-03-08 00:12:44 -05:00
microproofs dabaae8ca6 more identity and inline tests 2024-03-08 00:12:44 -05:00
microproofs 97b0cf6813 reorganize shrinker tests 2024-03-08 00:12:44 -05:00
microproofs eb709d6fc3 reorder tests to match order of functions 2024-03-08 00:12:44 -05:00
rvcas fab6d5aff7
chore: fix fmt 2024-03-07 19:32:33 -05:00
KtorZ 8e558d893f
Only reify unit tests assertions on failure. 2024-03-07 19:07:55 +01:00
KtorZ 0d599f7e2d
re-add missing newline after test blocks. 2024-03-07 18:28:21 +01:00
KtorZ 23a22a65cb
Handle (recursive) generic types during reification.
Also moved a bunch of functions from code-gen back into _tipo_, as
  they're better suited and generic enough to be reused elsewhere.
2024-03-07 18:07:52 +01:00
microproofs a3fbe6c155 fix tests 2024-03-06 23:27:10 -05:00
microproofs e217423145 mixed up pair builtin 2024-03-06 23:27:10 -05:00
microproofs bdd84dc952 fixing the tests lead to me create a new function for converting from data 2024-03-06 23:27:10 -05:00
microproofs 892da06e14 add more runtime checking for a few of the data to primitive conversions 2024-03-06 23:27:10 -05:00
KtorZ 4c97240900
Fill-in CHANGELOG about associativity. 2024-03-07 01:31:04 +01:00
KtorZ 0f926d3c31
Fix code-gen tests due to associativity change. 2024-03-07 01:28:51 +01:00
KtorZ bff822ea7f
Rework unit test report to leverage new reification
And also provide slightly better errors when traces, or trace-if-false operators are present.
2024-03-07 01:20:40 +01:00
KtorZ 59996850c1
Implement 'reify_constant' and rename reify to 'reify_data'
Both fullfill similar goal, but reify_constant sits one level above.
2024-03-07 01:17:06 +01:00
KtorZ 8ffa68d2f0
Fix && and || associativity.
Somehow, these have always been right-associative, when the natural thing to expect is left-associativity. It now matters when trying to crawl down binary tree to display them properly.
2024-03-07 01:17:05 +01:00
rvcas c9ab1aec98
chore: consume errs instead of cloning 2024-03-06 18:20:14 -05:00
rvcas f8377af0c8 feat(parse): run in parallel 2024-03-06 18:16:07 -05:00
rvcas 9c5556aa1e feat(deps): remove tests from ast and ignore warnings 2024-03-06 18:16:07 -05:00
rvcas 25ebdc2527
fix: validator args unexpectedly unbound
closes #852
2024-03-06 14:15:00 -05:00
rvcas ad4840958c
chore: add test for validator args with no annotation 2024-03-06 11:19:32 -05:00
Matthias Benkort f14bab69c0
Merge pull request #851 from aiken-lang/update-built
update package dependency
2024-03-06 17:11:05 +01:00
microproofs 2bc433f61e fix: need to use temp_term for counting var occurrences in identity reducer
chore: Adding more shrinker tests and fixed some of the existing ones
2024-03-05 12:08:18 -05:00
microproofs b146db8c95 update package dependency 2024-03-05 10:23:29 -05:00
dependabot[bot] 52795692d6 Bump mio from 0.8.10 to 0.8.11
Bumps [mio](https://github.com/tokio-rs/mio) from 0.8.10 to 0.8.11.
- [Release notes](https://github.com/tokio-rs/mio/releases)
- [Changelog](https://github.com/tokio-rs/mio/blob/master/CHANGELOG.md)
- [Commits](https://github.com/tokio-rs/mio/compare/v0.8.10...v0.8.11)

---
updated-dependencies:
- dependency-name: mio
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-05 10:18:01 -05:00
KtorZ 966a20f691
Fix run_n_times for properties expected to fail. 2024-03-04 23:41:37 +01:00
KtorZ 4d432513e0
Fix interesting case identification for properties expected to fail. 2024-03-04 23:28:45 +01:00
KtorZ 4097d1edb2
Fix negative integer literal parsing in fuzzer DSL. 2024-03-04 23:27:23 +01:00
KtorZ fbeb611e5f
Show counter examples in green when property is expected to fail. 2024-03-04 20:41:04 +01:00
KtorZ 3e922c0a52
Allow primitive literals, lists and tuples in fuzzer expressions. 2024-03-04 20:41:04 +01:00
rvcas c7cd89d127
chore: fix fmt 2024-03-04 13:03:07 -05:00
KtorZ df3baa082e
Remove 'seed' arg from 'with_project' to FinishedTests event
Also polish a bit the output of tests, move test result to stdout to allow filtering out warnings by redirecting stderr to /dev/null.
2024-03-04 18:43:51 +01:00
microproofs c9dd281b45 disable assert that was blocking issue #844 2024-03-04 11:48:22 -05:00
microproofs 27eb1a3e04 Change all uses of interning besides the uplc parser to use the new CodeGenInterner 2024-03-04 11:03:23 -05:00
microproofs e14f091b86 add back test 93 2024-03-04 10:52:56 -05:00
microproofs d971d9818b update tests and ensure identity reducer handles no_inline lambda 2024-03-04 10:52:56 -05:00
microproofs af6c107187 remove unneeded assert 2024-03-04 10:52:56 -05:00
microproofs 06ca22c26a update inliner to handle no_inline functions 2024-03-04 10:52:56 -05:00
microproofs 4e928f39db start adding no inline flag to functions 2024-03-04 10:52:56 -05:00
microproofs 2aaa46e54c remove print 2024-03-04 10:52:56 -05:00
microproofs c6ef37cc5c checkpoint 2024-03-04 10:52:56 -05:00
microproofs 4e0aaf970f update tests and fix final unique issues 2024-03-04 10:52:56 -05:00
microproofs 62963f7fc2 feat: finish curry optmization, improve inline optimization further, and add a subtract integer to add integer conversion 2024-03-04 10:52:56 -05:00
microproofs 7d8fdc0f22 prevent curried function hoisting if occurrences is 0 2024-03-04 10:52:56 -05:00
microproofs 258b5abf23 now currying works 2024-03-04 10:52:56 -05:00
microproofs 3b55a32583 finish up curry optimization on builtins 2024-03-04 10:52:56 -05:00
microproofs 58d586c5cf large refactor to reduce complexity 2024-03-04 10:52:56 -05:00
microproofs 8f84eb382f commit some changes so far 2024-03-04 10:52:56 -05:00
microproofs 9a52258e14 chugging along with a small refactor and some more work toward currying 2024-03-04 10:52:56 -05:00
microproofs 2f72510102 chore: Add back curry code removed in a previous commit 2024-03-04 10:52:56 -05:00
Matthias Benkort 7c2bae0904
Merge pull request #849 from waalge/waalge/bump-rust-1-76-0
Waalge/bump rust 1 76 0
2024-03-04 16:18:41 +01:00
waalge 658984e157 Merge remote-tracking branch 'official/main' into waalge/bump-rust-1-76-0 2024-03-04 14:34:14 +00:00
waalge 5d6bcaabe9 bump flake ... but in a way that works for external builds?! 2024-03-04 14:32:27 +00:00
KtorZ 8e8e0de044
cargo fmt --all 2024-03-04 14:46:16 +01:00
Matthias Benkort 6a4841dd7f
Merge pull request #848 from waalge/waalge/bump-rust-1-76-0
bump rust version in flake
2024-03-04 14:45:52 +01:00
waalge 69aefc8c48 bump rust version in flake 2024-03-04 13:33:43 +00:00
KtorZ 362acd43a3
Rework and optimize PRNG
Using ByteArrays as vectors on-chain is a lot more efficient than relying on actul Data's list of values. From the Rust end, it doesn't change much as we were already manipulating vectors anyway.
2024-03-04 14:27:16 +01:00
KtorZ dd1c7d675f
Allow Aiken files to have more than one dot-separated suffix. 2024-03-04 00:15:05 +01:00
KtorZ 50faf81c0f
Use u64 for PRNG choices. 2024-03-04 00:14:34 +01:00
Matthias Benkort b68f99cf24
Merge pull request #835 from aiken-lang/fuzz2
Property-based testing framework
2024-03-03 21:18:57 +01:00
KtorZ c2bc5848dd
Fill-in CHANGELOG. 2024-03-03 21:09:17 +01:00
KtorZ 900b73b21a
cargo fmt --all 2024-03-03 21:05:43 +01:00
KtorZ fbda31d980
Fix and improve test outputs for prop tests. 2024-03-03 21:00:51 +01:00
KtorZ 7a2537432a
Accept an optional --seed parameter for check, otherwise default to random.
Also, show the seed on failure.
2024-03-03 20:36:01 +01:00
KtorZ a7b9d4bb22
Use u8 for fuzzer choices instead of u32
Value is bounded between 0 and 255.
2024-03-03 19:38:49 +01:00
KtorZ 30841fe000
Rework generate_raw to avoid need to intern in prop tests
Also, this commit makes `apply_term` automatically re-intern the
  program since it isn't safe to apply any term onto a UPLC program. In
  particular, terms that introduce new let-bindings (via lambdas) will
  mess with the already generated DeBruijn indices.

  The problem doesn't occur for pure constant terms like Data. So we
  still have a safe and fast version 'apply_data' when needed.
2024-03-03 19:33:27 +01:00
KtorZ 1134b8d7d0
Register tests as callable definitions.
Also move the registering of validators into the same place as they
  other and define a little cute function to avoid code-duplication.
2024-03-03 19:33:27 +01:00
KtorZ c2dc47fa0b
Refactor creation of CodeGenerator and management of known data_types and functions.
This was a mess to say to the least. The mess started when we wanted
  to make all definitions in codegen use immutable maps of references --
  which was and still is a good idea. Yet, the population of the data
  types and functions definitions was done somehow in a separate step,
  in a rather ad-hoc manner.

  This commit changes that to ensure the project's data_types and
  functions are populated while type checking the AST such that we need
  not to redo it after.

  The code for registering the data type definitions and function
  definitions was also duplicated in at least 3 places. It is now a
  method of the TypedModule.

  Note: this change isn't only just cosmetic, it's also necessary for
  the commit that follows which aims at adding tests to the set of
  available function definitions, thus allowing to make property tests
  callable.
2024-03-03 19:33:26 +01:00
KtorZ 26e563a9be
Hardened property-based testing framework. More tests, less bugs.
Those end-to-end tests are useful. Both for controlling the behavior of the shrinker, but also to double check the reification of Plutus Data back into untyped expressions.
  I had to work-around a few things to get opaque type and private types play nice. Also found a weird bug due to how we apply parameters after unique debruijn indexes have been also applied. A work-around is to re-intern the program.
2024-03-03 19:33:26 +01:00
KtorZ 775a34bc47
Remove acceptance_test 095, now done directly from Rust.' 2024-03-03 19:33:26 +01:00
KtorZ 3df5bcd96d
Fix shrinker impl and implement 3rd strategy of bin_search reduction. 2024-03-03 19:33:26 +01:00
KtorZ 70ea3c9598
Write boilerplate code for being able to easily test properties.
Loads of plumbing, but we now have at least some nice ways to test property execution and shrinking.
2024-03-03 19:33:26 +01:00
KtorZ 2db15d59be
Rename 'aiken-project::script' into 'aiken-project::test_framework' 2024-03-03 19:33:26 +01:00
KtorZ bbc9fc5762
Yield proper user-facing error when inferring Fuzzer usage 2024-03-03 19:33:26 +01:00
KtorZ cf61387a41
Allow prop test argument to be (optionally) annotated. 2024-03-03 19:33:25 +01:00
KtorZ 93347d8e7b
Add Fuzzer to the prelude. 2024-03-03 19:33:25 +01:00
KtorZ 5b4fedd084
Add PRNG to the Prelude. 2024-03-03 19:33:25 +01:00
KtorZ 41fdcbdfae
Add via keywords to str_to_keyword 2024-03-03 19:33:25 +01:00
KtorZ bfcfc5c41b
Implement reification from Maps. 2024-03-03 19:33:25 +01:00
KtorZ 5272f5ecee
Adjust order in which Bool's constructors are declared in the prelude
True corresponds to Constr=1 and False corresponds to Constr=0; their position in the vector shall reflect that. Note that while this would in principle impact codegen for any other type, it doesn't for bool since we likely never looked up this type definition since it is well-known. It does now as the 'reify' function relies on this. Whoopsie.
2024-03-03 19:33:25 +01:00
KtorZ 14f1025f0b
Display counterexamples as Aiken values instead of raw UPLC. 2024-03-03 19:33:24 +01:00
KtorZ c766f44601
Allow Fuzzer with type parameter
Also fix shrinker first reduction, as well as passing of List/Tuples to fuzzer.
2024-03-03 19:33:24 +01:00
KtorZ c29d163900
Rename acceptance_test_093 -> acceptance_test_095 2024-03-03 19:33:24 +01:00
KtorZ a703db4d14
Borrow integrated shrinking approach from MiniThesis. 2024-03-03 19:33:24 +01:00
KtorZ 3762473a60
Add preliminary plumbing to run property test through the CLI.
This is very very rough at the moment. But it does a couple of thing:

  1. The 'ArgVia' now contains an Expr/TypedExpr which should unify to a Fuzzer. This is to avoid having to introduce custom logic to handle fuzzer referencing. So this now accepts function call, field access etc.. so long as they unify to the right thing.

  2. I've done quite a lot of cleanup in aiken-project mostly around the tests and the naming surrounding them. What we used to call 'Script' is now called 'Test' and is an enum between UnitTest (ex-Script) and PropertyTest. I've moved some boilerplate and relevant function under those module Impl.

  3. I've completed the end-to-end pipeline of:
     - Compiling the property test
     - Compiling the fuzzer
     - Generating an initial seed
     - Running property tests sequentially, threading the seed through each step.

   An interesting finding is that, I had to wrap the prop test in a similar wrapper that we use for validator, to ensure we convert primitive types wrapped in Data back to UPLC terms. This is necessary because the fuzzer return a ProtoPair (and soon an Array) which holds 'Data'.

  At the moment, we do nothing with the size, though the size should ideally grow after each iteration (up to a certain cap).

  In addition, there are a couple of todo/fixme that I left in the code as reminders of what's left to do beyond the obvious (error and success reporting, testing, etc..)
2024-03-03 19:33:24 +01:00
KtorZ aadf3cfb48
Allow test definition to carry one parameter
The parameter is special as it takes no annotation but a 'via' keyword followed by an expression that should unify to a Fuzzer<a>, where Fuzzer<a> = fn(Seed) -> (Seed, a). The current commit only allow name identifiers for now. Ultimately, this may allow full expressions.
2024-03-03 19:33:24 +01:00
Matthias Benkort bfb4455e0f
Merge pull request #847 from aiken-lang/forbid-opaque-types
Forbid opaque types in the application binary interface.
2024-03-03 15:37:43 +01:00
KtorZ 84c4ccaf4c
Forbid opaque types in the application binary interface.
We cannot enforce internal invariants on opaque types from only structural checks on Data. Thus, it is forbidden to find an opaque type in an outward-facing interface. Instead, users should rely on intermediate representations and lift them into opaque types using constructors and methods provided by the type (e.g. Dict.from_list, Rational.from_int, Rational.new, ...)
2024-03-03 13:55:10 +01:00
KtorZ 4ff11f4229
Fix acceptance test 087 following BigInt seralization fix. 2024-03-02 14:11:22 +01:00
KtorZ 2b8e99a1b8
Fix CI script for acceptance tests, and have them run in parallel. 2024-03-02 14:11:22 +01:00
rvcas d698f76e3c
fix(codegen): builtin calls for g1 and g2 where flipped
closes #840
2024-02-29 12:13:51 -05:00
rvcas ff5491caa0
fix(check): only disallow ml_result in data 2024-02-29 11:19:26 -05:00
rvcas d18caaeecb
feat(cli): support mainnet address output
closes #832
2024-02-27 21:55:18 -05:00
rvcas 50c37c7a14
feat(aikup): error message when version not found
closes #837
2024-02-27 21:38:00 -05:00
rvcas 2018a18d15
fix: error message for bls elements in a type def
closes #840
2024-02-27 21:21:18 -05:00
KtorZ 46c357df7b Fix Int/BigInt pivot
We've been wrongly representing large ints as BigInt, causing them to
  behave differently in the VM through builtins like 'serialise_data'.

  Indeed, we expect anything that fits in 8 bytes to be encoded as Major
  Type 0 or 1. But we were switching to encoding as Major type 6
  (tagged, PosBigInt, NegBigInt) for much smaller values! Anything
  outside of the range [-2^32, 2^32-1] would be treated as big int
  (positive or negative).

  Why? Because we checked whether a value i would fit in an i64, and if
  it didn't we treated it as big int. But the reality is more subtle...
  Fortunately, Rust has i128 and the minicbor library implements TryFrom
  which enforces that the value fits in a range of [-2^64, 2^64 - 1], so
  we're back on track easily.
2024-02-25 14:09:56 -05:00
rvcas 8d59ba1c77 chore: update the conformance tests 2024-02-20 13:05:28 -05:00
rvcas a15fead982 chore: remove unused import 2024-02-20 13:05:28 -05:00
rvcas 20917bbd5b feat(machine): fix Value::Constr fields order
cc @MicroProofs
2024-02-20 13:05:28 -05:00
rvcas 028528899c feat(runtime): implement byteStringToInteger and add conformance tests 2024-02-20 13:05:28 -05:00
rvcas da6e5ec6d1 feat: implement integerToByteString
Co-authored-by: Kasey White <kwhitemsg@gmail.com>
2024-02-20 13:05:28 -05:00
rvcas c7dd4d0e48 feat(aiken-lang): expose integerToByteString and byteStringToInteger 2024-02-20 13:05:28 -05:00
rvcas fc3bc4d9ff feat(cost_model): add costing for integerToByteString and byteStringToInteger 2024-02-20 13:05:28 -05:00
rvcas 70d4d7fdeb feat(runtime): add force count and arity for integerToByteString and byteStringToInteger 2024-02-20 13:05:28 -05:00
rvcas b0eade209b feat(DefaultFunction): add IntegerToByteString and ByteString 2024-02-20 13:05:28 -05:00
Sam Foo b6b57c776f chore: use updated theme method 2024-02-15 14:47:53 -05:00
rvcas 9e3f348c6c
chore: commit artifacts from acceptance tests 2024-02-13 21:29:46 -05:00
rvcas 0ccfe60072
feat: support nested void matching 2024-02-13 21:29:24 -05:00
rvcas ac0c73a56a
chore: clippy fixes 2024-02-13 20:26:12 -05:00
rvcas 3582c5569d
fix: no single when clause warning sometimes
While looking at some code, I noticed that this
warning would show up even if an error for a
non-exhaustive when/is shows up for the same when/is
expression. This isn't a useful situation to show this
warning because things are not exhaustive yet so we should
let the user finish and only provide the errors. If things
are exhaustive then the code proceeds and if a warning was set
when there's only one clause pattern then this warning message
can be pushed because that's when it's actually useful.
2024-02-13 20:12:40 -05:00
rvcas 4c5a449d83
chore: improve a comment/doc 2024-02-13 19:46:34 -05:00
microproofs 6e2f9b9eb9 fix tests 2024-02-07 12:48:07 -05:00
microproofs 056e3d76ea change check_validator_args to check type after each arg 2024-02-07 12:48:07 -05:00
microproofs 6c6be3f53d got past the errors and warnings 2024-02-07 12:37:37 -05:00
microproofs 51f1da2505 Removed AirStatements and AirExpressions
Still a WIP
2024-02-07 12:37:37 -05:00
microproofs b807d58e89 fix first compiler pass of errors 2024-02-07 12:37:37 -05:00
microproofs dc195b22d4 missed another hoist over 2024-02-07 12:36:35 -05:00
microproofs 713b16e25d we now build forwards when it comes to piplines and expressions
so this test got reordered
2024-02-07 12:36:35 -05:00
microproofs d1c784ed49 few more hoist over fixes 2024-02-07 12:36:35 -05:00
microproofs 3938d74bb6 missed a hoist over 2024-02-07 12:36:35 -05:00
microproofs 6b97ab71fe fix up code gen tests 2024-02-07 12:36:35 -05:00
microproofs 4ab3b61200 In most cases the context isn't need so I made the code more explicit about that 2024-02-07 12:36:35 -05:00
microproofs 575dde9885 fix: issue with reordering statements caused clause props to not be updated 2024-02-07 12:36:35 -05:00
microproofs 8702c736d0 fix warning 2024-02-07 12:36:35 -05:00
microproofs 806a74c192 fix all current errors 2024-02-07 12:36:35 -05:00
microproofs 9f96e4bc5a fix first compiler pass of errors 2024-02-07 12:36:35 -05:00
KtorZ a12c374258 Start turning AirTree statements into expressions (let)
Still many places to fix, WIP.
2024-02-07 12:36:35 -05:00
microproofs cf51b30045 update changelog 2024-02-07 11:48:52 -05:00
KtorZ 3c8460e6af Allow annotating Data for blueprint
This commit allows Data to be optionally annotated with a
  phantom-type. This doesn't change anything in codegen but we can now
  leverage this information to generate better blueprint schemas.
2024-02-07 11:48:52 -05:00
KtorZ 20ce19dfb1 Fix error hint when expecting 0 generic parameters. 2024-02-07 11:48:52 -05:00
microproofs 0e2995e16e fix test 2024-02-07 11:48:52 -05:00
microproofs 3b4c6cb2aa fix: missing message error term in one place for type is void 2024-02-07 11:48:52 -05:00
microproofs e25be7643e discards will now check for type too. 2024-02-07 11:48:52 -05:00
microproofs 982eff449e chore: Release 2024-01-31 13:48:20 -05:00
rvcas b46206bfe2
chore: update changelog 2024-01-31 13:47:07 -05:00
microproofs bcc2a0fd12 update changelog 2024-01-31 13:44:11 -05:00
microproofs 258c224e21 update changelog 2024-01-31 13:42:46 -05:00
microproofs d8cdeba6fd chore: lastest acceptance test lock and plutus.json files 2024-01-31 00:07:43 -05:00
microproofs 551941392e fix: assert had one minor edge case due to final clauses with lists 2024-01-31 00:05:09 -05:00
microproofs 444bccf19c fix: change list_access_to_uplc to properly handle list discards 2024-01-30 23:53:33 -05:00
microproofs a83220c8d9 fix: module_name was being overrided by the moduleselect field 2024-01-30 23:52:50 -05:00
rvcas 3a534271e7
chore: update changelog 2024-01-30 12:35:50 -05:00
Kuly14 81e93b4309 Introduce cli aliases for check and build subcommands 2024-01-30 12:32:17 -05:00
rvcas 3a7a0c1971
chore: remove unused deps 2024-01-30 12:28:18 -05:00
rvcas 16c15ee48a
fix: nix stuff for @waalge 2024-01-29 18:37:49 -05:00
microproofs 8584adc1b7 chore: Release 2024-01-25 15:10:11 -05:00
microproofs ede6c22267 remove traces from test 89 2024-01-25 14:24:21 -05:00
microproofs 115ff61abe update changelog again 2024-01-25 14:22:45 -05:00
microproofs 78d2049d7b fix: Using the wrong match string for discards in FieldsExpose
Also need to return a lambda wrapped term from list_access_to_uplc under all conditions
2024-01-25 14:18:36 -05:00
rvcas 09ca2b4955
fix: nix stuff 2024-01-25 11:36:56 -05:00
rvcas defd36ad8c
chore: Release 2024-01-25 11:07:32 -05:00
rvcas 1ab6d050af
chore: bump pallas 2024-01-25 11:07:18 -05:00
rvcas 589bb9a4b3
chore: change how we depend on pallas 2024-01-24 21:26:48 -05:00
rvcas 9d563612f3
chore: prep changelog for release 2024-01-24 20:40:53 -05:00
microproofs 4c00c9e7de update changelog 2024-01-24 20:03:57 -05:00
microproofs 1431bec32f update changelog 2024-01-24 19:50:52 -05:00
microproofs b15e6c296b Add a few more expect cases to test 40 2024-01-24 16:29:40 -05:00
microproofs ae0b428658 update tests to account for new verbose tracing 2024-01-24 16:29:40 -05:00
microproofs 00e1942999 another test fix 2024-01-24 16:29:40 -05:00
microproofs dc61e11813 fix test 2024-01-24 16:29:40 -05:00
microproofs 36a0b317ad fix condition to account for tail presence 2024-01-24 16:29:40 -05:00
microproofs 3c81ebf137 updating more of the tests 2024-01-24 16:29:40 -05:00
microproofs 51f1f2b67f change redundant if branches 2024-01-24 16:29:40 -05:00
microproofs e523ae63f3 fixed some of the tests 2024-01-24 16:29:40 -05:00
microproofs 3a44c45b48 fix: one builtin error wasn't be caught with a messaged exception 2024-01-24 16:29:40 -05:00
microproofs eda4e259d6 minor fix and some refactoring on the if statements 2024-01-24 16:29:40 -05:00
microproofs 82fc82ceee fix: used wrong index in tupleAcessor 2024-01-24 16:29:40 -05:00
microproofs 956c3d6cf0 feat: refactor code gen to avoid builtin errors when tracing is turned on 2024-01-24 16:29:40 -05:00
KtorZ b50e4ab63a
Re-format and re-run all acceptance tests. 2024-01-20 10:44:16 +01:00
Matthias Benkort 9ee2d58ba3
Merge pull request #807 from aiken-lang/rvcas/various-fixes
Various Fixes for parsing and checking
2024-01-20 10:42:31 +01:00
KtorZ 50ebfc6090
remove wrongly committed acceptance test blueprints
Actually copy-pasted from 090
2024-01-20 10:38:40 +01:00
KtorZ 54a1b50138
Make behavior between curly- and paren-delimited blocks consistent.
Note that the formatter rewrite parens-block sequences as curly-block
  sequences anyway. Albeit weird looking syntax, they are valid
  nonetheless.

  I also clarified a bit the hints and description of the
  'illegal::return' error as it would mistakenly say 'function' instead
  of 'block'.
2024-01-20 10:37:07 +01:00
KtorZ bf96c3afd2
Add more tests & rename 'Invalid' -> 'Unfinished' 2024-01-20 10:26:33 +01:00
Matthias Benkort cb6fd59dbd
Fix minor typo in error label 2024-01-20 09:58:36 +01:00
rvcas 25a837ab3f
feat: parser and check fixes
- do not erase sequences if the sole expression is an assignment
- emit parse error if an assignment is assigned to an assignment
- do not allow assignments in logical op chains
2024-01-19 14:32:21 -05:00
KtorZ 8a90e9eda0
Improve behavior and reporting of tests expected to fail
Fixes #786.
2024-01-19 18:20:58 +01:00
Matthias Benkort 94f9fa9cab
Merge pull request #805 from waalge/waalge/fix-nix-build-pallas-hash
fix nix build with pallas hash
2024-01-19 16:10:58 +01:00
waalge 0f10b343f1 fix: nix build git version patch (untested) 2024-01-19 14:15:22 +00:00
waalge 51cc7d68eb fix: nix build requires githash 2024-01-19 14:13:32 +00:00
Matthias Benkort 1f6e719fde
Merge pull request #800 from aiken-lang/codegen-traces
Adding a new option to toggle codegen traces
2024-01-19 14:41:25 +01:00
KtorZ 2b4137dc24
Revert "minor refactor"
This reverts commit 21f0b3a6220fdafb8f6aad6855de89d8cdde0e1b.

  Rationale:

  The absence of clause guard was here done *on purpose*. Indeed,
  introducing a clause guard here forces either duplication or the use
  of a wildcard which is not "future proof".

  Should we make a change to that one day (e.g. add a new variant to
  TraceLevel), we won't get any compiler warning and we'll very likely
  forget to update that particular section of the code.

  So as much as possible, enforce complete pattern-match on variants
  make for code that is easier to maintain in the long-run.
2024-01-19 14:31:09 +01:00
microproofs af90b38bf8
minor refactor 2024-01-19 14:31:04 +01:00
KtorZ 6fa272bd34
Remove compiler-generated helper 'global' traces in compact mode.
Since there's no line number to show here, we don't have much choice. And the alternative of showing shorter traces as code is just ugly as hell.
2024-01-19 14:30:44 +01:00
KtorZ 42fdecf41f
Fix coloring output of multi-line traces. 2024-01-19 14:30:44 +01:00
KtorZ 858e45f3f3
Fill-in CHANGELOG. 2024-01-19 14:30:43 +01:00
KtorZ 3d131a5d09
Fix CLI docs for traces. 2024-01-19 14:30:16 +01:00
KtorZ 59c784778e
Convert span's start to line number + col
This requires to make line numbers a first-class citizen in the module
  hierarchy but it is fortunately not _too involved_.
2024-01-19 14:30:15 +01:00
KtorZ e67d5863a1
Introduce 'compact' trace level verbosity
For now, it only shows the span start. We'll change that in the next commit to show a line number and a column.
2024-01-19 14:30:15 +01:00
KtorZ 627c6b576e
Move line_numbers under 'aiken-lang'
And add some unit tests to ensure things are working properly.
2024-01-19 14:30:15 +01:00
microproofs f79b37d551
Replace 'bool' with 'TraceLevel' in codegen
Co-authored-by: KtorZ <matthias.benkort@gmail.com>
2024-01-19 14:30:15 +01:00
KtorZ d27ea98a8f
Rework tracing arguments to --keep-traces & --trace-level
This allows for a more fine-grained control over how the traces are showed. Now users can instrument the compiler to preserve only their user-defined traces, or the only the compiler, or all, or none. We also want to add another trace level on top of that: 'compact' to only show line numbers; which will work for both user-defined and/or compiler-generated traces.
2024-01-19 14:30:15 +01:00
microproofs 86146ae7f4
adding codegen traces 2024-01-19 14:30:14 +01:00
Matthias Benkort 81e29539c8
Merge pull request #803 from aiken-lang/780-possible-bug-with-test-github-action-version-generated-by-aiken-new
fix: aiken new github action version
2024-01-19 14:27:38 +01:00
Matthias Benkort e439cb5924
Merge pull request #804 from aiken-lang/fix-796-flat-bigint
Bump pallas dependencies to include flat bigint patch
2024-01-19 14:27:25 +01:00
KtorZ 0e2b8ae251
Bump pallas dependencies to include flat bigint patch
Fixes #796.
2024-01-18 18:26:21 +01:00
microproofs 1796147264 fix: aiken new github action version 2024-01-18 12:10:06 -05:00
Matthias Benkort 9f263c46f8
Merge pull request #801 from cardenaso11/nix-macos-build-libs
Add additional CoreServices dependency when building on macOS
2024-01-18 13:18:55 +01:00
card 328514182e add additional CoreServices dependency when building on macOS 2024-01-17 17:47:58 -05:00
microproofs 06672fce05 add new test 2024-01-13 19:29:34 -05:00
microproofs d26524048e fix: headlist builtin on assoc lists
implement chooseunit for 0 args
2024-01-13 19:29:34 -05:00
microproofs c7af27a6ba fix: generic edge case with tuples that allowed 2 tuples and 3 tuples to use the same monomorphized function.
Also massively reduced the space taken up by generics in scripts when using generics with list and tuples
2024-01-13 17:46:32 -05:00
Niels Mündler f934e87b1d Reuse "convert_tag_to_constr" 2024-01-13 13:23:58 -05:00
Niels Mündler cda1716d47 Unify construction of PlutusData objects from int + fields 2024-01-13 13:23:58 -05:00
Niels Mündler 742a728d53 Fix conformance test to make a point 2024-01-13 13:23:58 -05:00
Niels Mündler 316842876d Fix PlutusData Constr test case 2024-01-13 13:23:58 -05:00
Niels Mündler 4bd8ab890a Add reverse mapping for PlutusData constr 2024-01-13 13:23:58 -05:00
Niels Mündler 0ae631a1fe Fix parsing Constr PlutusData 2024-01-13 13:23:58 -05:00
microproofs 4a8fecb70a fix: satisfy clippy's demands 2024-01-11 14:53:02 -05:00
rvcas 8b62873ef5
fix(format): post trace sequences getting wrapped in curlies closes #781 2024-01-09 22:39:55 -05:00
microproofs ff462fa8ea don't need clippy macro anymore :) 2024-01-08 18:08:50 -05:00
microproofs f722af1149 fix: accidentally put quotes around tail_name 2024-01-08 18:08:50 -05:00
microproofs 2216f387c3 refactor: change codegen uplc to have more type safety
Also refactor list_access_to_uplc
2024-01-08 18:08:50 -05:00
Mitchell Turner 7992a50bec
Make foreign `Language` type publicly available (#793)
* Make foreign type public available

* Fix formatting
2024-01-08 13:31:21 -08:00
KtorZ 30a6b77116 Get rid of 'VoidMsg' in favor of an 'Option'. 2024-01-04 16:03:51 -05:00
microproofs c50a9cb5bd refactor: convert msgs to use AirMsg type instead of AirTree 2024-01-04 16:03:51 -05:00
microproofs 394cac86b8 feat: expect on a type now can take in a msg when in trace mode 2024-01-04 16:03:51 -05:00
microproofs 4fc65cc600 feat: change expect from data on constrs to take in a message term 2024-01-04 16:03:51 -05:00
microproofs 43e84d7af7 fixing gen_uplc tets 2024-01-04 16:03:51 -05:00
microproofs c7a1ff0959 refactor how tracing is popped off to be in one location in uplc_gen 2024-01-04 16:03:51 -05:00
microproofs 355e38d6e2 feat: expects now print the line of code that failed 2024-01-04 16:03:51 -05:00
microproofs 412945af3a update aiken code gen test 2024-01-04 16:03:51 -05:00
microproofs aa51ce3e3e feat: add code messages when using expects on constrs 2024-01-04 16:03:51 -05:00
microproofs 71cfb6f6af feat: Add specific messages for using expect with booleans
TODO: fill out the rest of the expects with messages
2024-01-04 16:03:51 -05:00
Niels Mündler 7b452c21f0 Fix formatting 2023-12-29 22:57:10 -05:00
Niels Mündler 4c60be368e Add command line option to shrink uplc 2023-12-29 22:57:10 -05:00
Niels Mündler b6acdde552 Use to_i64 for clarity 2023-12-19 12:20:10 -05:00
Niels Mündler d06f2f6008 Formatting 2023-12-19 12:20:10 -05:00
Niels Mündler eefd26c6fa Add acceptance tests for this tricky case 2023-12-19 12:20:10 -05:00
Niels Mündler fb56700bde Fix and re-enable pretty print test for bigint 2023-12-19 12:20:10 -05:00
Niels Mündler 89e518f878 Deduplicate code 2023-12-19 12:20:10 -05:00
Niels Mündler ba76c1d2cf Adjust acceptance tests and fix IData and UData 2023-12-19 12:20:10 -05:00
Niels Mündler 022503e254 Fix to_pallas_bigint 2023-12-19 12:20:10 -05:00
Niels Mündler 1b1636ab0e Fix parsing of negative bigint 2023-12-19 12:20:10 -05:00
Niels Mündler 0cfcd78039 Use more clear functions 2023-12-15 21:59:57 -05:00
Niels Mündler 8c619954d3 Add conformance test for big ints 2023-12-15 21:59:57 -05:00
Niels Mündler ceb6d63e95 Add parsing for big builtins 2023-12-15 21:59:57 -05:00
microproofs 6a10be3e82 chore: remove redundant clone 2023-12-15 21:58:02 -05:00
microproofs a0ec92897b chore: clean up pr 2023-12-15 21:58:02 -05:00
microproofs 2cd1379aec for now comment out curry code so the rest of the changes
can be merged to main
2023-12-15 21:58:02 -05:00
microproofs c0c9f2f432 commit latest changes 2023-12-15 21:58:02 -05:00
microproofs 058a190294 feat: implement curried tree pruning 2023-12-15 21:58:02 -05:00
microproofs 51079b8590 fix: builtin_force_reducer wasn't handling double forces correctly 2023-12-15 21:58:02 -05:00
microproofs 4015550f55 start testing the first stage of currying builtins 2023-12-15 21:58:02 -05:00
microproofs 249581e1bc chore: continuing progress on implementing currying optimization for builtins
Introduced some new abstractions to make a different number of args easier to deal with
2023-12-15 21:58:02 -05:00
microproofs 8fdedb754e chore: continue more on curry optimizations 2023-12-15 21:58:02 -05:00
microproofs 88e21449c5 chore: comment fixes 2023-12-15 21:58:02 -05:00
microproofs 5c688b1404 Feat: refactor optimizations to use tree traversal algorithm
This makes each optimization a single function that acts on an existing tree traversal function
2023-12-15 21:58:02 -05:00
rvcas 07122aaa88
feat: allow importing off validators in validators/tests/* 2023-12-11 18:27:08 -05:00
Niels Mündler b25e82ed36 Handle errors and format 2023-12-08 12:19:22 -05:00
Niels Mündler 772e73ae48 Fix parsing of hex encoded escaped bytes 2023-12-08 12:19:22 -05:00
Niels Mündler 3ac35f4e00 Make sure that new issue is covered by testcase 2023-12-08 12:19:22 -05:00
Niels Mündler d0bc782f75 Fix pretty prenting of strings in complex data structures 2023-12-08 12:19:22 -05:00
KtorZ 92488e535a
Fix type definitions for g1 & g2 elements. 2023-12-08 16:58:12 +01:00
microproofs 825e65d7a3 fix: zero arg functions were being compiled without the trace messages
Now traces are added before evaluating
2023-12-06 10:31:48 -05:00
rvcas 4b04517aba
fix: blst stuff is not happy on windows aarch64 2023-12-04 22:29:23 -05:00
rvcas 2647e4aae6
chore: Release 2023-12-04 22:14:03 -05:00
rvcas 0a1e0d7bee
feat: remove flat-rs crate and use it through pallas_codec 2023-12-04 22:01:51 -05:00
rvcas b17b7f287c
chore: update to pallas v0.20.0 2023-12-04 21:44:19 -05:00
rvcas 7c4cabada9
chore: add latest acceptance artifacts 2023-12-04 21:10:55 -05:00
rvcas 38e8255328
chore: update changelog 2023-12-04 21:04:55 -05:00
rvcas c50d4d1396
fix: forgot to handle None case for other_fun in validator 2023-11-29 21:24:30 -05:00
rvcas 1503b525b2
feat(lsp): implement quickfix for utf8 byte array is valid hex string warning 2023-11-28 21:02:15 -05:00
rvcas 858a9621fc
fix: due to how error code now get printed match_code for quickfix was always false 2023-11-28 21:00:17 -05:00
rvcas 1f411cde0e
chore: needless dbg 2023-11-28 20:59:23 -05:00
rvcas 2dab62857f
chore: useless rebinding 2023-11-28 19:46:08 -05:00
rvcas 832ca81a8c
fix(lsp): when desugaring and/or chains we should use the whole span of the chain for the generated BinOp locations 2023-11-28 19:19:56 -05:00
rvcas 7015a9badc
feat(lsp): hover support for the optional multi validator fn 2023-11-28 19:18:29 -05:00
rvcas 2159053cb5
fix: using the word pattern here reads better and applies more broadly like for lists 2023-11-28 16:15:24 -05:00
rvcas a46a7e82b7
feat: implement hover on when clause patterns 2023-11-28 16:13:08 -05:00
rvcas f7dd2de17b
feat: implement hover info for tuple, list, and contructor pattern elements 2023-11-28 16:12:37 -05:00
rvcas 6ce30bd949
fix: allow spread operator on positional constructors closes #677 2023-11-27 23:11:17 -05:00
rvcas d5820bb20a
fix: restore printing of some error messages
We rely on some errors to just bubble up and get printed.
By matching on result at the top level like this we blocked some
error messages from being able to be printed. For me this showed up
when `cargo run -- new thing/thing` printed nothing even when there
was an existing `thing` folder. It has already been the pattern for
sometime for some subcommands to handle calling process::exit(1) in
situations where it needs to handle error reporting more specially. It
may seem lame, hacky, or repetitive but it's easy to maintain and read.
2023-11-27 21:48:56 -05:00
rvcas 2980e8e21d
fix: use a distinct warning for discarded let assignments to avoid confusion closes #763 2023-11-27 21:23:10 -05:00
KtorZ c2725abcea
Merge branch 'aiken-watch' 2023-11-25 15:14:18 +01:00
KtorZ a23bc32fa2
Fill-in CHANGELOG. 2023-11-25 15:14:10 +01:00
KtorZ 40c0fa7d77
Add --watch flag to the 'build' and 'docs' commands too. 2023-11-25 15:14:09 +01:00
KtorZ 7645a9460f
Display error codes better.
This is a *slight* hack / abuse of the code() method as we are now
  doing a bit of formatting within that function. Yet, we only do so at
  the very top-level (i.e. project's Error) because we can't actually
  fiddle with how miette presents errors.
2023-11-25 15:14:09 +01:00
KtorZ 6c039708c3
Rework 'watch_project' to reuse 'with_project'
Also removed the 'clear' flag to do it by default instead of clogging
  the terminal view.

  This now works pretty nicely, and the logic is back under
  `aiken_project`.
2023-11-25 14:48:22 +01:00
KtorZ 777d30b8ac
Rework 'with_project' to avoid early process exit. 2023-11-25 13:26:24 +01:00
KtorZ 4adedaac15
Remove unnecessary 'Rc' in function signature. 2023-11-25 13:09:26 +01:00
KtorZ 1ca81ec133
Turn evaluation hints into strings earlier, to make project's Error thread-safe. 2023-11-24 09:44:05 +01:00
Pi Lanningham d04094560b
Add an example usage in the check command
Feel free to do this differently, I just implemented it because i'm actually using it heh
2023-11-24 08:37:54 +01:00
Pi Lanningham 4bb424ba78
Fix a small bug with the filtering 2023-11-24 08:37:54 +01:00
Pi Lanningham 5945a9515b
Disable the doctest, since I don't have an impl of EventListener I can use 2023-11-24 08:37:54 +01:00
Pi Lanningham 5068da3a17
Refactor into cargo-project
Rather than have this logic in the aiken binary, this provides a generic
mechanism to do "something" on file change events.  KtorZ is going to
handle wiring it up to the CLI in the best way for the project.

I tried to write some tests for this, but it's hard to isolate the
watcher logic without wrestling with the borrow checker, or overly
neutering this utility.
2023-11-24 08:37:54 +01:00
Pi Lanningham 771f6d1601
Formatting and check 2023-11-24 08:37:54 +01:00
Pi Lanningham 689a41ded4
Implement a basic watch command
This adds the following command
```
aiken watch
```

There are some open questions to answer, though:
- I really like the ergonomics of `aiken watch`; but it also makes sense
  as a flag to `aiken check` or `aiken build` etc.; should we just
  support the flag, the command, or both?
- Right now I duplicated the with_project method, because it forces
  process::exit(1); Should we refactor this, and if so, how?
- Are there other configuration options we want?
2023-11-24 08:37:53 +01:00
microproofs 45177cd08b fix: add missing type checks for the new bls primitives 2023-11-23 13:00:24 -05:00
microproofs 63f96d13ca fix: clippy warning 2023-11-22 19:17:45 -05:00
microproofs 78b0789cbc chore: unit test for pub in validator module warnings closes #681 2023-11-22 18:02:21 -05:00
rvcas abd18656e3 fix: unable to have newline after expect bool shortcut 2023-11-20 11:44:16 -05:00
rvcas 2ed91780f4 fix: call arg should be top level 2023-11-20 11:44:16 -05:00
rvcas 7118253401 fix: if branches, final_else, and anon fns should all be "top level" 2023-11-20 11:44:16 -05:00
rvcas 7680d33663 fix: panic in formatter when substracting u8 0 - 1 2023-11-20 11:44:16 -05:00
rvcas 6869f73033 fix: sequence formatting when not top level 2023-11-20 11:44:16 -05:00
microproofs 1567e42875 chore: fill in machine todos and cost model for case and constr
This allows for several more tests to pass
**Had to remove case-7 since it was incorrectly passing before**
2023-11-17 19:52:03 -05:00
rvcas 0382e5ce12
chore: this comment doesn't make sense 2023-11-17 18:41:28 -05:00
rvcas df992cba67 chore: remove check_type 2023-11-17 13:58:13 -05:00
rvcas 9ab458dcc6 feat: delay typemismatch errors in the machine runtime
to pass 2 of the conformance tests, we need to make sure
that we aren't typechecking builtin arguments as arguments
are applied. This switches push to by removing the call to check_type
and then reworking all the associated unwrap methods on Value
so that they return the same errors that were being returned before.
2023-11-17 13:58:13 -05:00
rvcas ed909055b5 chore: temp remove conformance tests that are failing 2023-11-15 15:55:56 -05:00
rvcas 308fb47e40 fix: don't panic on invalid hex strings 2023-11-15 15:55:56 -05:00
rvcas dfa0378404 chore: explain a todo in the machine 2023-11-15 15:55:56 -05:00
rvcas 3f8f624a7b fix(uplc): more whitespace characters 2023-11-15 15:55:56 -05:00
rvcas 58d98b3325 fix(uplc): parser should accept single quote in var name and comments 2023-11-15 15:55:56 -05:00
rvcas b6f6064aaf test: add all plutus conformance tests 2023-11-15 15:55:56 -05:00
rvcas b80db2f7f8 fix(bls): wrong types for equals functions 2023-11-15 15:55:56 -05:00
rvcas d53d2665b2 test(bls): g1 and g2 formatting 2023-11-15 15:55:56 -05:00
rvcas c910e0054e test(bls): constant parsing tests 2023-11-15 15:55:56 -05:00
rvcas 7073fd29b3 test(bls): literal parsing tests 2023-11-15 15:55:56 -05:00
microproofs 8b89ba3b93 feat: implement bls primitives in code gen 2023-11-15 15:55:56 -05:00
microproofs d51374aac1 feat: add conversion to data and from data for new primitive types 2023-11-15 15:55:56 -05:00
rvcas 3675762c3e feat(bls): aiken level g1 and g2 literals 2023-11-15 15:55:56 -05:00
rvcas 90aea6476a feat: uplc g1 and g2 literal parsing 2023-11-15 15:55:56 -05:00
rvcas 6ce85e1662 fix: add keccak to TryFrom<u8> 2023-11-15 15:55:56 -05:00
rvcas 49ae8152f8 feat(bls): add new aiken level builtins 2023-11-15 15:55:56 -05:00
rvcas 8a3a465237 feat(bls): add new types to aiken prelude 2023-11-15 15:55:56 -05:00
rvcas cdcd8172e6 feat(bls): pretty print mlresult type 2023-11-15 15:55:56 -05:00
rvcas 318ae6aad4 feat(bls): finish cost model 2023-11-15 15:55:56 -05:00
rvcas 5243c36ed6 feat(bls): add default costs for the new functions 2023-11-15 15:55:56 -05:00
microproofs 18db1c394a feat: Implemented builtin semantic versioning
feat: impl flat serialization and deserialization for bls constants
feat: started on cost models for the new builtins

Co-authored-by: rvcas <x@rvcas.dev>
2023-11-15 15:55:56 -05:00
rvcas f101581813 feat(bls): pretty printing for g1 and g1 element
Co-authored-by: Kasey White <kwhitemsg@gmail.com>
2023-11-15 15:55:56 -05:00
microproofs 0d2ac952d0 feat: implemented the Bls381-12 builtins and types
also implemented Keccak256 and Blake2b_224

TODO: cost model, flat serialization, pretty

Co-authored-by: rvcas <x@rvcas.dev>
2023-11-15 15:55:56 -05:00
microproofs 446ef11606 chore: finishing acceptance test 29
and updating acceptance test lock files
2023-11-08 14:31:44 -05:00
microproofs d50fb99b75 feat: add acceptance tests 28-30 2023-11-08 14:31:44 -05:00
microproofs 7d319077e6 chore: clean up validator comments and
commit script context test lockfile
2023-11-06 15:49:13 -05:00
microproofs 5d56d41a68 chore: update lock files for acceptance tests 2023-11-06 15:37:04 -05:00
microproofs 2f694b01cb chore: use insta snapshot for blueprint validator tests 2023-11-06 15:37:04 -05:00
microproofs 4eebd4628b chore: fix comment 2023-11-06 15:37:04 -05:00
microproofs 7427bac4a0 chore: remove unused code 2023-11-06 15:37:04 -05:00
microproofs 598ec5eaef Use a better algorithm for inlining single occurrences 2023-11-06 15:37:04 -05:00
microproofs 49bd4ba33d chore: Release 2023-10-25 19:00:03 -04:00
microproofs d2202a705c update changelog 2023-10-25 18:59:44 -04:00
microproofs 4dd17dacf3 chore: rename uplc builder builtins 2023-10-22 17:08:48 -04:00
waalge 3e283a59ec Split off builtin function builders
- sort alphabetically
- add some of the missing builtins used for ints
- comment on what is "correct" for future additions
- comment on the current remaining missing builtins
- comment on the current incoherent method names
2023-10-22 17:08:48 -04:00
KtorZ 46c58dbd61
Implement quickfixes for redundant imports. 2023-10-22 00:29:09 +02:00
KtorZ 28b699c86a
Merge unused imported constructors and unused imported type with unused imported value
This was somewhat weirdly done, with a boolean 'imported' set on the
  formers; but an explicit new warning for values. I don't see the point
  of distinguishing them so I just merged them all into a single
  warning.

  I have however preserved the 'UnusedType' and 'UnusedConstructor'
  warnings since they were ALSO used for unused private constructors or
  types.
2023-10-22 00:27:33 +02:00
KtorZ 5f8e256050
Present aiken-lsp & fill-in CHANGELOG 2023-10-21 21:39:30 +02:00
KtorZ 17832fc5af
Fix clippy warnings: remove redundant closures & guards. 2023-10-21 21:27:31 +02:00
Matthias Benkort d6f74b5932
Merge pull request #753 from aiken-lang/lsp/quickfix-unknowns
Lsp/quickfix unknowns
2023-10-21 21:23:56 +02:00
KtorZ c0513da032
Add quickfix for unknown constructors. 2023-10-21 14:24:47 +02:00
KtorZ f6eff7ec58
Fix incoherent 'UnknownVariable' being returned in type-check
I initially removed the 'UnkownTypeConstructor' since it wasn't used anywhere and was in fact dead-code. On second thoughts however, it is nicer to provide a slightly better error message when a constructor is missing as well as some valid suggestion. Prior to that commit, we would simply return a 'UnknownVariable' and the hint might suggest lowercase identifiers; which is wrong.
2023-10-21 14:10:45 +02:00
KtorZ 5986163ba7
Add quickfix for unknown alias & data types. 2023-10-21 13:57:06 +02:00
KtorZ d965467a53
Fix insertion of unqualified import when first
I previously missed a case and it causes qualified imports to be added at the end if they are lexicographically smaller than ALL other qualified imports. No big deal, but this is now fixed.
2023-10-21 13:56:15 +02:00
KtorZ c550b4766d
Implement quickfix for 'UnknownModule'. 2023-10-21 12:59:48 +02:00
KtorZ e48ac6b592
Relocate and refactor quickfix code into its own module
We're going to have more quickfixes, to it's best not to overload the
  'server' module. Plus, there's a lot of boilerplate around the
  quickfixes so we might want to factor it out.
2023-10-21 12:00:58 +02:00
KtorZ 763516eb96
Refactor and relocate document edits function for imports.
It's a bit 'off-topic' to keep these in aiken-lang as those functions are really just about lsp. Plus, it removes a bit some of the boilerplate and make the entire edition more readable and re-usable. Now we can tackle other similar errors with the same quickfix.
2023-10-21 11:31:01 +02:00
KtorZ 699d0a537c
Use (untyped) AST to find the right insert location for imports.
This removes the need to rely on the formatter to clear things up
  after insert a new import. While this is not so useful for imports, I
  wanted to experiment with the approach for future similar edits (for
  example, when suggesting an inline rewrite).
2023-10-21 10:43:00 +02:00
KtorZ 66ade8e3e3
Implement simple code action quickfix for unknown variable. 2023-10-20 18:01:07 +02:00
KtorZ c4221730bf
Define 'ExtraData' trait for errors
This should allow passing some extra information to LSP diagnostic in order to provide quickfix actions, such as auto-imports.
2023-10-20 18:00:12 +02:00
KtorZ 41e26b216b
Some LSP improvements regarding hovering
- Resolve module select properly
  - Add some type annotations to _some patterns_ such as assignments
2023-10-19 20:04:10 +02:00
microproofs a08405c607 changelog additions 2023-10-17 12:36:13 -04:00
rvcas e5801f9c19
feat: support doc comments for functions args and validator params
- Add support to the formatter for these doc comments
- Add a new field to `Arg` `doc: Option<String>`
- Don't attach docs immediately after typechecking a module
  - instead we should do it on demand in docs, build, and lsp
  - the check command doesn't need to have any docs attached
  - doing it more lazily defers the computation until later making
    typechecking feedback a bit faster
- Add support for function arg and validator param docs in
  `attach_module_docs` methods
- Update some snapshots
- Add put_doc to Arg

closes #685
2023-10-16 13:38:23 -04:00
rvcas 10b9dc2042
chore: remove unused constants 2023-10-13 16:56:03 -04:00
microproofs 596ce49327 fix: mixed up operators for ConstAboveDiagonal and ConstBelowDiagonal
Closes #618
2023-10-13 11:40:07 -04:00
rvcas e8bcbecf31
chore: avoid cloning name 2023-10-12 17:50:44 -04:00
rvcas 55f89a7ff4
fix: incorrect 'unused::constructor'
`ExprTyper` was not incrementing the usage of a constructor
when infering `RecordAccess`.

closes #554
2023-10-12 17:44:57 -04:00
rvcas 52dfc13f8f
chore: explain a weird if condition 2023-10-12 17:24:11 -04:00
microproofs c764a6f99c fix: reset option should not reset special functions in only a multivalidator 2023-10-07 19:42:24 -04:00
microproofs 4649a5a9d2 fix: don't reset the used special functions 2023-10-07 19:42:24 -04:00
microproofs 8964675670 feat: Add tracing for common multivalidator issues 2023-10-07 19:42:24 -04:00
microproofs 68d9a21c6a commit current lock files 2023-10-07 19:42:24 -04:00
microproofs a86f08c6d1 update tests for new trace reduction 2023-10-07 19:42:24 -04:00
microproofs 7a6ddc45a0 feat: Rework codegen traces to prevent repeated messages from taking up uplc script space 2023-10-07 19:42:24 -04:00
microproofs 44021cde19 Detect when fields_expose is unnecessary in clause_pattern 2023-10-07 19:42:24 -04:00
microproofs 9335522df4 Make change @ktorz suggested 2023-10-07 19:42:24 -04:00
microproofs 98cb01413b chore: prevent strings from being inlined and replicated 2023-10-07 19:42:24 -04:00
KtorZ c2bf6e5682
Add missing keywords to documentation generator. 2023-10-06 14:46:34 +02:00
KtorZ a524836c94
Add compiler version & system information to panic error message
So that we stop constantly asking people about it.
2023-10-06 14:46:11 +02:00
KtorZ 524d0dadf5
Add compiler's version to blueprint. 2023-10-06 14:17:55 +02:00
KtorZ d56d5180cf
Move compile-time build info to aiken-project
So that we can use it as part of the blueprints.
2023-10-06 14:08:47 +02:00
rvcas bd61a2ddf3
chore: adjust git ignore 2023-10-04 17:09:18 -04:00
microproofs 8a1c824dd7 chore: add specific error for when the validator returns false 2023-10-04 11:08:22 -04:00
rvcas 78ff6cf178 chore: update changelog 2023-10-03 01:17:15 -04:00
rvcas 135dbd8335 feat: handle pipe fn infer TODOs
This improves error messages for `a |> b(x)`.

We need to do a special check when looping over the args
and unifying. This information is within a function that does not belong
to pipe typer so I used a closure to forward along a way to add
metadata to the error when the first argument in the loop has a
unification error. Simply adding the metadata at the pipe typer
level is not good enough because then we may annotate regular
unification errors from the args.
2023-10-03 01:17:15 -04:00
microproofs fb6cbbec8b chore: Release 2023-09-29 22:08:09 -04:00
microproofs d131ec563b update changelog 2023-09-29 22:07:19 -04:00
microproofs add513790d hotfix: cyclic functions hoisted as a dependency used the wrong key to modify its own cyclic_calls 2023-09-29 22:01:43 -04:00
microproofs 82ceb5b696 chore: Release 2023-09-29 19:39:28 -04:00
microproofs 4aa5bda9eb update changelog 2023-09-29 19:37:44 -04:00
microproofs 83f0dd2cbe chore: fix blueprint validator tests 2023-09-29 17:47:39 -04:00
microproofs fb2ca0e3e0 inline is actually cheaper in a lot of cases 2023-09-29 17:47:39 -04:00
microproofs a2068ff062 fix: optmizer should never inline recursive functions
chore: some renames
2023-09-29 17:47:39 -04:00
microproofs 335560b81f Add placeholders for new terms in optimize
Update tests to check optimization is applied properly
2023-09-29 17:47:39 -04:00
microproofs 5e2a78173b optimization: increase the cases that inline_basic_reduce can handle 2023-09-29 17:47:39 -04:00
waalge 4c278e2f9d Use unknown when git dirty
Co-authored-by: Matthias Benkort <5680256+KtorZ@users.noreply.github.com>
2023-09-28 13:30:34 -04:00
waalge dbd4fe2aab fix rust version 2023-09-28 13:30:34 -04:00
waalge 14a6141046 shortRev 2023-09-28 13:30:34 -04:00
waalge 37ec2b121b rev 2023-09-28 13:30:34 -04:00
waalge f5fb84f104 try patch 2023-09-28 13:30:34 -04:00
waalge 3c11c95e01 insert into rust 2023-09-28 13:30:34 -04:00
waalge b4837c7ee6 add rev 2023-09-28 13:30:34 -04:00
microproofs 3fc469b7c7 update changelog 2023-09-28 01:05:05 -04:00
microproofs 47596f0324 feat: Remove tuple_index and record_access in favor of faster more direct functions for
accessing an item in a tuple or a field in a record
2023-09-28 01:05:05 -04:00
microproofs 1bcc9e8524 fix: expect on tuples from data now checks for no more items after the last 2023-09-26 12:49:50 -04:00
microproofs 8e75007a5f changelog: remove accidental duplicated Fixed 2023-09-25 21:16:19 -04:00
microproofs 38d15c677f Update changelog 2023-09-25 21:16:19 -04:00
microproofs 1ca3499128 chore: rename type 2023-09-25 21:16:19 -04:00
microproofs eb0b4dd6d8 update lock files 2023-09-25 21:16:19 -04:00
microproofs b8737a1021 add one more test for unbound generics 2023-09-25 21:16:19 -04:00
microproofs 534eb62a07 fix: There was a stack overflow due to passing unbound types to a function 2023-09-25 21:16:19 -04:00
microproofs 1cab479b81 fix: dependency hoisting for cyclic functions
Add more tests
2023-09-25 21:16:19 -04:00
microproofs 2f80d07132 fix: minor stuff including fixing the var name used in modify_cyclic_calls
and carefully controling the functions we add to sorted dependencies
2023-09-25 21:16:19 -04:00
microproofs f4310bcf33 feat: finished up mutual recursion
Now we "handle" vars that call the cyclic function.
That includes vars in the cyclic function as well as in other functions
"handle" meaning we modify the var to be a call that takes in more arguments.
2023-09-25 21:16:19 -04:00
microproofs ae3053522e feat: Update cyclic functions to be aware of being in a cycle.
Finish the creation of cyclic functions
The last part is to update vars that call into a function in the cycle
2023-09-25 21:16:19 -04:00
microproofs 794fc93084 remove unused structs 2023-09-25 21:16:19 -04:00
microproofs 0b38855ce4 add new enum for hoistablefunctions 2023-09-25 21:16:19 -04:00
microproofs ced818c455 checkpoint commit 2023-09-25 21:16:19 -04:00
microproofs 0fb9837ddf chore: change UserFunction to HoistableFunction to prepare for mututal recursion 2023-09-25 21:16:19 -04:00
KtorZ 984237075a Add new acceptance test scenario: 066
Mutua recursion.
2023-09-25 21:16:19 -04:00
microproofs 74b8ab62b2 chore: add comments 2023-09-25 21:16:19 -04:00
microproofs a4aa51ed2d WIP: first part of mutual recursion is done.
This involves creating the function definition and detecting cycles.
The remaining part is to "fix" the call sites
of the mutually recursive functions
2023-09-25 21:16:19 -04:00
Chris Gianelloni ecc5769c64 fix: restore static binary builds
Signed-off-by: Chris Gianelloni <cgianelloni@applause.com>
2023-09-20 16:25:45 -04:00
microproofs 5b018b7c07 test: add a test around a tuple of constructors when with many conditions 2023-09-20 16:20:42 -04:00
rvcas 4ca8681ca0
chore: commit example lock files 2023-09-20 13:26:49 -04:00
rvcas 1ecdf38842
fix: release 2023-09-20 13:03:38 -04:00
KtorZ ee4001d2c8
chore: Release 2023-09-20 18:03:46 +02:00
KtorZ 91d4cb9b12
Fix a date in the CHANGELOG for 0.17.0 2023-09-20 18:02:39 +02:00
microproofs 4650c64f6b update changelog 2023-09-20 11:51:01 -04:00
KtorZ f379039efc
Fix record shorthand causing parsing ambiguity in if/else expressions.
Fixes #735.
2023-09-15 09:41:00 +02:00
rvcas 1dea348a2e
chore: rust rover error 2023-09-13 21:29:05 -04:00
rvcas 7b915b7dcf
chore: allow clippy::arc_with_non_send_sync in tests 2023-09-13 19:07:45 -04:00
rvcas d808197507
chore: clippy fix 2023-09-13 18:17:59 -04:00
rvcas bc0824f4eb
chore: new aiken.lock files for examples 2023-09-13 18:17:40 -04:00
rvcas 9a4f181a0f
chore: clippy fix 2023-09-13 17:19:31 -04:00
KtorZ 06347c3efa Add CHANGELOG entry. 2023-09-13 17:17:32 -04:00
KtorZ c711a97e69 Throttle calls to package registry for version resolution
The 'HEAD' call that is done to resolve package revisions from
  unpinned versions is already quite cheap, but it would still be better
  to avoid overloading Github with such calls; especially for users of a
  language-server that would compile on-the-fly very often. Upstream
  packages don't change often so there's no need to constantly check the
  etag.

  So we now keep a local version of etags that we fetched, as well as a
  timestamp from the last time we fetched them so that we only re-fetch
  them if more than an hour has elapsed. This should be fairly resilient
  while still massively improving the UX for people showing up after a
  day and trying to use latest 'main' features.

  This means that we now effectively have two caching levels:

  - In the manifest, we store previously fetched etags.
  - In the filesystem, we have a cache of already downloaded zip archives.

  The first cache is basically invalidated every hour, while the second
  cache is only invalidated when a etag changes. For pinned versions,
  nothing is invalidated as they are considered immutable.
2023-09-13 17:17:32 -04:00
KtorZ 15efeb3069 Remove unused code & data-type 'UseManifest'
If it's unused, it shall be gone. It obfuscate what functions are
  doing and require managing extra complexity for no reason.
2023-09-13 17:17:32 -04:00
KtorZ 5381762e50 Rework logs around dependency fetching. 2023-09-13 17:17:32 -04:00
KtorZ 76ff09ba0e Ensure that version resolution works offline
And so, even for unpinned package. In this case, we can't do a HEAD request. So we fallback by looking at what's available in the cache and using the most recently downloaded version from the cache. This is only a best effort as the most recently downloaded one may not be the actual latest. But common, this is a case where (a) someone didn't pin any version, (b) is trying to build on in an offline setup. We could possibly make that edge-case better but, let's see if anyone ever complains about it first.
2023-09-13 17:17:32 -04:00
KtorZ 87087a1811 Always check package status when version is not pinned
When the version isn't a git sha or a tag, we always check that we got
  the last version of a particular dependency before building. This is
  to avoid those awkward moments where someone try to use something from
  the stdlib that is brand new, and despite using 'main' they get a
  strange build failure regarding how it's not available.

  An important note is that we don't actually re-download the package
  when the case occurs; we merely check an HTTP ETag from a (cheap) 'HEAD'
  request on the package registry. If the tag hasn't changed then that
  means the local version is correct.

  The behavior is completely bypassed if the version is specified using
  a git sha or a tag, as here, we can assume that fetching it once it
  enough (and that it can change). If a package maintainer force-pushed
  a tag however, there may be discrepency and the only way around that
  is to `rm -r ./build`.
2023-09-13 17:17:32 -04:00
KtorZ 3c3a7f2423 Define 'is_git_sha_or_version' to assert whether a version is 'immutable'
Best-effort to assert whether a version refers is a git sha digest or a tag. When it is, we
avoid re-downloading it if it's already fetched. But when it isn't, and thus refer to a branch,
we always re-download it. Note however that the download might be short-circuited by the
system-wide package cache, so a download doesn't actually mean a network request.

The package cache is however smart-enough to assert whether a package in the cache must be
re-downloaded (using HTTP ETag). So this is mostly about delegating the re-downloading logic to
the global packages cache.
2023-09-13 17:17:32 -04:00
KtorZ 65fb3a640a Remove dead-code. 2023-09-13 17:17:32 -04:00
KtorZ a72628a4dc Auto-derive 'Debug' trait instance for types in deps
Actually useful to debug / troubleshoot things.
2023-09-13 17:17:32 -04:00
microproofs a45001376d fix: is_record was used incorrectly in code gen,
the real solution was to look up the datatype and check constructors length
2023-09-13 00:33:02 -04:00
microproofs d042d55d42 fix clippy warnings in code gen 2023-09-12 21:25:05 -04:00
KtorZ 9782c094b7
Fix clippy suggestions. 2023-09-08 16:21:07 +02:00
KtorZ 8ba5946c32
Preserve escape sequence after formatting
Bumped into this randomly. We do correctly parse escape sequence, but
  the format would simply but the unescaped string back on save. Now it
  properly re-escapes strings before flushing them back. I also removed
  the escape sequence for 'backspace' and 'new page' form feed as I
  don't see any use case for those in an Aiken program really...
2023-09-08 12:12:15 +02:00
KtorZ 5cfc3de7bf
Add CODEOWNERS 2023-09-08 10:21:33 +02:00
rvcas 6b70292dfb
chore: cargo fmt 2023-09-06 21:10:50 -04:00
rvcas 1de7b2866a
feat(cli): add --deny to build, check, and docs
This is useful for CI, where people that may have
a stricter workflow want to force CI to fail if any warnings
are detected.
2023-09-06 17:19:44 -04:00
microproofs 819a0a20e6 add tests for case and constr
Fix a minor issue with decoding order
2023-09-03 11:52:49 -04:00
microproofs c9b01ab365 chore: fill in cost model
test: Add case and constr eval tests
2023-09-03 11:52:49 -04:00
microproofs 85901dc141 chore: update cost model with placeholders for new terms to pass tests 2023-09-03 11:52:49 -04:00
microproofs 40e1d39f8b Add placeholders for cost model 2023-09-03 11:52:49 -04:00
microproofs 33d6d3049e add compute for the new terms constr and case 2023-09-03 11:52:49 -04:00
microproofs e566c4e1de feat(uplc): add Case and Const terms
- parsering
- interning
- flat encoding and decoding
- pretty printing
- debruijn conversion

Co-authored-by: Lucas Rosa <x@rvcas.dev>
2023-09-03 11:52:49 -04:00
rvcas dfe433ea46
fix: trim whitespace when loading hex strings from files closes #720 2023-08-31 18:22:09 -04:00
rvcas 097d1fa893
chore: update changelog 2023-08-31 18:01:52 -04:00
rvcas 437a95bfe8
fix: behave like rust with hyphens closes #722 closes #690 2023-08-31 18:00:21 -04:00
rvcas a87a8a7b35
chore: update changelog 2023-08-31 17:41:36 -04:00
rvcas dca09811c1
fix: empty records crashing code gen closes #728 2023-08-31 17:39:38 -04:00
rvcas fb967d4c7b
fix: uplc formatter of Data closes #716 2023-08-31 17:20:48 -04:00
microproofs 51c44c6a30 fix: add an assert for better error messages when doing empty types 2023-08-30 13:50:37 -04:00
waalge cd3a02416f chore: rm unused pub function 2023-08-29 22:30:06 -04:00
waalge 756e16c14b fix: rename assert to expect 2023-08-29 22:30:06 -04:00
microproofs baa6917af5 Fix: Change type map length assert to check for greater than equals instead of equals to argument length 2023-08-29 21:59:15 -04:00
Matthias Benkort d01766d735
Merge pull request #721 from waalge/waalge/rm-mut
rm unnecessary mut
2023-08-29 21:00:05 +02:00
Chris Gianelloni 67986d9416 chore: build static binaries for Linux/Windows
Signed-off-by: Chris Gianelloni <cgianelloni@applause.com>
2023-08-29 00:46:50 -04:00
waalge d4b9f22ac3 rm unnecessary mut 2023-08-26 16:30:44 +00:00
rvcas 1715496d5b
chore: update resolver in virtual workspace 2023-08-24 15:51:39 -06:00
rvcas 0e7f1597bf
chore: add release instructions in contributing.md 2023-08-24 15:43:26 -06:00
rvcas b075d85b40
chore: Release 2023-08-24 15:05:12 -06:00
rvcas b3494a7f63
chore: fix versions 2023-08-24 15:04:52 -06:00
rvcas a7062ccb88
chore: fix versions 2023-08-24 15:04:19 -06:00
rvcas 747e057d05
fix: tags 2023-08-24 15:00:09 -06:00
KtorZ 379368c530
Fix clippy. 2023-08-22 13:30:30 +02:00
KtorZ 2f0211a7b1
Bump all version manually because cargo workspaces didn't work. 2023-08-22 13:27:10 +02:00
KtorZ 780a61e3e8
Release 1.0.16-alpha
aiken@1.0.16-alpha

Generated by cargo-workspaces
2023-08-22 13:18:48 +02:00
KtorZ d3fe241ccd
Wrap-up CHANGELOG 2023-08-22 13:14:35 +02:00
KtorZ 7883aff5f7
revert 619b73d03e
There's really no scenario where we want to generate boilerplate that
  always end up being removed. In particular, the boilerplate breaks
  tutorial as it generate conflicting validators in the blueprint.

  The only argument in favor of the boilerplate is to serve as example
  and show people some syntax reminder. However, this is better done in
  the README or on the user manual directly.
2023-08-22 12:59:36 +02:00
microproofs 89c55a23fa chore: Release 2023-08-19 20:17:00 -04:00
microproofs 0eec4c188a update changelog for v1.0.15 2023-08-19 20:11:24 -04:00
microproofs 084b900b2a change: traverse_with_tree now has a boolean to determine when with is called
fix: Opaque types are now properly handled in code gen (i.e. code gen functions, in datums/redeemers, in from data casts)
chore: add specific nested opaque type tests to code gen
2023-08-19 20:07:37 -04:00
KtorZ c6f764d2db Refresh Cargo.lock & fill-in CHANGELOG. 2023-08-19 13:39:39 -04:00
KtorZ 139226cdab Support interactive blueprint parameter application. 2023-08-19 13:39:39 -04:00
KtorZ c1b8040ae2 Add helper for splitting a long line into multiple lines. 2023-08-19 13:39:39 -04:00
KtorZ 961e323c36 Enable iterating over validator's parameters with a callback
This is how we'll construct parameters interactively. We need to lookup the definition, and provide a data representation for it.
2023-08-19 13:39:39 -04:00
KtorZ 051e9a6851 Add some utility functions for displaying Term/PlutusData
This is useful with the blueprint stuff, where Term are often just plain PlutusData.
2023-08-19 13:39:39 -04:00
rvcas 690e41261e
chore: Release 2023-08-16 23:30:21 -04:00
rvcas be20426329
chore: update changelog 2023-08-16 23:16:56 -04:00
rvcas f5a49c4df4
fix: aliased import of single type throws compiler error closes #707 2023-08-16 23:15:51 -04:00
rvcas 6d90c27587
chore: update changelog 2023-08-16 23:06:53 -04:00
rvcas 2600937447
chore: cargo fmt 2023-08-16 22:56:22 -04:00
rvcas b138cb0ccd
chore: update changelog 2023-08-16 22:55:59 -04:00
logicalmechanism 649039c993 tx simulate still need fee work 2023-08-16 22:37:00 -04:00
logicalmechanism 050c41c8dc tx simulate returns a vector of exbudgets now 2023-08-16 22:37:00 -04:00
Ariady Putra 8cf92ce8ed `aiken new`: Try to get the latest tag of stdlib 2023-08-16 22:30:15 -04:00
microproofs c95f43ae07 add one more test 2023-08-16 21:59:25 -04:00
microproofs 20aa54b5ca fix: last test fixed 2023-08-16 21:59:25 -04:00
microproofs a45e04fd9b fix: using the wrong var for pattern matching 2023-08-16 21:59:25 -04:00
microproofs 2456801b17 fix list clauses with guards and add more tests 2023-08-16 21:59:25 -04:00
rvcas f4d0f231d7
test: fix acceptance tests 2023-08-16 14:52:06 -04:00
rvcas 80e4a5c6a2
chore: remove build folder 2023-08-16 14:17:33 -04:00
rvcas ae216bd932
test(ci): run examples too 2023-08-16 13:33:54 -04:00
rvcas 6ecb3f08b0
chore: default stdlib on new is 1.5.0 2023-08-16 13:24:10 -04:00
rvcas 0ff64e3bac test: check and format tests for logical op chain 2023-08-15 09:58:35 -04:00
rvcas e14d51600f feat(format): logical op chain 2023-08-15 09:58:35 -04:00
rvcas 2c2f3c90fb feat: new snapshots 2023-08-15 09:58:35 -04:00
rvcas 05eb281f40 chore: can safely remove this at this point 2023-08-15 09:58:35 -04:00
rvcas e4ef386c44 feat(tipo): inference for and/or chains 2023-08-15 09:58:35 -04:00
rvcas ab3a418b9c feat(parser): add support for and/or chaining 2023-08-15 09:58:35 -04:00
microproofs 4a1ae9f412 set eval to public 2023-08-12 16:42:23 -04:00
microproofs ca4a9fcd3d chore: make eval function and SlotConfig public 2023-08-11 20:33:08 -04:00
microproofs 8af253e1df chore: make slot_to_begin_posix_time a public function 2023-08-11 20:05:22 -04:00
microproofs 2f7784f31e chore: update changelog
expecting a type on List<Data> from data now only checks that type is a list and not each element
2023-08-10 23:01:46 -04:00
microproofs eda388fb29 test(aiken-lang): add a new test for list edge case in when clause patterns 2023-08-08 20:47:35 -04:00
microproofs 252f68de17 fix clippy 2023-08-07 19:08:18 -04:00
microproofs 367dabafb5 fix: update last 2 tests for new recursion optimization 2023-08-07 19:06:00 -04:00
Pi Lanningham f464eb3702 Cargo fmt + clippy, with latest rust 2023-08-07 19:00:39 -04:00
Pi Lanningham 0d99afe5e2 Cargo fmt 2023-08-07 19:00:39 -04:00
microproofs 90c7753201 update tests for new recursion optmization 2023-08-07 19:00:39 -04:00
microproofs 65984ed15b fix: move where we call the with in traverse_tree_with 2023-08-07 19:00:39 -04:00
Pi Lanningham dba0e11ba7 Add other shadowing cases 2023-08-07 19:00:39 -04:00
Pi Lanningham fc948f0029 Add the same optimization to dependent functions
I originally didn't add this because I thought this was mutually
recursive functions, which I couldn't picture how that would work;

I refactored all this logic into modify_self_calls, which maybe needs a
better name now.

Perf gain on some stdlib tests (line concat tests) is 93%!!
2023-08-07 19:00:39 -04:00
Pi Lanningham c45caaefc8 Rudimentary implementation
Adds an identify_recursive_static_params; doesn't handle all shadowing cases yet
2023-08-07 19:00:39 -04:00
Pi Lanningham 09f889b121 Add codegen for recursive statics case
We also flip the recursive_statics fields to recursive_nonstatics; This makes the codegen a little easier.  It also has a hacky way to hard code in some recursive statics for testing
2023-08-07 19:00:39 -04:00
Pi Lanningham 586a2d7972 Add recursive_static_params to AIR
Any methods to a recursive function that are unchanged and forwarded
don't need to be applied each time we recurse; instead, you can
define a containing lambda, reducing the number of applications
dramatically when recursing
2023-08-07 19:00:39 -04:00
microproofs 71a941e0b0 Update changelog 2023-08-07 12:11:39 -04:00
microproofs 6254eeb2ed add acceptance test 88 2023-08-07 12:02:44 -04:00
microproofs f7d278a472 fix: 2 acceptance tests were throwing errors due to exhaustiveness checker 2023-08-07 12:02:44 -04:00
microproofs 1d9878c5ee fix: code gen tests now up to date using trace
fix: Formatter should take ErrorTerm and return "fail"
fix: fail with no reason should just return ErrorTerm
2023-08-07 12:02:44 -04:00
microproofs 624fdee9ea keep traces in tests 2023-08-07 12:02:44 -04:00
microproofs 36c80f36c1 fix tests 2023-08-07 12:02:44 -04:00
microproofs 29599879b2 one minor tail fix in clause pattern 2023-08-07 12:02:44 -04:00
microproofs 6a1b2db698 use retain instead of position 2023-08-07 12:02:44 -04:00
microproofs 7bf22fa58b fix multivalidator issue 2023-08-07 12:02:44 -04:00
microproofs 281a8363c0 fixes to tuples and usage of discard.
Also a fix to tail and its type in when list pattern matches
2023-08-07 12:02:44 -04:00
microproofs bfa4cc2efc fix: some function dependency tree path was not being updated in order
fix: revert to old implicit way of casting to data for now
2023-08-07 12:02:44 -04:00
microproofs a45ff692a6 last changes for today 2023-08-07 12:02:44 -04:00
microproofs db79468435 remove old stuff 2023-08-07 12:02:44 -04:00
microproofs aca79bd728 remove warning 2023-08-07 12:02:44 -04:00
microproofs 3189a60bdb fixes to how we sort dependencies.
Also update dependency path based on a functions path.
2023-08-07 12:02:44 -04:00
microproofs 80b950b8aa fix edge case with assign and pattern matching 2023-08-07 12:02:44 -04:00
microproofs 186e1235fd checkpoint 2023-08-07 12:02:44 -04:00
microproofs 1ee7492f1f fix tuple clause 2023-08-07 12:02:44 -04:00
microproofs 49a0a91103 fix tests again 2023-08-07 12:02:44 -04:00
microproofs f5c7d222aa optmization fix 2023-08-07 12:02:44 -04:00
microproofs 5aecb96668 constants are back. I had broke them when switching how data casting works 2023-08-07 12:02:44 -04:00
microproofs 0b8266dfd1 some type conversion fixes 2023-08-07 12:02:44 -04:00
microproofs 02948616cd some more fixes involving clauses 2023-08-07 12:02:44 -04:00
microproofs a689b8748f fix: working on minor edge cases
fix: zero arg function dependencies should not count as hoisted
fix: tuple index was receiving the wrong type
2023-08-07 12:02:44 -04:00
microproofs 4e3ced5b75 fix and clean up tests and handle
one edge case on rearrange clauses
2023-08-07 12:02:44 -04:00
microproofs 018453f6b1 fix expect on tuple type using the wrong internal type 2023-08-07 12:02:44 -04:00
microproofs f03ed41e03 fix some unnecessary lambdas in assign 2023-08-07 12:02:44 -04:00
microproofs 03dd13dc7d fixing list condition edge cases and clean up rearrange list clauses 2023-08-07 12:02:44 -04:00
microproofs e8fa8f5423 fixing list clause issues 2023-08-07 12:02:44 -04:00
microproofs c6f90a999b checkpoint 2023-08-07 12:02:44 -04:00
microproofs 389699f485 fix to subject type for assignment on single clause 2023-08-07 12:02:44 -04:00
microproofs dcb3a9b45b some type and expect fixes 2023-08-07 12:02:44 -04:00
microproofs 3545bad3c4 fix typing to constr 2023-08-07 12:02:44 -04:00
microproofs 52ebc9b6c1 some more fixes 2023-08-07 12:02:44 -04:00
microproofs 58b327e5b3 fixing bugs and edge cases 2023-08-07 12:02:44 -04:00
microproofs 2f4319f162 fix: tuples and list patterns had a few issues 2023-08-07 12:02:44 -04:00
microproofs 960a15c4ec checkpoint - fixing tests and stuff 2023-08-07 12:02:44 -04:00
microproofs 72b6f0f847 all but six tests passing 2023-08-07 12:02:44 -04:00
microproofs 6eeb282dee Now code gen is finished and we just have testing 2023-08-07 12:02:44 -04:00
microproofs 518bea5be4 feat: fixed up generate and generate test
last step is checking on uplc code gen
2023-08-07 12:02:44 -04:00
microproofs 18ea44adb0 chore: rename unwrapData and wrapData
add validator cast function for extra validator params
2023-08-07 12:02:44 -04:00
microproofs 55dd1a1a56 out with the old code and in with the air tree 2023-08-07 12:02:44 -04:00
microproofs 02ce3761ae final checkpoint 2023-08-07 12:02:44 -04:00
microproofs 8641c305f4 feat: airtree now hoists function. Now all that is left is finishing uplc gen 2023-08-07 12:02:44 -04:00
microproofs 5ad8b520fd checkpoint 2023-08-07 12:02:44 -04:00
microproofs 5a51764cff remove some warnings 2023-08-07 12:02:44 -04:00
microproofs a099c01734 feat: add support for hoisting code gen functions
fix: code gen vars should be module functions
fix: missed a recursive call in do_find_air_tree_node under binop
2023-08-07 12:02:44 -04:00
microproofs c0f09856d3 feat: Here's a first, we hoisted some user functions onto the validator 2023-08-07 12:02:44 -04:00
microproofs 62660e04b5 checkpoint;
Remaining work is on function hoisting. Functions have been defined and monomorphized
2023-08-07 12:02:44 -04:00
microproofs ae9de11e77 big checkpoint:
feat: add monomorphize and other useful tree function abstractions
feat: started testing function hositing result so far
2023-08-07 12:02:44 -04:00
microproofs 947c118175 checkpoint 2023-08-07 12:02:44 -04:00
microproofs 9704cafefe a checkpoint for function hoisting start and type fix 2023-08-07 12:02:44 -04:00
microproofs 55ae708e3e checkpoint: start on function hoisting 2023-08-07 12:02:44 -04:00
microproofs 2b7e7ead1c feat: add support for validator arguments
feat: finish expect type on data constr
fix: tuple clause was exposing all items regardless of discard
fix: tuple clause was not receiving complex_clause flag
fix: condition for assert where constructor had 0 args was tripping assert
fix: had to rearrange var and discard assignment to ensure correct val is returned
fix: binop had the wrong type
2023-08-07 12:02:44 -04:00
microproofs 7d4e136467 checkpoint 2023-08-07 12:02:44 -04:00
microproofs fd83c9a739 feat: fix up generic type functions to work with the new air tree functions
chore: remove commented code
2023-08-07 12:02:44 -04:00
microproofs b3714ca9d0 fix: list clause guard for final clause needs to use list accessor 2023-08-07 12:02:44 -04:00
microproofs 2c61ecd4bb feat: finish up nested clauses 2023-08-07 12:02:44 -04:00
microproofs a3afb62861 chore: fixing nested clauses to match aiken stack air 2023-08-07 12:02:44 -04:00
microproofs 95af421f95 feat: finish tuple conditions 2023-08-07 12:02:44 -04:00
microproofs 05b6b2a97d chore: rename some functions 2023-08-07 12:02:44 -04:00
microproofs c025073056 fix: List clauses were destructuring the next element unnecessarily
feat: finish nested constructor clauses
2023-08-07 12:02:44 -04:00
microproofs f6e163d16d feat: start on nested clauses
chore: remove then field from list clause guard and clause guard
2023-08-07 12:02:44 -04:00
microproofs 5bcc425f0f feat: changed air expressions clause guard
and list clause guard to air statements
2023-08-07 12:02:44 -04:00
microproofs 023be88bf6 chore: another checkpoint
fix: guard clause to properly check condition
2023-08-07 12:02:44 -04:00
microproofs f94c8213b6 checkpoint 2023-08-07 12:02:44 -04:00
microproofs 0854d71836 chore: another checkpoint and renamed ClauseProperties fields 2023-08-07 12:02:44 -04:00
microproofs d731757123 feat: start on clauses in when conditions
**checkpoint**
2023-08-07 12:02:44 -04:00
microproofs 96959011e9 feat: finish up build. just have helper methods
feat: Create an air and AirTree iterator.
This allows us to iterate forwards or backwards over the tree as a vec.
chore: moved around some functions
2023-08-07 12:02:44 -04:00
microproofs ba3265054c chore: move tree to gen_uplc2 and create a duplicate air file without scope 2023-08-07 12:02:44 -04:00
microproofs 7cee9a4d15 chore: move assignment_air_tree and expect_type to gen_uplc
feat: add is_primitive check to types
2023-08-07 12:02:44 -04:00
microproofs cd726b561e feat: add removal of discard lets
chore: Name change for AirTree sequence
feat: finish up assignment  constructor and list for airtree builder
2023-08-07 12:02:44 -04:00
microproofs 59362e3d8c feat: almost done assignment have tuple and constr left
feat: modified the AirTree structure to have statements, sequences, and expressions
feat: changed the hoist_over function to be universal
2023-08-07 12:02:44 -04:00
microproofs 65bb7e48e2 feat: start on build assignment
feat: implement assignment hoisting
2023-08-07 12:02:44 -04:00
microproofs c359bd35d7 feat: update tree to allow for let hoisting
feat: start on build for when expressions
feat: add builder methods for AirTree
2023-08-07 12:02:44 -04:00
microproofs 83ade9335f feat: implement most of airtree build 2023-08-07 12:02:44 -04:00
microproofs 5e097d42ba feat: add AirTree types and builder functions 2023-08-07 12:02:44 -04:00
Olof Blomqvist d25bb9ae60 format 2023-08-04 14:56:16 -04:00
Olof Blomqvist 4e4a477ff1 meh 2023-08-04 14:56:16 -04:00
Olof Blomqvist 17eef195a9 fix diagnostics and formatting on windows vscode 2023-08-04 14:56:16 -04:00
rvcas 266b6bbb7d
fix(exhaustiveness): for constructor use correct name because import aliases 2023-08-03 16:28:47 -04:00
rvcas 60ac8ab591
fix(exhaustiveness): adjust helper method to get contructors properly 2023-08-03 16:14:42 -04:00
KtorZ 675b737898
Check exhaustiveness behavior on pattern guards. 2023-08-02 10:40:59 +02:00
KtorZ 4f7f39292d
Fix subtle bug in pattern rendering
When rendering missing or redundant patterns, linked-list would
  wrongly suggest the last nil constructor as a pattern on non-empty
  list.

  For example, before this commit, the exhaustivness checker would yield:

  ```
  [(_, True), []]
  ```

  as a suggestion, for being the result of being a list pattern with a
  single argument being `(_, True) :: Nil`. Blindly following the
  compiler suggestion here would cause a type unification error (since
  `[]` doesn't unify with a 2-tuple).

  Indeed, we mustn't render the Nil constructor when rendering non-empty
  lists! So the correct suggestion should be:

  ```
  [(_, True)]
  ```
2023-08-02 10:31:35 +02:00
KtorZ 00b255e960
Remove now-dead code. 2023-08-02 09:22:21 +02:00
rvcas f3cab94ae1 test(check): a bunch of tests for the new exhaustiveness stuff 2023-08-01 21:13:50 -04:00
rvcas 75e18d485d fix: redundant might be wildcard which doesn't match technically 2023-08-01 21:13:50 -04:00
rvcas a6b230aad4 fix: exhaustiveness on types from other modules 2023-08-01 21:13:50 -04:00
rvcas 7e531d0da1 fix: wrong var for name in UnknownModule error 2023-08-01 21:13:50 -04:00
rvcas b6ac39f322 feat(exhaustiveness): show both clauses in redundant error 2023-08-01 21:13:50 -04:00
rvcas ef2fc57ca9 feat(exhaustiveness): check tuple patterns 2023-08-01 21:13:50 -04:00
rvcas f1100e901d feat(exhaustiveness): pretty print missing patterns 2023-08-01 21:13:50 -04:00
rvcas de2791fe82 feat(tipo): add new error for redundant clauses 2023-08-01 21:13:50 -04:00
rvcas 0061bcf78d feat: add support for list patterns 2023-08-01 21:13:50 -04:00
rvcas e8a71cd63b chore: rename usefulness module 2023-08-01 21:13:50 -04:00
rvcas 03efb46e6f feat(exhaustiveness): algorithm U borrowed from elm 2023-08-01 21:13:50 -04:00
microproofs 55887d3a45 fix: decode should always print to textual 2023-08-01 00:47:29 -04:00
3643 changed files with 92385 additions and 26905 deletions

1
.gitattributes vendored
View File

@ -1,3 +1,4 @@
Cargo.lock linguist-generated=true merge=binary linguist-vendored
Cargo.nix linguist-generated=true merge=binary linguist-vendored
flake.lock linguist-generated=true merge=binary linguist-vendored
**/*.snap merge=binary linguist-vendored

1
.github/CODEOWNERS vendored Normal file
View File

@ -0,0 +1 @@
* @aiken-lang/maintainers

5
.github/musl-build-setup.yml vendored Normal file
View File

@ -0,0 +1,5 @@
- name: Musl build setup
if: ${{ runner.os == 'Linux' }}
run: |
sudo apt-get install -y pkg-config libssl-dev musl musl-dev musl-tools
rustup target add x86_64-unknown-linux-musl

View File

@ -1,137 +1,363 @@
# This file was autogenerated by cargo-dist: https://opensource.axo.dev/cargo-dist/
#
# Copyright 2022-2024, axodotdev
# SPDX-License-Identifier: MIT or Apache-2.0
#
# CI that:
#
# * checks for a Git Tag that looks like a release
# * builds artifacts with cargo-dist (archives, installers, hashes)
# * uploads those artifacts to temporary workflow zip
# * on success, uploads the artifacts to a GitHub Release
#
# Note that the GitHub Release will be created with a generated
# title/body based on your changelogs.
name: Release
permissions:
"contents": "write"
# This task will run whenever you push a git tag that looks like a version
# like "1.0.0", "v0.1.0-prerelease.1", "my-app/0.1.0", "releases/v1.0.0", etc.
# Various formats will be parsed into a VERSION and an optional PACKAGE_NAME, where
# PACKAGE_NAME must be the name of a Cargo package in your workspace, and VERSION
# must be a Cargo-style SemVer Version (must have at least major.minor.patch).
#
# If PACKAGE_NAME is specified, then the announcement will be for that
# package (erroring out if it doesn't have the given version or isn't cargo-dist-able).
#
# If PACKAGE_NAME isn't specified, then the announcement will be for all
# (cargo-dist-able) packages in the workspace with that version (this mode is
# intended for workspaces with only one dist-able package, or with all dist-able
# packages versioned/released in lockstep).
#
# If you push multiple tags at once, separate instances of this workflow will
# spin up, creating an independent announcement for each one. However, GitHub
# will hard limit this to 3 tags per commit, as it will assume more tags is a
# mistake.
#
# If there's a prerelease-style suffix to the version, then the release(s)
# will be marked as a prerelease.
on:
pull_request:
push:
tags: ["v*.*.*"]
env:
CARGO_TERM_COLOR: always
tags:
- '**[0-9]+.[0-9]+.[0-9]+*'
jobs:
prepare:
name: Prepare release
runs-on: ubuntu-latest
# Run 'cargo dist plan' (or host) to determine what tasks we need to do
plan:
runs-on: "ubuntu-20.04"
outputs:
tag_name: ${{ steps.release_info.outputs.tag_name }}
release_name: ${{ steps.release_info.outputs.release_name }}
# release_notes: ${{ steps.extract_release_notes.outputs.release_notes }}
val: ${{ steps.plan.outputs.manifest }}
tag: ${{ !github.event.pull_request && github.ref_name || '' }}
tag-flag: ${{ !github.event.pull_request && format('--tag={0}', github.ref_name) || '' }}
publishing: ${{ !github.event.pull_request }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- name: Checkout
uses: actions/checkout@v2
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Compute release name and tag
id: release_info
run: |
echo "tag_name=${GITHUB_REF_NAME}" >> $GITHUB_OUTPUT
echo "release_name=${GITHUB_REF_NAME}" >> $GITHUB_OUTPUT
# - name: Extract release notes
# id: extract_release_notes
# run: echo "release_notes=\"$(sed -n '/^## .*$/,$p' CHANGELOG.md | sed '1d;/^## /,$d')\"" >> $GITHUB_OUTPUT
release:
name: ${{ matrix.job.target }} (${{ matrix.job.os }})
runs-on: ${{ matrix.job.os }}
needs: prepare
strategy:
matrix:
job:
# os: used for the runner
# platform: a generic platform name
# target: used by Cargo
# arch: either 386, arm64 or amd64
- os: ubuntu-latest
platform: linux
target: x86_64-unknown-linux-gnu
arch: amd64
# - os: ubuntu-latest
# platform: linux
# target: aarch64-unknown-linux-gnu
# arch: arm64
- os: macos-latest
platform: darwin
target: x86_64-apple-darwin
arch: amd64
- os: macos-latest
platform: darwin
target: aarch64-apple-darwin
arch: arm64
- os: windows-latest
platform: win32
target: x86_64-pc-windows-msvc
arch: amd64
- os: windows-latest
platform: win32
target: aarch64-pc-windows-msvc
arch: arm64
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
target: ${{ matrix.job.target }}
override: true
- uses: Swatinem/rust-cache@v1
with:
cache-on-failure: true
- name: Apple M1 setup
if: ${{ matrix.job.target == 'aarch64-apple-darwin' }}
run: |
echo "SDKROOT=$(xcrun -sdk macosx --show-sdk-path)" >> $GITHUB_ENV
echo "MACOSX_DEPLOYMENT_TARGET=$(xcrun -sdk macosx --show-sdk-platform-version)" >> $GITHUB_ENV
- name: Linux ARM setup
if: ${{ matrix.job.target == 'aarch64-unknown-linux-gnu' }}
run: |
sudo apt-get update -y
sudo apt-get install -y gcc-aarch64-linux-gnu libssl-dev:armhf
echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc" >> $GITHUB_ENV
- name: Build binaries
uses: actions-rs/cargo@v1
with:
command: build
args: --release --bins --target ${{ matrix.job.target }}
- name: Archive binaries
id: artifacts
env:
PLATFORM_NAME: ${{ matrix.job.platform }}
TARGET: ${{ matrix.job.target }}
ARCH: ${{ matrix.job.arch }}
VERSION_NAME: ${{ needs.prepare.outputs.tag_name }}
run: |
if [ "$PLATFORM_NAME" == "linux" ]; then
tar -czvf "aiken_${VERSION_NAME}_${PLATFORM_NAME}_${ARCH}.tar.gz" -C ./target/${TARGET}/release aiken
echo "::set-output name=file_name::aiken_${VERSION_NAME}_${PLATFORM_NAME}_${ARCH}.tar.gz"
elif [ "$PLATFORM_NAME" == "darwin" ]; then
# We need to use gtar here otherwise the archive is corrupt.
# See: https://github.com/actions/virtual-environments/issues/2619
gtar -czvf "aiken_${VERSION_NAME}_${PLATFORM_NAME}_${ARCH}.tar.gz" -C ./target/${TARGET}/release aiken
echo "::set-output name=file_name::aiken_${VERSION_NAME}_${PLATFORM_NAME}_${ARCH}.tar.gz"
else
cd ./target/${TARGET}/release
7z a -tzip "aiken_${VERSION_NAME}_${PLATFORM_NAME}_${ARCH}.zip" aiken.exe
mv "aiken_${VERSION_NAME}_${PLATFORM_NAME}_${ARCH}.zip" ../../../
echo "::set-output name=file_name::aiken_${VERSION_NAME}_${PLATFORM_NAME}_${ARCH}.zip"
fi
submodules: recursive
- name: Install cargo-dist
# we specify bash to get pipefail; it guards against the `curl` command
# failing. otherwise `sh` won't catch that `curl` returned non-0
shell: bash
# Creates the release for this specific version
- name: Create release
uses: softprops/action-gh-release@v1
run: "curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/cargo-dist/releases/download/v0.22.1/cargo-dist-installer.sh | sh"
- name: Cache cargo-dist
uses: actions/upload-artifact@v4
with:
name: ${{ needs.prepare.outputs.release_name }}
tag_name: ${{ needs.prepare.outputs.tag_name }}
files: |
${{ steps.artifacts.outputs.file_name }}
name: cargo-dist-cache
path: ~/.cargo/bin/cargo-dist
# sure would be cool if github gave us proper conditionals...
# so here's a doubly-nested ternary-via-truthiness to try to provide the best possible
# functionality based on whether this is a pull_request, and whether it's from a fork.
# (PRs run on the *source* but secrets are usually on the *target* -- that's *good*
# but also really annoying to build CI around when it needs secrets to work right.)
- id: plan
run: |
cargo dist ${{ (!github.event.pull_request && format('host --steps=create --tag={0}', github.ref_name)) || 'plan' }} --output-format=json > plan-dist-manifest.json
echo "cargo dist ran successfully"
cat plan-dist-manifest.json
echo "manifest=$(jq -c "." plan-dist-manifest.json)" >> "$GITHUB_OUTPUT"
- name: "Upload dist-manifest.json"
uses: actions/upload-artifact@v4
with:
name: artifacts-plan-dist-manifest
path: plan-dist-manifest.json
# Build and packages all the platform-specific things
build-local-artifacts:
name: build-local-artifacts (${{ join(matrix.targets, ', ') }})
# Let the initial task tell us to not run (currently very blunt)
needs:
- plan
if: ${{ fromJson(needs.plan.outputs.val).ci.github.artifacts_matrix.include != null && (needs.plan.outputs.publishing == 'true' || fromJson(needs.plan.outputs.val).ci.github.pr_run_mode == 'upload') }}
strategy:
fail-fast: false
# Target platforms/runners are computed by cargo-dist in create-release.
# Each member of the matrix has the following arguments:
#
# - runner: the github runner
# - dist-args: cli flags to pass to cargo dist
# - install-dist: expression to run to install cargo-dist on the runner
#
# Typically there will be:
# - 1 "global" task that builds universal installers
# - N "local" tasks that build each platform's binaries and platform-specific installers
matrix: ${{ fromJson(needs.plan.outputs.val).ci.github.artifacts_matrix }}
runs-on: ${{ matrix.runner }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BUILD_MANIFEST_NAME: target/distrib/${{ join(matrix.targets, '-') }}-dist-manifest.json
steps:
- name: enable windows longpaths
run: |
git config --global core.longpaths true
- uses: actions/checkout@v4
with:
submodules: recursive
- name: "Musl build setup"
if: "${{ runner.os == 'Linux' }}"
run: |
sudo apt-get install -y pkg-config libssl-dev musl musl-dev musl-tools
rustup target add x86_64-unknown-linux-musl
- name: Install cargo-dist
run: ${{ matrix.install_dist }}
# Get the dist-manifest
- name: Fetch local artifacts
uses: actions/download-artifact@v4
with:
pattern: artifacts-*
path: target/distrib/
merge-multiple: true
- name: Install dependencies
run: |
${{ matrix.packages_install }}
- name: Build artifacts
run: |
# Actually do builds and make zips and whatnot
cargo dist build ${{ needs.plan.outputs.tag-flag }} --print=linkage --output-format=json ${{ matrix.dist_args }} > dist-manifest.json
echo "cargo dist ran successfully"
- id: cargo-dist
name: Post-build
# We force bash here just because github makes it really hard to get values up
# to "real" actions without writing to env-vars, and writing to env-vars has
# inconsistent syntax between shell and powershell.
shell: bash
run: |
# Parse out what we just built and upload it to scratch storage
echo "paths<<EOF" >> "$GITHUB_OUTPUT"
jq --raw-output ".upload_files[]" dist-manifest.json >> "$GITHUB_OUTPUT"
echo "EOF" >> "$GITHUB_OUTPUT"
cp dist-manifest.json "$BUILD_MANIFEST_NAME"
- name: "Upload artifacts"
uses: actions/upload-artifact@v4
with:
name: artifacts-build-local-${{ join(matrix.targets, '_') }}
path: |
${{ steps.cargo-dist.outputs.paths }}
${{ env.BUILD_MANIFEST_NAME }}
# Build and package all the platform-agnostic(ish) things
build-global-artifacts:
needs:
- plan
- build-local-artifacts
runs-on: "ubuntu-20.04"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BUILD_MANIFEST_NAME: target/distrib/global-dist-manifest.json
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Install cached cargo-dist
uses: actions/download-artifact@v4
with:
name: cargo-dist-cache
path: ~/.cargo/bin/
- run: chmod +x ~/.cargo/bin/cargo-dist
# Get all the local artifacts for the global tasks to use (for e.g. checksums)
- name: Fetch local artifacts
uses: actions/download-artifact@v4
with:
pattern: artifacts-*
path: target/distrib/
merge-multiple: true
- id: cargo-dist
shell: bash
run: |
cargo dist build ${{ needs.plan.outputs.tag-flag }} --output-format=json "--artifacts=global" > dist-manifest.json
echo "cargo dist ran successfully"
# Parse out what we just built and upload it to scratch storage
echo "paths<<EOF" >> "$GITHUB_OUTPUT"
jq --raw-output ".upload_files[]" dist-manifest.json >> "$GITHUB_OUTPUT"
echo "EOF" >> "$GITHUB_OUTPUT"
cp dist-manifest.json "$BUILD_MANIFEST_NAME"
- name: "Upload artifacts"
uses: actions/upload-artifact@v4
with:
name: artifacts-build-global
path: |
${{ steps.cargo-dist.outputs.paths }}
${{ env.BUILD_MANIFEST_NAME }}
# Determines if we should publish/announce
host:
needs:
- plan
- build-local-artifacts
- build-global-artifacts
# Only run if we're "publishing", and only if local and global didn't fail (skipped is fine)
if: ${{ always() && needs.plan.outputs.publishing == 'true' && (needs.build-global-artifacts.result == 'skipped' || needs.build-global-artifacts.result == 'success') && (needs.build-local-artifacts.result == 'skipped' || needs.build-local-artifacts.result == 'success') }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
runs-on: "ubuntu-20.04"
outputs:
val: ${{ steps.host.outputs.manifest }}
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Install cached cargo-dist
uses: actions/download-artifact@v4
with:
name: cargo-dist-cache
path: ~/.cargo/bin/
- run: chmod +x ~/.cargo/bin/cargo-dist
# Fetch artifacts from scratch-storage
- name: Fetch artifacts
uses: actions/download-artifact@v4
with:
pattern: artifacts-*
path: target/distrib/
merge-multiple: true
- id: host
shell: bash
run: |
cargo dist host ${{ needs.plan.outputs.tag-flag }} --steps=upload --steps=release --output-format=json > dist-manifest.json
echo "artifacts uploaded and released successfully"
cat dist-manifest.json
echo "manifest=$(jq -c "." dist-manifest.json)" >> "$GITHUB_OUTPUT"
- name: "Upload dist-manifest.json"
uses: actions/upload-artifact@v4
with:
# Overwrite the previous copy
name: artifacts-dist-manifest
path: dist-manifest.json
# Create a GitHub Release while uploading all files to it
- name: "Download GitHub Artifacts"
uses: actions/download-artifact@v4
with:
pattern: artifacts-*
path: artifacts
merge-multiple: true
- name: Cleanup
run: |
# Remove the granular manifests
rm -f artifacts/*-dist-manifest.json
- name: Create GitHub Release
env:
PRERELEASE_FLAG: "${{ fromJson(steps.host.outputs.manifest).announcement_is_prerelease && '--prerelease' || '' }}"
ANNOUNCEMENT_TITLE: "${{ fromJson(steps.host.outputs.manifest).announcement_title }}"
ANNOUNCEMENT_BODY: "${{ fromJson(steps.host.outputs.manifest).announcement_github_body }}"
RELEASE_COMMIT: "${{ github.sha }}"
run: |
# Write and read notes from a file to avoid quoting breaking things
echo "$ANNOUNCEMENT_BODY" > $RUNNER_TEMP/notes.txt
gh release create "${{ needs.plan.outputs.tag }}" --target "$RELEASE_COMMIT" $PRERELEASE_FLAG --title "$ANNOUNCEMENT_TITLE" --notes-file "$RUNNER_TEMP/notes.txt" artifacts/*
publish-homebrew-formula:
needs:
- plan
- host
runs-on: "ubuntu-20.04"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PLAN: ${{ needs.plan.outputs.val }}
GITHUB_USER: "axo bot"
GITHUB_EMAIL: "admin+bot@axo.dev"
if: ${{ !fromJson(needs.plan.outputs.val).announcement_is_prerelease || fromJson(needs.plan.outputs.val).publish_prereleases }}
steps:
- uses: actions/checkout@v4
with:
repository: "aiken-lang/homebrew-tap"
token: ${{ secrets.HOMEBREW_TAP_TOKEN }}
# So we have access to the formula
- name: Fetch homebrew formulae
uses: actions/download-artifact@v4
with:
pattern: artifacts-*
path: Formula/
merge-multiple: true
# This is extra complex because you can make your Formula name not match your app name
# so we need to find releases with a *.rb file, and publish with that filename.
- name: Commit formula files
run: |
git config --global user.name "${GITHUB_USER}"
git config --global user.email "${GITHUB_EMAIL}"
for release in $(echo "$PLAN" | jq --compact-output '.releases[] | select([.artifacts[] | endswith(".rb")] | any)'); do
filename=$(echo "$release" | jq '.artifacts[] | select(endswith(".rb"))' --raw-output)
name=$(echo "$filename" | sed "s/\.rb$//")
version=$(echo "$release" | jq .app_version --raw-output)
export PATH="/home/linuxbrew/.linuxbrew/bin:$PATH"
brew update
# We avoid reformatting user-provided data such as the app description and homepage.
brew style --except-cops FormulaAudit/Homepage,FormulaAudit/Desc,FormulaAuditStrict --fix "Formula/${filename}" || true
git add "Formula/${filename}"
git commit -m "${name} ${version}"
done
git push
publish-npm:
needs:
- plan
- host
runs-on: "ubuntu-20.04"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PLAN: ${{ needs.plan.outputs.val }}
if: ${{ !fromJson(needs.plan.outputs.val).announcement_is_prerelease || fromJson(needs.plan.outputs.val).publish_prereleases }}
steps:
- name: Fetch npm packages
uses: actions/download-artifact@v4
with:
pattern: artifacts-*
path: npm/
merge-multiple: true
- uses: actions/setup-node@v4
with:
node-version: '20.x'
registry-url: 'https://registry.npmjs.org'
- run: |
for release in $(echo "$PLAN" | jq --compact-output '.releases[] | select([.artifacts[] | endswith("-npm-package.tar.gz")] | any)'); do
pkg=$(echo "$release" | jq '.artifacts[] | select(endswith("-npm-package.tar.gz"))' --raw-output)
npm publish --access public "./npm/${pkg}"
done
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
announce:
needs:
- plan
- host
- publish-homebrew-formula
- publish-npm
# use "always() && ..." to allow us to wait for all publish jobs while
# still allowing individual publish jobs to skip themselves (for prereleases).
# "host" however must run to completion, no skipping allowed!
if: ${{ always() && needs.host.result == 'success' && (needs.publish-homebrew-formula.result == 'skipped' || needs.publish-homebrew-formula.result == 'success') && (needs.publish-npm.result == 'skipped' || needs.publish-npm.result == 'success') }}
runs-on: "ubuntu-20.04"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@v4
with:
submodules: recursive

View File

@ -11,22 +11,76 @@ env:
jobs:
build:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: Swatinem/rust-cache@v2
with:
save-if: ${{ github.ref == 'refs/heads/main' }}
key: ${{ runner.os }}-cache-build-v${{ inputs.cache-version }}
- name: Build release
run: |
sudo apt-get install -y pkg-config libssl-dev musl musl-dev musl-tools
rustup target add x86_64-unknown-linux-musl
cargo install --path=crates/aiken --target=x86_64-unknown-linux-musl
mv $(which aiken) aiken
ldd aiken
- uses: actions/upload-artifact@v4
with:
name: aiken-${{ github.sha }}-${{ runner.arch }}-${{ runner.os }}
path: ./aiken
acceptance_tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build
run: cargo build --verbose --workspace
- name: Run unit tests
run: cargo test --verbose --workspace
- uses: actions/checkout@v4
- uses: Swatinem/rust-cache@v2
with:
save-if: ${{ github.ref == 'refs/heads/main' }}
key: ${{ runner.os }}-cache-build-v${{ inputs.cache-version }}
- name: Run examples
run: |
cargo run -r -- check examples/hello_world
cargo run -r -- check examples/gift_card
- name: Run acceptance tests
working-directory: examples/acceptance_tests
run: |
cargo install cbor-diag-cli
bash ci
shell: bash
unit_tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: Swatinem/rust-cache@v2
with:
save-if: ${{ github.ref == 'refs/heads/main' }}
key: ${{ runner.os }}-cache-tests-v${{ inputs.cache-version }}
- name: Run unit tests
run: cargo test --verbose --workspace
benchmarks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: Swatinem/rust-cache@v2
with:
save-if: ${{ github.ref == 'refs/heads/main' }}
key: ${{ runner.os }}-cache-build-v${{ inputs.cache-version }}
- name: Run benchmarks
run: |
cargo run -r -- check benchmarks
checks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: Swatinem/rust-cache@v2
with:
save-if: ${{ github.ref == 'refs/heads/main' }}
key: ${{ runner.os }}-cache-unit-v${{ inputs.cache-version }}
- name: Format
run: cargo fmt --all -- --check
- name: Clippy
run: cargo clippy --all-targets --all-features -- -D warnings
# - name: Audit
# run: cargo audit

3
.gitignore vendored
View File

@ -2,4 +2,5 @@
/target
.idea
_site/
temp
temp/
scratch/

View File

@ -1,5 +1,626 @@
# Changelog
## v1.1.7 - 2024-11-19
### Changed
- **aiken**: Move JSON schema help for `check` under a new dedicated flag `--show-json-schema`. @KtorZ
- **aiken-lang**: Fix pattern-matching on list wildcard sometimes causing compiler crash following the new _decision trees_ approach. @MicroProofs
- **uplc**, **aiken**, **aiken-lang**: Update internal dependencies to pallas-0.31.0. @KtorZ
## v1.1.6 - 2024-11-13
### Added
- **aiken**: Optionally provide blueprint file location when using `blueprint apply`. @Riley-Kilgore
- **aiken**: Output test results as structured JSON when the target output is not a TTY terminal. @Riley-Kilgore, @KtorZ
### Changed
- **aiken**: Fix validator selection for `apply`, `address` and `policy` commands. Parameters are also now correctly applied to all handlers of a given validator, instead of needing to be manually targetted one-by-one. @KtorZ
- **aiken**: Add more flexibility around the management of Plutus blueprint files for `build`, `address`, `policy` and `apply` commands. See [#1055](https://github.com/aiken-lang/aiken/issues/1055). @KtorZ
- **aiken**: Rename `--filter_traces` to `--trace_filter` for more consistency with `--trace_level`. An alias for `--filter_traces` still exists for backward compatibility. @KtorZ
- **aiken-project**: Fix `aiken docs` wrongly formatting list constants as tuples. See [#1048](https://github.com/aiken-lang/aiken/issues/1048). @KtorZ
- **aiken-project**: Fix `aiken docs` source linking crashing when generating docs for config modules. See [#1044](https://github.com/aiken-lang/aiken/issues/1044). @KtorZ
- **aiken-project**: Fix `aiken docs` generating very long lines for constants. @KtorZ
- **aiken-lang**: Leverage [Decision Trees](https://www.cs.tufts.edu/comp/150FP/archive/luc-maranget/jun08.pdf) for compiling pattern matches to UPLC. @MicroProofs
- **aiken-lang**: Rework optimization passes to safely reduce different kinds of patterns for each pass over the uplc. @MicroProofs
- **aiken-lang**: Implement a looping mechanism to reduce uplc with deletion optimizations until term count remains the same. @MicroProofs
### Removed
- N/A
## v1.1.5 - 2024-10-19
### Added
- N/A
### Changed
- **uplc**: Fix costing of byteStringToInteger builtins. @Microproofs
- **aiken-lang**: Fix data-type reification from `Void`; somehow missing from known definition :facepalm:. @KtorZ
### Removed
- N/A
## v1.1.4 - 2024-10-01
### Added
- N/A
### Changed
- **aiken-project**: Generate empty redeemer for `else` handler, to keep full compliance with the blueprint spec. @KtorZ
- **aiken-lang**: Forbid constants evaluating to generic or unbound functions. Same restrictions as for validators or any exported UPLC programs apply here. @KtorZ & @MicroProofs
- **aiken-lang**: Fix compiler crash on trace + expect as last expression of a clause. See #1029. @KtorZ
- **aiken-lang**: Fix redundant warning on introduced identifiers when destructuring validator params. @KtorZ
- **aiken-lsp**: Compile project using verbose tracing, to avoid having the language server complain about unused imports. @KtorZ
- **uplc**: Fix (again :grimacing:) cost-models for PlutusV1 & PlutusV2. @MicroProofs
### Removed
- N/A
## v1.1.3 - 2024-09-20
### Added
- N/A
### Changed
- **aiken-project**: Fix documentation link-tree generation messing up with modules when re-inserting the same module. @KtorZ
- **aiken-project**: Provide intermediate feedback when looking for counterexamples during property tests. @KtorZ
- **aiken-lang**: Fix formatter adding extra unnecessary newlines after literal lists clause values or assignments. @KtorZ
- **aiken-lang**: Fix formatting of long multi-line if/is expressions. @KtorZ
- **aiken-lang**: Fix extraneous white-space added by the formatter after multiline alternative patterns. @KtorZ
- **aiken-lang**: Fix incorrect warning about unused variable when softcasting without explicit right-pattern. @KtorZ
- **aiken-lang**: Fix soft cast and hard cast on same type issues that lead to validator errors. @Microproofs
- **aiken-lang**: Bls constants are automatically converted to a hoisted compressed form with uncompress builtin call. @Microproofs
- **uplc**: Fix cost-models for PlutusV1 & PlutusV2. @MicroProofs
### Removed
- N/A
## v1.1.2 - 2024-09-13
### Added
- N/A
### Changed
- **aiken-lang**: Fix issues with static recursive optimization. See [#1009](https://github.com/aiken-lang/aiken/issues/1009) @Microproofs
- **aiken-lang**: Aiken IR now interns variables while building up to ensure uniqueness for local vars. @Microproofs
- **aiken-lang**: Fix reification of `Data` (failing to reify) & `PRNG` (missing variants' arguments). @KtorZ
- **aiken-lang**: Adjust reification of `String` to be shown as plain UTF-8 text strings (instead of hex-encoded byte array). @KtorZ
- **aiken-lang**: Fix formatting of long if-condition over multiline. @KtorZ & @Microproofs
- **aiken-lang**: Fix formatting of standalone logical binary chains (`and` & `or`) in functions. @KtorZ
- **uplc**: Fix script context generation failure on missing datum when evaluating transactions. @solidsnakedev
### Removed
- N/A
## v1.1.1 - 2024-09-10
### Added
- N/A
### Changed
- **aiken-lang**: Fix validator's else handler generation. See [#1015](https://github.com/aiken-lang/aiken/issues/1015) @KtorZ
- **aiken-lang**: Fix underflow in error message reported by the validator arity. See [#1013](https://github.com/aiken-lang/aiken/issues/1013) @KtorZ
- **aiken-lang**: Fix list-pattern needlessly formatting over multiple lines. @KtorZ
- **aiken-lang**: Fix formatter on long alternative patterns spanning over multiple lines. @KtorZ
- **aiken-lang**: Fix needed parentheses under trace-if-false operator for todo, fail, unop & pipelines; removed when formatting. @KtorZ
- **aiken-lang**: Fix formatter removing curly braces around multi-line constants. It's fine to not have curly braces, but it's the Aiken signature after all. @KtorZ
- **aiken-lang**: Improve LSP suggestion for module imports. @Riley-Kilgore
### Removed
- N/A
## v1.1.0 - 2024-09-03
### Added
- **aiken-lang**: also authorize (complete) patterns in function arguments list instead of only variable names. @KtorZ
- **aiken-lang**: new syntax for soft casting otherwise known as `if/is`. See [#959](https://github.com/aiken-lang/aiken/pull/959) or [Control Flow - soft casting](https://aiken-lang.org/language-tour/control-flow#soft-casting-with-ifis) for more details. @rvcas
- **aiken-lang**: optimization: pre-evaluate constant arguments to lambdas when safe to do so. @MicroProofs
- **aiken-lang**: infer type when immediately possible during a patterned type-cast. See [#969](https://github.com/aiken-lang/aiken/pull/979). @KtorZ
- **aiken-lang**: add support for `mk_cons` and `mk_pair_data` builtins. See [#964](https://github.com/aiken-lang/aiken/issues/964). @KtorZ
- **aiken-lang**: pattern-matching on bytearrays is now available. See [#989](https://github.com/aiken-lang/aiken/issues/989). @KtorZ
- **aiken-project**: conditional configuration and environment. See [#937](https://github.com/aiken-lang/aiken/issues/937). @KtorZ
- **aiken-project**: warning on compiler version mismatch. See [de870e2](https://github.com/aiken-lang/aiken/commit/de870e2529eb2336957e228cd30d4850ec2619a2). @rvcas
- **aiken-project**: source links to generated documentation for types, constants and functions. @KtorZ
- **aiken-project**: comments containing Markdown section headings (`#`, `##`, `###` etc.) will now be preserved and rendered in generated documentation. @KtorZ
- **aiken-project**: modules starting with `@hidden` in their docs will be skipped from docs generation. @KtorZ
- **aiken-project**: preserve type-aliases as titles in blueprint generated schemas. @KtorZ
- **uplc**: support evaluation of Plutus V3 transactions, including new purposes introduced in Conway. @KtorZ
### Changed
- **aiken-lang**: zero-arg functions are **no longer** evaluated at compile-time. However, constants can now hold _any_ expression and are fully evaluated at compile-time. Use `const` whenever a zero-arg function was used, unless you do want to defer execution. @KtorZ @MicroProofs.
- **aiken-lang**: fix zero-arg builtins `mk_nil_data` and `mk_nil_pair_data` invokation. @KtorZ
- **aiken-lang**: rename some builtins. @KtorZ
| old name | new name |
| --- | --- |
| `mk_nil_data` | `new_list` |
| `mk_pair_data` | `new_pair` |
| `mk_nil_pair_data` | `new_pairs` |
- **aiken-lang**: duplicate import lines are now automatically merged instead of raising a warning. However, imports can no longer appear anywhere in the file and must come as the first definitions. @KtorZ
- **aiken-lang**: remove warning on discarded expect, allowing to keep 'side-effects' when necessary. See [#967](https://github.com/aiken-lang/aiken/pull/967). @KtorZ
- **aiken-lang**: allow expect as last (or only) expression in function body, when clauses and if branches. Such expressions unify with `Void`. See [#1000](https://github.com/aiken-lang/aiken/pull/1000). @KtorZ
- **aiken-lang**: allow tests to return `Void`. Tests that return `Void` are treated the same as tests that return `True`. See [#1000](https://github.com/aiken-lang/aiken/pull/1000). @KtorZ
- **aiken-lang**: rework traces to be (1) variadic, (2) generic in its arguments and (3) structured. @KtorZ
In more details:
1. Enables the `trace` keyword to take one, two or any argument really separated by comma after the first. For example:
```ak
trace @"a classic trace"
// ..
trace @"condition_1": @"foo"
// ...
trace @"condition_2": @"foo", @"bar"
```
2. Enables the `trace` keyword to not only take strings as arguments; but any
data-type that is serialisable (i.e. that can be cast to Data). It is fundamentally identical to calling the [`cbor.diagnostic`](https://aiken-lang.github.io/stdlib/aiken/cbor.html#diagnostic) function from the standard lib; except that this is done and glued with the rest of the trace automatically.
```ak
trace @"condition_1": [1, 2, 3]
// ...
let my_var = Some("foo")
trace my_var
```
3. Changes the behavior of the `--trace-level compact` mode to now:
- remove trace-if-false (`?` operator) traces entirely in this mode;
- only keep the label (first trace argument) and error when it isn't a string.
See also [#978](https://github.com/aiken-lang/aiken/pull/978).
- **aiken-lang**: rework formatter behaviour on long-lines, especially in the presence of binary operators. @KtorZ
- **aiken-lang**: provide better errors for unknown types used in cyclic type definitions. @KtorZ
- **aiken-project**: fix blueprint's apply truncating last character of outputs. See [#987](https://github.com/aiken-lang/aiken/issues/987). @KtorZ
- **aiken-project**: provide better error (include input ref) when inputs are missing during transaction evaluation. See [#974](https://github.com/aiken-lang/aiken/issues/974). @KtorZ
- **aiken-project**: module inhabitants are no longer alphabetically sorted when generating documentation. Instead, the order in which they are defined in the module is used. @KtorZ
- **aiken-project**: the sidebar links to modules within a package is now fully hierarchical and (hopefully) better-looking. @KtorZ
### Removed
- **aiken-lang**: clause guards are no longer part of the language. See [#886](https://github.com/aiken-lang/aiken/issues/886). @KtorZ.
## v1.0.29-alpha - 2024-06-06
### Added
- **aiken-lang**: new LSP quickfix for 'use let' warning. @KtorZ
### Changed
- **aiken-lang**: the keyword `fail` on property-based test semantic has changed and now consider a test to succeed only if **every** execution of the test failed (instead of just one). The previous behavior can be recovered by adding the keyword `once` after `fail`. @KtorZ
### Fixed
- **aiken-lang**: fixed the number of 'after x tests' number reported on property test failure, which was off by one. @KtorZ
- **aiken-lang**: fixed parsing of single hex digits. @KtorZ
## v1.0.28-alpha - 2024-05-23
### Added
- **aiken**: install shell completions automatically. @freexploit
- **aiken**: added export command that exports regular function definitons. @rvcas
- **aiken-project**: compiler version field to `aiken.toml` @rvcas
- **aiken-project**: plutus version field to `aiken.toml` @rvcas
- **aiken-lsp**: hover and goto definition support on list tail. @rvcas
- **aiken-lsp**: hover on prop test via expression. @rvcas
- **aiken-lang**: new builtin types in the prelude `Pair` and `Pairs`. @KtorZ @Microproofs
- **aiken-lang**: Codegen now generates uplc version 1.1.0 scripts when running build with plutus v3.
### Fixed
- **aiken-lang**: formatter should not erase `pub` on validators. @rvcas
- **aiken-lang**: error on using tuple index when a tuple is returned by a generic function. @rvcas
- **aiken-lang**: backpassing with expect gives a warning on pattern matches. @rvcas
- **aiken-lang**: fix a regression in the Type-checker introduced in v1.0.25-alpha regarding types comparison. See #917. @KtorZ
- **aiken-lang**: fix incongruous generics after type-checking which caused [] to be treated as a list in cases where it needed to be an empty map primitive. See #922. @KtorZ
- **aiken-lang**: fix for generic constrs being used as functions causing type mismatch errors. @Microproofs
- **aiken-lang**: fix for error occuring when a field holds Data that is not a constr type when compiler traces are on. @Microproofs
- **aiken-lang**: fix for curry optimization involving 2 constants #945. @MicroProofs
- **aiken-lang**: fix compiler wrongly requiring MillerLoopResult to be 'serialisable' when manipulated as a top-level value. See #921. @KtorZ
- **aiken-lang**: fix type-checker oversight regarding serialisation of generics. See #939. @KtorZ
- **aiken-lang**: fix type-checker not raising error when comparing non-serialisable types. See #940. @KtorZ
- **aiken-project**: show a warning when ignoring modules in lib/validator because they have an invalid name. See #916. @KtorZ
### Changed
> [!WARNING]
>
> **BREAKING-CHANGE**
>
> 2-tuples `(a, b)` are now treated the same as 3+ tuples -- which directly impacts the way that Aiken now deserialise those, especially when nested inside a `List`.
>
> To deserialize into a list of 2-tuple (`List<(a, b)>`), one is now expected to provide a CBOR array of arrays (of 2 elements). Previously, this would require to provide a CBOR map! The downside of the latter is that CBOR serialization libraries do not necessarily preserve the order of keys in a map which could cause issues down the line, in particular with Aiken's dictionnaries.
>
> To recover the old behavior when desired, Aiken introduces a new type `Pair<a, b>` to the language. So any existing program can be migrated by switching any occurences of `(a, b)` to `Pair<a, b>`.
>
> However, it is often preferable to use 2-tuples where possible. The main place you will see usage of `Pair` is in the script context because its form is imposed by the ledger.
- **aiken-lang**: altered internal representation of 2-tuples to distinguish them from pairs. @KtorZ @Microproofs
- **aiken-lang**: some more code gen cleanup. @Microproofs
- **aiken-lang**: new optimization for wrapped builtins found in the stdlib. @Microproofs
- **aiken-project**: slightly restyle warnings to be less noisy. @KtorZ
## v1.0.26-alpha - 2024-03-25
### Fixed
- **aiken-lang**: allow casting of types to Data in function pipiing. @KtorZ
## v1.0.25-alpha - 2024-03-22
### Added
- **aiken-lang**: Data now has a generic argument that can be used to specify the blueprint type. @KtorZ
- **aiken-lang**: New types `PRNG` and `Fuzzer` in the prelude. @KtorZ
- **aiken-lang**: Test definitions now accept an (optional) argument alongside a new keyword `via` to specify fuzzers. @KtorZ
- **aiken-project**: Property-based testing framework with integrated shrinking and case labelling. @KtorZ
- **aiken-project**: Unit tests now show assertion operands as Aiken expression instead of raw UPLC . @KtorZ
- **aiken**: The `check` command now accept an extra arg `--seed` to provide an initial seed for the pseudo-random generator of properties. @KtorZ
- **uplc**: add `integerToByteString` and `byteStringToInteger` builtins. @rvcas @Microproofs
- **aiken-lang**: add `integer_to_byte_string` and `byte_string_to_integer` `aiken/builtins`. @rvcas
- **uplc**: more conformance tests for `integerToByteString` and `byteStringToInteger` along with new ones. @rvcas
- **aikup**: error message when version is not found. @rvcas
- **aiken**: support outputting mainnet addresses for validators. @rvcas
- **aiken-lang**: added serde to CheckedModule to encode modules as cbor. @rvcas
- **aiken-lang**: Strings can contain a nul byte using the escape sequence `\0`. @KtorZ
- **aiken**: The `check` command now accept an extra (optional) option `--max-success` to control the number of property-test iterations to perform. @KtorZ
- **aiken**: The `docs` command now accept an optional flag `--include-dependencies` to include all dependencies in the generated documentation. @KtorZ
- **aiken-lang**: Implement [function backpassing](https://www.roc-lang.org/tutorial#backpassing) as a syntactic sugar. @KtorZ
- **aiken-lang**: Extend backpassing to support multiple patterns/arguments. @rvcas
### Fixed
- **aiken-lang**: Boolean operators (`||` and `&&`) were (somewhat) left-associative. This is now fixed and changed to right-associativity. @KtorZ
- **uplc**: `serialise_data` builtin wrongly encoding some larger ints as tagged CBOR bigints, instead of plain integers over 9 bytes. @KtorZ
- **aiken-project**: Unit tests reports are now inline with the test with less noise. @KtorZ
- **aiken-lang**: Data deserialization for primitive types (pairs, bools, void) now do full checks on the Data structure. @Microproofs
- **aiken-lang**: The identity reducer optimization was not removing the identity function before. That is fixed now.@Microproofs
- **aiken-lang**: Inner opaque types can now be properly destructured by expect and when patterns. @Microproofs
- **aiken-lang**: A codegen specific name-unique interner is now used to preserve lambda scoping. @Microproofs
- **aiken-lang**: if there is only one clause we want to present a warning that suggests that a `let` binding should be used instead but only if it's an exhaustive pattern. @rvcas
- **aiken-lang**: support nested void matching @rvcas
- **uplc**: fix constr identity (`constr-3.uplc`) conformance test. @rvcas
- **aiken-lang**: disallow `MLResult` in a type definition. @rvcas
- **aiken-lang**: reversed deserialization of bls types out of data types. @rvcas
- **aiken-lang**: validator args unexpectedly unbound causing code gen crashes. @rvcas
- **aiken-lang**: allow implicitly discarded values when right-hand side unified with `Void`. @KtorZ
- **aiken-lang**: allow zero arg mutually recursive functions. @Microproofs
- **aiken-lang**: function aliases now resolved to the module and function name in codegen. @Microproofs
- **aiken-lang**: fix indentation of pipelines to remain a multiple of the base indent increment. @KtorZ
- **aiken-lang**: forbid presence of non-serialisable data-types in compound structures like List and Tuple. @KtorZ
- **aiken-lang**: fix 'given' arity reported by 'incorrect arity' error message. @rvcas
### Changed
- **aiken-lang**: Discards will now also type check the validator arguments instead of completely ignoring them. @Microproofs
- **aiken-lang**: Further improvements to tracing when using expect casting from Data. @Microproofs
- **aiken-lang**: The set of curriable builtins with arguments that occur 3 or more times are now hoisted in scope with the arguments curried. @Microproofs
- **aiken-lang**: Improved the way the lambda inliner works to prevent unnecessary inlining into functions. @Microproofs
- **aiken-lang**: Simplifications to the AirTree type in codegen. @Microproofs
- **aiken-lang**: CONSTR_FIELD_EXPOSER and CONSTR_INDEX_EXPOSER now inline the builtins instead. @Microproofs
- **aiken-lang**: SubtractInteger with a constant as the second arg is now flipped to addInteger with a negated constant. @Microproofs
- **aiken-lang**: Validator arguments are now checked per arg instead of after all args are applied. @Microproofs
- **aiken-project**: remove test definitions from dependency modules. @rvcas
- **aiken-project**: ignore warnings from dependency modules. @rvcas
- **aiken-project**: parse sources in parallel, this resulted in a nice speedup. @rvcas
- **aiken-lang**: You can no longer use expect on opaque types in various situations. @rvcas & @KtorZ
## v1.0.24-alpha - 2024-01-31
### Added
- **aiken**: New aliases for `check` (aiken c) and `build` (aiken b) commands. @Kuly14
### Fixed
- **aiken-lang**: Fixed an issue with expects on lists that used discards. This fixes
the validator issues being seen for previously succeeding validators on 1.0.21-alpha. @MicroProofs
- **aiken-lang**: Out of Span issue is now solved. This also fixes incorrectly selected
traces from the wrong module, which in some cases lead to the out of span issue. @MicroProofs
- **aiken-lang**: Calling head_list on a list of pairs no longer throws a type error. @MicroProofs
## v1.0.23-alpha - 2024-01-24
### Fixed
- **aiken-lang**: Now using correct discard match for constructor field access.
- **aiken-lang**: The list_access_to_uplc now always returns a lambda wrapped
term even with only discards. This fixes an apply error being seen by a few
people.
## v1.0.22-alpha - 2024-01-24
### Added
- **aiken**: New `--trace-level` option for the `check` and `build` commands to
allow chosing the verbosity level of traces amongst three levels: silent,
compact & verbose. @MicroProofs @KtorZ
- **aiken**: New `--filter-traces` option for the `check` and `build` commands
to enable restricting traces with more granularity between user-defined
- **aiken-lang**: Most builtin errors are now caught and instead catched trace
errors are thrown. The exception is BLS primitives.
### Fixed
- **aiken-lang**: Fix flat encoding and decoding of large integer values. @KtorZ
- **aiken-lang**: Traces should not have following expressions formatted into a
block. @rvcas
- **aiken-lang**: Sequences should not be erased if the sole expression is an
assignment. @rvcas
- **aiken-lang**: Should not be able to assign an assignment to an assignment.
@rvcas
- **aiken-lang**: Should not be able to have an assignment in a logical op
chain. @rvcas
- **aiken**: Ensures that test expected to fail that return `False` are
considered to pass & improve error reporting when they fail. @KtorZ
- **aiken-lang**: Fix generic edge case involving tuples.
- **aiken**: `aiken new` now uses the current version for the github action.
- **aiken-lang**: Using the head_list builtin on assoc lists now works.
### Removed
- **aiken**: The options `--keep-traces` (on the `build` command) and
`--no-traces` (on the `check` command) have been removed; superseded by the
new options. @MicroProofs @KtorZ
> [!TIP]
>
> - If you've been using `aiken check --no-traces`, you can recover the old
> behavior by doing `aiken check --trace-level silent`.
> - If you've been using `aiken build --keep-traces`, you can recover the old
> behavior by doing `aiken build --trace-level verbose`.
## v1.0.21-alpha - 2023-12-04
### Added
- **aiken**: `--watch` flag on the `build`, `check` and `docs` commands to
automatically watch and re-execute the command on file changes.
@Quantumplation & @KtorZ
- acceptance tests 28-30 @MicroProofs
- **aiken-lang**: expose BLS builtins and types @MicroProofs & @rvcas
- **aiken-lsp**: implement hover info for tuples, lists, and contructor pattern
elements @rvcas
- **aiken-lsp**: implement hover on when clause patterns @rvcas
- **aiken-lsp**: hover support for the optional multi validator fn @rvcas
- **aiken-lsp**: implement quickfix for "utf8 byte array is valid hex string"
warning @rvcas
- **uplc**: add all BLS builtins and types @MicroProofs & @rvcas
- **uplc**: add plutus conformance tests from
[here](https://github.com/input-output-hk/plutus/tree/master/plutus-conformance/test-cases/uplc/evaluation).
@MicroProofs & @rvcas
- **uplc**: case and constr cost models @MicroProofs
### Changed
- **aiken**: update to pallas v0.20.0 @rvcas
- **aiken-project**: switch blueprint validator tests now uses insta
@MicroProofs
- **aiken-project**: update to pallas v0.20.0 @rvcas
- **aiken-lang**: use a better algorithm for inlining single occurrences
@MicroProofs
- **uplc**: update to pallas v0.20.0 @rvcas
- **uplc**: remove `flat-rs` crate and use it through pallas_codec instead
### Fixed
- **aiken-lang**: formatting unable to have newline after expect bool shortcut
@rvcas
- **aiken-lang**: formatter incorrectly erasing blocks in certain situations
@rvcas
- **aiken-lang**: use a distinct warning for discarded let assignments to avoid
confusion @rvcas
- **aiken-lang**: allow spread operator on positional constructor arguments
@rvcas
- **aiken-lsp**: and/or chains hovering on nested elements not working @rvcas
- **uplc**: delay typemismatch errors in the machine runtime (caught by
conformance tests) @rvcas
## v1.0.20-alpha - 2023-10-25
### Added
- **aiken-project**: The `plutus.json` blueprint now contains a `compiler.name`
and `compiler.version` fields.
- **aiken-prokect**: Added compiler and system information to panic error
report.
- **aiken-lsp**: Added quickfix suggestions for unknown variables, modules and
constructors.
### Changed
- **aiken-lang**: Added validator specific error when validator returns false
- **aiken-lang**: Running a multi-validator with traces on will let you know
which validator function is running
- **aiken-lang**: Multi-validator with traces will give a better error when the
'spend' redeemer is not properly wrapped with a constr
- **aiken-lang**: Code gen traces are referenced instead of being inlined
leading to smaller validators
### Fixed
- **aiken-lang**: improved error messages for `a |> b(x)`.
- **uplc**: Fixed cost model issue when using div, quot, rem, mod.
- **aiken-lsp**: Improved hovering suggestions and type annotations.
## v1.0.19-alpha - 2023-09-29
### Fixed
- **aiken-lang**: Fixed small typo in `hoist_dependent_functions` lead to
internal cyclic calls not being recognized.
## v1.0.18-alpha - 2023-09-29
### Added
- **aiken-lang**: Code gen now allows for mutual recursion
### Fixed
- **aiken-lang**: fixed stack overflow with unbound typing being passed into a
function with inferred types
- **aiken-lang**: expect on tuples greater than 2 checks the length to ensure
tuple lists are the same length as the type.
### Changed
- **aiken-lang**: (Code Gen): Rename some of the types to use aliases
- **aiken-lang**: (Code Gen): Remove the use of Air::RecordAccess and TupleIndex
and replace them with functions that directly get the item at the specified
index. Also improves performance.
- **uplc**: Added more cases to the inline optimization function to allow the
removal of further unnecessary lambda bindings.
## v1.0.17-alpha - 2023-09-20
### Added
- **aiken**: add ability to force warnings to cause a failing exit code on
check, build, and docs
- **aiken-lang**: automatically resolve and fetch latest revision of a package
on build when a branch is specified as version
- **uplc**: Add Case and Constr Terms; This includes their flat serialization
and evaluation
### Fixed
- **uplc**: trim whitespace when loading files with hex strings to avoid
confusing errors #720
- **uplc**: uplc `Constant::Data` formatting
- **aiken-lang**: code gen fixes including nested constr when matches and expect
on None
- **aiken-lang**: empty records properly parse as record sugar
- **aiken-lang**: escape sequences are now properly preserved after formatting
- **aiken-lang**: fixed parser ambiguity when using record constructor in if
conditions followed by single-line var expressions #735
- **aiken-project**: when a module name has a hyphen we should behave like rust
and force an underscore
## v1.0.16-alpha - 2023-08-24
### Removed
- **aiken**: `aiken new` no longer accept an `--empty` flag. Projects are
generated empty by default.
## v1.0.15-alpha - 2023-08-19
### Added
- **aiken**: Parameters for `blueprint apply` can now be built interactively.
### Changed
- **aiken-lang**: Opaque types are now properly handled in code gen (i.e. in
code gen functions, in datums/redeemers, in from data casts).
- **aiken**: `blueprint apply` now expects only one OPTIONAL argument. When not
provided, the parameter will be prompted interactively.
- **aiken-lang**: New tests for code gen around opaque types.
- **aiken-lang**: `traverse_with_tree` now has a boolean parameter to determine
when `with` is called.
### Removed
- **aiken**: `blueprint apply` no longer accept a target directory. The command
has to be executed within the same directory as the `aiken.toml`.
## v1.0.14-alpha - 2023-08-16
### Added
- **aiken**: `new` command now fetches latest stdlib version
- **aiken-lang**: new `and` and `or` chaining
```
and {
1 == 1,
or {
2 == 2,
3 != 2,
True,
},
}
```
### Changed
- **aiken-lang**: significantly improved pattern matching exhuastiveness
checking
- **aiken-lang**: Tx Simulate now returns a list of execution budgets for each
redeemer instead of calculating the total units required to run all the
scripts.
- **aiken-lang**: Now code gen uses a tree abstraction to build the Aiken
Intermediary Representation. This now fixes quite a number of minor issues
while making the code more maintainable. This is a large leap towards a stable
version and future updates will be on further simplifying and stabilizing the
tree abstraction.
- **aiken-lang**: Zero argument anonymous functions now are implemted as a
delayed function body and calling them simply does force
- **aiken-lang**: Matching on int in expect and when cases is now implemented
- **aiken-lang**: Using assign in nested pattern matches is now implemented
- **aiken-lang**: Using List<Data> as a validator params only checks the type is
a list and does not attempt to check each item
- **aiken-lang**: Recursion optimization to prevent static parameters from being
passed through every recursion
- **aiken-lang**: aliased import of single type throws compiler error
- **aiken-lsp**: fix diagnostics and formatting on windows vscode
- **aiken**: decode should always print to textual
- **uplc**: pair type formatting
## v1.0.13-alpha - 2023-07-15
### Added
@ -8,24 +629,28 @@
### Fixed
- **aiken-lang**: fail, todo, and trace had issues with sequences and expressions
- **aiken-lang**: fail, todo, and trace had issues with sequences and
expressions
## v1.0.12-alpha - 2023-07-14
### Added
- **aiken**: added a `blueprint policy` command to compute the policy ID of a minting script
- **aiken**: added a `blueprint policy` command to compute the policy ID of a
minting script
- **uplc**: parsing and pretty printing for PlutusData
### Fixed
- **aiken-lang**: Prevent mutual recursion caused by conflicting function names for generic expect type
- **aiken-lang**: Prevent mutual recursion caused by conflicting function names
for generic expect type
- **aiken-lang**: UPLC evaluation of large integers literals (> max u64)
- **aiken-lang**: Parsing of error / todo keywords in when cases
- **aiken-lang**: Parsing of negative integer patterns and constants
- **aiken-lang**: automatically infer unused validator args as `Data`
- **aiken-lang**: test crashing when referencing validators
- **aiken**: mem and cpu values were not showing in white terminals, switched to cyan
- **aiken**: mem and cpu values were not showing in white terminals, switched to
cyan
### Changed
@ -52,8 +677,10 @@
### Fixed
- **aiken-lang**: Explain discards and expect a bit better in the unused var warning
- **aiken-lang**: Fix expect \_ = ... not including the cast from data logic if the type is data and right hand has a type annotation
- **aiken-lang**: Explain discards and expect a bit better in the unused var
warning
- **aiken-lang**: Fix expect \_ = ... not including the cast from data logic if
the type is data and right hand has a type annotation
- **aiken-lang**: Fix for the final clause of a when expecting another clause
afterwards in nested list cases.
- **aiken-lang**: Fix for all elements were being destructured in tuple clauses
@ -61,7 +688,8 @@
- **aiken-lang**: Fix for tuple clause not consuming the next case causing
incomplete contracts. Now tuple clause will always consume the next case
unless it is the final clause
- **aiken-lang**: Fix for builtins using the incorrect data to type conversion when used as a function param.
- **aiken-lang**: Fix for builtins using the incorrect data to type conversion
when used as a function param.
## v1.0.10-alpha - 2023-06-13

View File

@ -71,14 +71,44 @@
Want to give some financial support? Have a look at the ways to sponsor below for more details.
- [rvcas](https://github.com/sponsors/rvcas/)
- [microproofs](https://github.com/sponsors/microproofs/)
- [rvcas](https://github.com/sponsors/rvcas)
- [microproofs](https://github.com/sponsors/microproofs)
- [ktorz](https://github.com/sponsors/KtorZ)
Want to support with crypto?
- Our Ada address is `addr1q83nlzwu4zjeu927m8t24xa68upgmwgt5w29ww5ka695hc5rez2r4q7gcvj7z0ma6d88w3j220szsqk05sn43ghcsn4szvuklq`
- Our Ada handle is `$aiken_lang`
## Releasing
To be able to create a release you need to be on the [maintainers](https://github.com/orgs/aiken-lang/teams/maintainers) team.
This means that only core team members can create releases. We have a
[github action](https://github.com/aiken-lang/aiken/blob/main/.github/workflows/release.yml) for creating the binaries and a github release.
The process follows these steps:
1. `cargo release --execute`
2. After a release is created by the github action fill in the release notes. Try to tag contributors so that they show up in the release.
3. Screenshot the result of `aikup` and post on twitter saying "We've just released vx.x.x". [example](https://twitter.com/aiken_eng/status/1693084816931987930?s=20)
> `cargo release` takes arguments and flags to tell it how to bump the version number. Examples include `cargo release 1.0.16-alpha` and `cargo release major`.
>
> The root `Cargo.toml` in the repo contains this configuration for `cargo release`:
>
> ```toml
> [workspace.metadata.release]
> shared-version = true
> tag-name = "v{{version}}"
> ```
> [!IMPORTANT]
>
> Since v1.1.4, we have switched to producing statically linked binary with musl, preventing issues with openssl on various linux platforms. However, this changes the artifact name
> from: `aiken-x86_64-unknown-linux-gnu.tar.gz` to `aiken-x86_64-unknown-linux-musl.tar.gz`. Consequently, we've patched `aikup` in version v0.0.11, but people using previous
> version will fail to install aiken through aikup. So for a little a while, we need to manually re-upload a `-gnu.tar.gz` archive (which can be obtained by simply renaming the musl one) so that aikup can keep fetching artifacts on Linux prior to version `v0.0.11`. We can cease doing that once enough time has reasonably passed and enough people have switched to aikup.
>
> Ideally, we should introduce an `upgrade` command to aikup, and have some kind of notification system that indicates to people that they should upgrade their aikup installer.
## About Issues
### :bug: How To Report A Bug

2434
Cargo.lock generated vendored

File diff suppressed because it is too large Load Diff

View File

@ -1,18 +1,70 @@
[workspace]
members = ["crates/*"]
[profile.release]
strip = true
resolver = "2"
[workspace.metadata.release]
shared-version = true
tag-name = "v{{version}}"
# Config for 'cargo dist'
[workspace.metadata.dist]
# The preferred cargo-dist version to use in CI (Cargo.toml SemVer syntax)
cargo-dist-version = "0.22.1"
# CI backends to support
ci = "github"
# The installers to generate for each app
installers = ["shell", "powershell", "npm", "homebrew"]
# A GitHub repo to push Homebrew formulas to
tap = "aiken-lang/homebrew-tap"
# Target platforms to build apps for (Rust target-triple syntax)
targets = ["aarch64-apple-darwin", "x86_64-apple-darwin", "x86_64-unknown-linux-musl", "x86_64-pc-windows-msvc"]
# The archive format to use for windows builds (defaults .zip)
windows-archive = ".tar.gz"
# The archive format to use for non-windows builds (defaults .tar.xz)
unix-archive = ".tar.gz"
# A namespace to use when publishing this package to the npm registry
npm-scope = "@aiken-lang"
# Publish jobs to run in CI
publish-jobs = ["homebrew", "npm"]
# Which actions to run on pull requests
pr-run-mode = "plan"
# Whether to install an updater program
install-updater = false
# Path that installers should place binaries in
install-path = "~/.aiken/bin"
# Whether to publish prereleases to package managers
publish-prereleases = true
# Inject build steps into the build-local-artifacts job to prepare the container.
# This is needed to install libssl-dev and musl tools for producing statically linked
# binary on Linux and avoid weird segfaults.
#
# Note: should be a path relative to the .github/workflows/ directory, and
# which should point to a .yml file containing the github workflow steps just
# as one would normally write them in a workflow.
github-build-setup = "../musl-build-setup.yml"
# Cargo-dist uses ubuntu-20.04 by default, causing issues in various cases
# because it links with openssl-1.1 whereas recent distro ships with 3.x
[workspace.metadata.dist.github-custom-runners]
x86_64-unknown-linux-musl = "ubuntu-22.04"
[workspace.dependencies]
insta = { version = "1.30.0", features = ["yaml"] }
walkdir = "2.3.2"
insta = { version = "1.30.0", features = ["yaml", "json", "redactions"] }
miette = { version = "7.2.0" }
pallas-addresses = "0.31.0"
pallas-codec = { version = "0.31.0", features = ["num-bigint"] }
pallas-crypto = "0.31.0"
pallas-primitives = "0.31.0"
pallas-traverse = "0.31.0"
[profile.dev.package.insta]
opt-level = 3
[profile.dev.package.similar]
opt-level = 3
# The profile that 'cargo dist' will build with
[profile.dist]
inherits = "release"
lto = "thin"

View File

@ -187,7 +187,8 @@
identification within third-party archives.
Copyright 2016-2022 Louis Pilfold (as Gleam)
Copyright 2022-Present TxPipe & Lucas Rosa (as Aiken)
Copyright 2022-2024 Cardano Foundation (as Aiken)
Copyright 2024-Present PRAGMA (as Aiken)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@ -1,36 +1,46 @@
<div align="center">
<img src="https://raw.githubusercontent.com/aiken-lang/branding/main/assets/logo-light.png?sanitize=true#gh-dark-mode-only" alt="Aiken" height="150" />
<img src="https://raw.githubusercontent.com/aiken-lang/branding/main/assets/logo-dark.png?sanitize=true#gh-light-mode-only" alt="Aiken" height="150" />
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/aiken-lang/branding/main/assets/logo-light.png">
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/aiken-lang/branding/main/assets/logo-dark.png">
<img alt="Aiken" src="https://raw.githubusercontent.com/aiken-lang/branding/main/assets/logo-dark.png" height="150">
</picture>
<hr />
<h2 align="center" style="border-bottom: none">A modern smart contract platform for Cardano</h2>
[![Licence](https://img.shields.io/github/license/aiken-lang/aiken)](https://github.com/aiken-lang/aiken/blob/main/LICENSE)
[![Crates.io](https://img.shields.io/crates/v/aiken)](https://crates.io/crates/aiken)
[![Tests](https://github.com/aiken-lang/aiken/actions/workflows/tests.yml/badge.svg?branch=main)](https://github.com/aiken-lang/aiken/actions/workflows/tests.yml)
[![Licence](https://img.shields.io/github/license/aiken-lang/aiken?style=for-the-badge)](https://github.com/aiken-lang/aiken/blob/main/LICENSE)
[![Tests](https://img.shields.io/github/actions/workflow/status/aiken-lang/aiken/tests.yml?style=for-the-badge)](https://github.com/aiken-lang/aiken/actions/workflows/tests.yml)
[![Twitter/X](https://img.shields.io/badge/Follow%20us-@aiken__eng-blue?logo=x&style=for-the-badge)](https://x.com/aiken_eng)
[![Crates.io](https://img.shields.io/crates/v/aiken?style=for-the-badge)](https://crates.io/crates/aiken)
[![NPM](https://img.shields.io/npm/v/%40aiken-lang%2Faiken?style=for-the-badge)](https://www.npmjs.com/package/@aiken-lang/aiken)
<hr/>
</div>
## Installation
## Getting Started
- [Linux/MacOS](https://aiken-lang.org/installation-instructions#from-aikup-linux--macos-only)
- [Windows](https://aiken-lang.org/installation-instructions#from-sources-all-platforms)
- [nix](https://aiken-lang.org/installation-instructions#from-nix-flakes-linux--macos-only)
- [Installation instructions](https://aiken-lang.org/installation-instructions)
### How to use
- [Online playground](https://play.aiken-lang.org/)
For more information please see the [user manual](https://aiken-lang.org).
- [Beginner checklist](https://aiken-lang.org/fundamentals/getting-started#checklist)
### Hello, World!
Wanna get started right-away? Complete the [_Hello, World!_ tutorial](https://aiken-lang.org/example--hello-world/basics)!
## Contributing
Want to contribute? See [CONTRIBUTING.md](./CONTRIBUTING.md) to know how.
---
## Changelog
> **Note**
>
> The name comes from [Howard Aiken](https://en.wikipedia.org/wiki/Howard_H._Aiken), an American physicist and a pioneer in computing.
Be on top of any updates using the [CHANGELOG](https://github.com/aiken-lang/aiken/blob/main/CHANGELOG.md) and the [Project Tracking](https://github.com/orgs/aiken-lang/projects/2/views/1).
## Stats
![Alt](https://repobeats.axiom.co/api/embed/c93f72d2f0dd8cac82fc230ea97fa23787b32978.svg "Repobeats analytics image")
> [!NOTE]
>
> The name comes from [Howard Aiken](https://en.wikipedia.org/wiki/Howard_H._Aiken), an American physicist and a pioneer in computing.

View File

@ -1,17 +0,0 @@
# `aikup`
Update or revert to a specific Aiken version with ease.
## Installing
```sh
curl -sSfL https://install.aiken-lang.org | bash
```
## Usage
To install a specific **version** (in this case the `v0.1.0`):
```sh
aikup install v0.1.0
```

View File

@ -1,197 +0,0 @@
#!/usr/bin/env bash
set -e
AIKEN_DIR=${AIKEN_DIR-"$HOME/.aiken"}
AIKEN_BIN_DIR="$AIKEN_DIR/bin"
BINS=(aiken)
export RUSTFLAGS="-C target-cpu=native"
main() {
need_cmd git
need_cmd curl
while [[ $1 ]]; do
case $1 in
--) shift; break;;
install) shift; AIKUP_VERSION=$1;;
-l|--list)
list_versions
exit 0
;;
-h|--help)
usage
exit 0
;;
*)
warn "unknown option: $1"
usage
exit 1
esac; shift
done
if [ -z "$AIKUP_VERSION" ]; then
AIKUP_VERSION=$(get_latest_release)
say "no version specified; installing latest: $AIKUP_VERSION"
fi
# Print the banner after successfully parsing args
banner
AIKUP_REPO="aiken-lang/aiken"
AIKUP_TAG=$AIKUP_VERSION
# Normalize versions
if [[ "$AIKUP_VERSION" == [[:digit:]]* ]]; then
# Add v prefix
AIKUP_VERSION="v${AIKUP_VERSION}"
AIKUP_TAG="${AIKUP_VERSION}"
fi
say "installing aiken (version ${AIKUP_VERSION}, tag ${AIKUP_TAG})"
PLATFORM="$(uname -s)"
case $PLATFORM in
Linux)
PLATFORM="linux"
;;
Darwin)
PLATFORM="darwin"
;;
*)
err "unsupported platform: $PLATFORM"
;;
esac
ARCHITECTURE="$(uname -m)"
if [ "${ARCHITECTURE}" = "x86_64" ]; then
# Redirect stderr to /dev/null to avoid printing errors if non Rosetta.
if [ "$(sysctl -n sysctl.proc_translated 2>/dev/null)" = "1" ]; then
ARCHITECTURE="arm64" # Rosetta.
else
ARCHITECTURE="amd64" # Intel.
fi
elif [ "${ARCHITECTURE}" = "arm64" ] ||[ "${ARCHITECTURE}" = "aarch64" ] ; then
ARCHITECTURE="arm64" # Arm.
else
ARCHITECTURE="amd64" # Amd.
fi
# Compute the URL of the release tarball in the Aiken repository.
RELEASE_URL="https://github.com/${AIKUP_REPO}/releases/download/${AIKUP_TAG}/"
BIN_TARBALL_URL="${RELEASE_URL}aiken_${AIKUP_VERSION}_${PLATFORM}_${ARCHITECTURE}.tar.gz"
# Download the binaries tarball and unpack it into the .aiken bin directory.
say "downloading aiken"
ensure curl -# -L "$BIN_TARBALL_URL" | tar -xzC "$AIKEN_BIN_DIR"
for bin in "${BINS[@]}"; do
bin_path="$AIKEN_BIN_DIR/$bin"
# Print installed msg
say "installed - $("$bin_path" --version)"
# Check if the default path of the binary is not in AIKEN_BIN_DIR
which_path="$(which "$bin")"
if [ "$which_path" != "$bin_path" ]; then
warn ""
cat 1>&2 <<EOF
There are multiple binaries with the name '$bin' present in your 'PATH'.
This may be the result of installing '$bin' using another method,
like Cargo or other package managers.
You may need to run 'rm $which_path' or move '$AIKEN_BIN_DIR'
in your 'PATH' to allow the newly installed version to take precedence!
EOF
fi
done
say "done"
}
usage() {
cat 1>&2 <<EOF
The installer for Aiken.
Update or revert to a specific Aiken version with ease.
USAGE:
aikup <SUBCOMMAND>
OPTIONS:
-l, --list List available versions
-h, --help Print help information
SUBCOMMANDS:
install Install a specific version
EOF
}
list_versions() {
say "available versions"
curl -sSL "https://api.github.com/repos/aiken-lang/aiken/tags" |
grep -E '"name": "v[1-9]' |
sed 's/.*\(v[^"]*\)",.*/\1/'
}
get_latest_release () {
curl --silent "https://api.github.com/repos/aiken-lang/aiken/releases/latest" |
grep '"tag_name":' |
sed -E 's/.*"([^"]+)".*/\1/'
}
say() {
printf "aikup: %s\n" "$1"
}
warn() {
say "warning: ${1}" >&2
}
err() {
say "$1" >&2
exit 1
}
need_cmd() {
if ! check_cmd "$1"; then
err "need '$1' (command not found)"
fi
}
check_cmd() {
command -v "$1" > /dev/null 2>&1
}
# Run a command that should never fail. If the command fails execution
# will immediately terminate with an error showing the failing
# command.
ensure() {
if ! "$@"; then err "command failed: $*"; fi
}
# Banner Function for Aiken
banner() {
printf '
================================================================================
░█▀▀▄░▀█▀░▒█░▄▀░▒█▀▀▀░▒█▄░▒█ Modern and modular toolkit
▒█▄▄█░▒█░░▒█▀▄░░▒█▀▀▀░▒█▒█▒█ for Cardano Smart Contract development.
▒█░▒█░▄█▄░▒█░▒█░▒█▄▄▄░▒█░░▀█ Written in Rust.
================================================================================
Repo : https://github.com/aiken-lang/aiken
Docs : https://aiken-lang.org/
Chat : https://discord.gg/Vc3x8N9nz2
Contribute : https://github.com/aiken-lang/aiken/blob/main/CONTRIBUTING.md
================================================================================
'
}
main "$@" || exit 1

View File

@ -1,51 +0,0 @@
#!/usr/bin/env bash
set -e
echo Installing aikup...
AIKEN_DIR=${AIKEN_DIR-"$HOME/.aiken"}
AIKEN_BIN_DIR="$AIKEN_DIR/bin"
BIN_URL="https://raw.githubusercontent.com/aiken-lang/aiken/main/aikup/aikup"
BIN_PATH="$AIKEN_BIN_DIR/aikup"
# Create the .aiken bin directory and aikup binary if it doesn't exist.
mkdir -p $AIKEN_BIN_DIR
curl -# -L $BIN_URL -o $BIN_PATH
chmod +x $BIN_PATH
# Store the correct profile file (i.e. .profile for bash or .zshrc for ZSH).
case $SHELL in
*/zsh)
PROFILE=$HOME/.zshrc
PREF_SHELL=zsh
INJECT="export PATH=\"\$PATH:$AIKEN_BIN_DIR\""
;;
*/bash)
PROFILE=$HOME/.bashrc
PREF_SHELL=bash
INJECT="export PATH=\"\$PATH:$AIKEN_BIN_DIR\""
;;
*/fish)
PROFILE=$HOME/.config/fish/config.fish
PREF_SHELL=fish
INJECT="fish_add_path $AIKEN_BIN_DIR"
;;
*/ash)
PROFILE=$HOME/.profile
PREF_SHELL=ash
INJECT="export PATH=\"\$PATH:$AIKEN_BIN_DIR\""
;;
*)
echo "aikup: could not detect shell, manually add ${AIKEN_BIN_DIR} to your PATH."
exit 1
esac
# Only add aikup if it isn't already in PATH.
if [[ ":$PATH:" != *":${AIKEN_BIN_DIR}:"* ]]; then
# Add the aikup directory to the path and ensure the old PATH variables remain.
echo >> $PROFILE && echo "$INJECT" >> $PROFILE
fi
echo && echo "Detected your preferred shell is ${PREF_SHELL} and added aikup to PATH. Run 'source ${PROFILE}' or start a new terminal session to use aikup."
echo "Then, simply run 'aikup' to install Aiken."

6
benchmarks/.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
# Aiken compilation artifacts
artifacts/
# Aiken's project working directory
build/
# Aiken's default documentation export
docs/

170
benchmarks/README.md Normal file
View File

@ -0,0 +1,170 @@
# (No Fib) Benchmarks
This folder contains a set of benchmarks inspired and ported from the [plutus-benchmarks](https://github.com/IntersectMBO/plutus/tree/master/plutus-benchmark/nofib#plutus-nofib-benchmarks), written in Haskell. The idea is to provide benchmarks which can capture more realistic patterns and behaviours than usual "Fibonacci" benchmarks often used for benchmarking applications but falling short in capturing real-world scenarios.
Note that the primary use-case of those benchmarks is to compare Aiken with itself across compiler versions. As optimizations get implemented, it comes as a supplimentary means to assess their impact.
## Summary
Results are summarized below, relatively to the previous version. For brevity, we only report versions for which there's a deviation from a previous version.
<!--
Plutus-Tx
Script Size CPU budget Memory budget
-----------------------------------------------------------------
clausify/F1 1573 3316814452 19803348
clausify/F2 1573 4329805760 25708376
clausify/F3 1573 11847889335 70086982
clausify/F4 1573 26924400260 152296076
clausify/F5 1573 57792275160 340971480
knights/4x4 2049 16660243968 86107706
knights/6x6 2049 49595956778 271079788
knights/8x8 2049 89757683708 495426680
primes/05digits 1501 9617902676 37194205
primes/08digits 1501 15888515320 60723255
primes/10digits 1501 18980946392 71916641
primes/20digits 1501 36493682732 137260387
primes/30digits 1501 57224069574 214186802
primes/40digits 1501 75870264649 282727215
primes/50digits 1501 93666987132 345920797
queens4x4/bt 1867 5135006267 28184130
queens4x4/bm 1867 6345082859 35502236
queens4x4/bjbt1 1867 6252769293 34895616
queens4x4/bjbt2 1867 5820721293 32195316
queens4x4/fc 1867 13740412571 78668768
queens5x5/bt 1867 71081240426 381100320
queens5x5/bm 1867 71574838831 400366576
queens5x5/bjbt1 1867 82536005114 449984088
queens5x5/bjbt2 1867 79887717114 433432288
queens5x5/fc 1867 179227518621 1023295666
-->
<!--
v1.1.0
┍━ benchmarks/clausify/benchmark ━━━━━━━━━━━━━━━━━━━━━━━━━━━
│ PASS [mem: 53769377, cpu: 16198154564] bench_clausify_f1
│ PASS [mem: 67108683, cpu: 20169891270] bench_clausify_f2
│ PASS [mem: 179606857, cpu: 53923018831] bench_clausify_f3
│ PASS [mem: 231444137, cpu: 70014384566] bench_clausify_f4
│ PASS [mem: 874286879, cpu: 262421671684] bench_clausify_f5
┕━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 5 tests | 5 passed | 0 failed
┍━ benchmarks/knights/benchmark ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
│ PASS [mem: 172246681, cpu: 57037226471] bench_knights_100_4x4
│ PASS [mem: 321690197, cpu: 137399466410] bench_knights_100_6x6
│ PASS [mem: 601026745, cpu: 281418742606] bench_knights_100_8x8
┕━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3 tests | 3 passed | 0 failed
v1.0.29-alpha & v1.0.28-alpha
┍━ benchmarks/clausify/benchmark ━━━━━━━━━━━━━━━━━━━━━━━━━━━
│ PASS [mem: 53769377, cpu: 21594809455] bench_clausify_f1
│ PASS [mem: 67108683, cpu: 26864755594] bench_clausify_f2
│ PASS [mem: 179606857, cpu: 71814854199] bench_clausify_f3
│ PASS [mem: 231444137, cpu: 93024749730] bench_clausify_f4
│ PASS [mem: 874286879, cpu: 349894049008] bench_clausify_f5
┕━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 5 tests | 5 passed | 0 failed
┍━ benchmarks/knights ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
│ PASS [mem: 172256715, cpu: 71851995726] bench_knights_100_4x4
│ PASS [mem: 321712271, cpu: 159767368294] bench_knights_100_6x6
│ PASS [mem: 601065675, cpu: 319834775948] bench_knights_100_8x8
┕━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3 tests | 3 passed | 0 failed
==== There's no 1.0.27-alpha
v1.0.26-alpha & V1.0.25-alpha
┍━ benchmarks/clausify/benchmark ━━━━━━━━━━━━━━━━━━━━━━━━━━━
│ PASS [mem: 52538257, cpu: 20243486892] bench_clausify_f1
│ PASS [mem: 65404263, cpu: 25235091975] bench_clausify_f2
│ PASS [mem: 174866054, cpu: 67523028814] bench_clausify_f3
│ PASS [mem: 225087758, cpu: 88367835856] bench_clausify_f4
│ PASS [mem: 851294369, cpu: 328896952793] bench_clausify_f5
┕━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 5 tests | 5 passed | 0 failed
┍━ benchmarks/knights ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
│ PASS [mem: 171421863, cpu: 72861467671] bench_knights_100_4x4
│ PASS [mem: 354137347, cpu: 174027736310] bench_knights_100_6x6
│ PASS [mem: 688090183, cpu: 356296429240] bench_knights_100_8x8
┕━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3 tests | 3 passed | 0 failed
v1.0.24-alpha & V1.0.23-alpha
┍━ benchmarks/clausify/benchmark ━━━━━━━━━━━━━━━━━━━━━━━━━━━━
│ PASS [mem: 64738801, cpu: 24123180244] bench_clausify_f1
│ PASS [mem: 80280627, cpu: 29901360387] bench_clausify_f2
│ PASS [mem: 214423277, cpu: 79840016473] bench_clausify_f3
│ PASS [mem: 269232481, cpu: 101739948515] bench_clausify_f4
│ PASS [mem: 1045036759, cpu: 389233562263] bench_clausify_f5
┕━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 5 tests | 5 passed | 0 failed
┍━ benchmarks/knights ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
│ PASS [mem: 180946463, cpu: 75052125671] bench_knights_100_4x4
│ PASS [mem: 374910247, cpu: 178805503310] bench_knights_100_6x6
│ PASS [mem: 729107683, cpu: 365730454240] bench_knights_100_8x8
┕━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3 tests | 3 passed | 0 failed
==== There's no 1.0.22-alpha
V1.0.21-alpha
┍━ benchmarks/clausify/benchmark ━━━━━━━━━━━━━━━━━━━━━━━━━━━━
│ PASS [mem: 64738801, cpu: 24123180244] bench_clausify_f1
│ PASS [mem: 80280627, cpu: 29901360387] bench_clausify_f2
│ PASS [mem: 214423277, cpu: 79840016473] bench_clausify_f3
│ PASS [mem: 269232481, cpu: 101739948515] bench_clausify_f4
│ PASS [mem: 1045036759, cpu: 389233562263] bench_clausify_f5
┕━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 5 tests | 5 passed | 0 failed
┍━ benchmarks/knights ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
│ PASS [mem: 180697463, cpu: 74944457471] bench_knights_100_4x4
│ PASS [mem: 374661247, cpu: 178697835110] bench_knights_100_6x6
│ PASS [mem: 728858683, cpu: 365622786040] bench_knights_100_8x8
┕━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3 tests | 3 passed | 0 failed
V1.0.20-alpha, v1.0.19-alpha & v1.0.18-alpha
┍━ benchmarks/clausify/benchmark ━━━━━━━━━━━━━━━━━━━━━━━━━━━━
│ PASS [mem: 64861501, cpu: 24151401244] bench_clausify_f1
│ PASS [mem: 80442927, cpu: 29938689387] bench_clausify_f2
│ PASS [mem: 214833977, cpu: 79934477473] bench_clausify_f3
│ PASS [mem: 269959981, cpu: 101907273515] bench_clausify_f4
│ PASS [mem: 1046684059, cpu: 389612441263] bench_clausify_f5
┕━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 5 tests | 5 passed | 0 failed
┍━ benchmarks/knights ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
│ PASS [mem: 182244075, cpu: 75300076471] bench_knights_100_4x4
│ PASS [mem: 380548699, cpu: 180051720110] bench_knights_100_6x6
│ PASS [mem: 740194031, cpu: 368229509040] bench_knights_100_8x8
┕━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3 tests | 3 passed | 0 failed
-->
### CPU
| Benchmark | `v1.1.0` | vs `v1.0.29` | vs `v1.0.25` | vs `v1.0.23` | vs `v1.0.21` |
| --- | ---: | ---: | ---: | ---: | ---: |
| `clausify_f1` | 16198154564 | -24.99% | -6.26% | +11.71% | +11.71% |
| `clausify_f2` | 20169891270 | -24.92% | -6.07% | +11.30% | +11.30% |
| `clausify_f3` | 53923018831 | -24.91% | -5.98% | +11.17% | +11.17% |
| `clausify_f4` | 70014384566 | -24.74% | -5.01% | +9.37% | +9.37% |
| `clausify_f5` | 262421671684 | -25.00% | -6.00% | +11.24% | +11.24% |
| `knights_100_4x4` | 57037226471 | -20.62% | +1.40% | +4.45% | +4.30% |
| `knights_100_6x6` | 137399466410 | -14.00% | +8.93% | +11.92% | +11.85% |
| `knights_100_8x8` | 281418742606 | -12.00% | +11.40% | +14.35% | +14.32% |
### Mem
| Benchmark | `v1.1.0` | vs `v1.0.29` | vs `v1.0.25` | vs `v1.0.23` | vs `v1.0.21` |
| --- | ---: | ---: | ---: | ---: | ---: |
| `clausify_f1` | 53769377 | ± 0.00% | -2.29% | +20.40% | +20.40% |
| `clausify_f2` | 67108683 | ± 0.00% | -2.54% | +19.63% | +19.63% |
| `clausify_f3` | 179606857 | ± 0.00% | -2.64% | +19.38% | +19.38% |
| `clausify_f4` | 231444137 | ± 0.00% | -2.75% | +16.33% | +16.33% |
| `clausify_f5` | 874286879 | ± 0.00% | -2.63% | +19.53% | +19.53% |
| `knights_100_4x4` | 172246681 | -0.01% | -0.48% | +5.04% | +4.90% |
| `knights_100_6x6` | 321690197 | -0.01% | +10.08% | +16.54% | +16.46% |
| `knights_100_8x8` | 601026745 | -0.01% | +14.48% | +21.30% | +21.26% |

View File

@ -11,3 +11,6 @@ name = "aiken-lang/stdlib"
version = "main"
requirements = []
source = "github"
[etags]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1725022066, nanos_since_epoch = 34627000 }, "21da5761ffd088c964cb038888826da8a6ea1d8c26f6f4e8a1dc6e97a64fe3f7"]

14
benchmarks/aiken.toml Normal file
View File

@ -0,0 +1,14 @@
name = "aiken/benchmarks"
version = "0.0.0"
license = "Apache-2.0"
description = "Aiken contracts for project 'aiken/benchmarks'"
[repository]
user = "aiken"
project = "benchmarks"
platform = "github"
[[dependencies]]
name = "aiken-lang/stdlib"
version = "main"
source = "github"

View File

@ -0,0 +1,300 @@
use aiken/collection/list
use aiken/primitive/int
// ------------------------------------------------------------------ Benchmarks
test bench_clausify_f1() {
run_clausify(F1) == []
}
test bench_clausify_f2() {
run_clausify(F2) == []
}
test bench_clausify_f3() {
run_clausify(F3) == [([1], [])]
}
test bench_clausify_f4() {
run_clausify(F4) == [
([1], [2, 3, 4, 5, 6, 7]),
([1, 2, 3], [4, 5, 6, 7]),
([1, 2, 3, 4, 5], [6, 7]),
([1, 2, 3, 4, 5, 6, 7], []),
([1, 2, 3, 4, 6], [5, 7]),
([1, 2, 3, 4, 7], [5, 6]),
([1, 2, 3, 5, 6], [4, 7]),
([1, 2, 3, 5, 7], [4, 6]),
([1, 2, 3, 6, 7], [4, 5]),
([1, 2, 4], [3, 5, 6, 7]),
([1, 2, 4, 5, 6], [3, 7]),
([1, 2, 4, 5, 7], [3, 6]),
([1, 2, 4, 6, 7], [3, 5]),
([1, 2, 5], [3, 4, 6, 7]),
([1, 2, 5, 6, 7], [3, 4]),
([1, 2, 6], [3, 4, 5, 7]),
([1, 2, 7], [3, 4, 5, 6]),
([1, 3, 4], [2, 5, 6, 7]),
([1, 3, 4, 5, 6], [2, 7]),
([1, 3, 4, 5, 7], [2, 6]),
([1, 3, 4, 6, 7], [2, 5]),
([1, 3, 5], [2, 4, 6, 7]),
([1, 3, 5, 6, 7], [2, 4]),
([1, 3, 6], [2, 4, 5, 7]),
([1, 3, 7], [2, 4, 5, 6]),
([1, 4, 5], [2, 3, 6, 7]),
([1, 4, 5, 6, 7], [2, 3]),
([1, 4, 6], [2, 3, 5, 7]),
([1, 4, 7], [2, 3, 5, 6]),
([1, 5, 6], [2, 3, 4, 7]),
([1, 5, 7], [2, 3, 4, 6]),
([1, 6, 7], [2, 3, 4, 5]),
([2], [1, 3, 4, 5, 6, 7]),
([2, 3, 4], [1, 5, 6, 7]),
([2, 3, 4, 5, 6], [1, 7]),
([2, 3, 4, 5, 7], [1, 6]),
([2, 3, 4, 6, 7], [1, 5]),
([2, 3, 5], [1, 4, 6, 7]),
([2, 3, 5, 6, 7], [1, 4]),
([2, 3, 6], [1, 4, 5, 7]),
([2, 3, 7], [1, 4, 5, 6]),
([2, 4, 5], [1, 3, 6, 7]),
([2, 4, 5, 6, 7], [1, 3]),
([2, 4, 6], [1, 3, 5, 7]),
([2, 4, 7], [1, 3, 5, 6]),
([2, 5, 6], [1, 3, 4, 7]),
([2, 5, 7], [1, 3, 4, 6]),
([2, 6, 7], [1, 3, 4, 5]),
([3], [1, 2, 4, 5, 6, 7]),
([3, 4, 5], [1, 2, 6, 7]),
([3, 4, 5, 6, 7], [1, 2]),
([3, 4, 6], [1, 2, 5, 7]),
([3, 4, 7], [1, 2, 5, 6]),
([3, 5, 6], [1, 2, 4, 7]),
([3, 5, 7], [1, 2, 4, 6]),
([3, 6, 7], [1, 2, 4, 5]),
([4], [1, 2, 3, 5, 6, 7]),
([4, 5, 6], [1, 2, 3, 7]),
([4, 5, 7], [1, 2, 3, 6]),
([4, 6, 7], [1, 2, 3, 5]),
([5], [1, 2, 3, 4, 6, 7]),
([5, 6, 7], [1, 2, 3, 4]),
([6], [1, 2, 3, 4, 5, 7]),
([7], [1, 2, 3, 4, 5, 6]),
]
}
test bench_clausify_f5() {
run_clausify(F5) == []
}
// ----------------------------------------------------------------------- Setup
type Var =
Int
type LRVars =
(List<Var>, List<Var>)
type Formula {
Sym(Var)
Not(Formula)
Dis(Formula, Formula)
Con(Formula, Formula)
Imp(Formula, Formula)
Eqv(Formula, Formula)
}
type StaticFormula {
F1
F2
F3
F4
F5
}
fn run_clausify(static_formula: StaticFormula) -> List<LRVars> {
static_formula
|> get_formula
|> clauses
}
fn get_formula(static_formula: StaticFormula) -> Formula {
when static_formula is {
// (a = a) = (a = a) = (a = a)
F1 ->
Eqv(Eqv(Sym(1), Sym(1)), Eqv(Eqv(Sym(1), Sym(1)), Eqv(Sym(1), Sym(1))))
// (a = a = a) = (a = a = a)
F2 ->
Eqv(Eqv(Sym(1), Eqv(Sym(1), Sym(1))), Eqv(Sym(1), Eqv(Sym(1), Sym(1))))
// (a = a = a) = (a = a) = (a = a)
F3 ->
Eqv(
Eqv(Sym(1), Eqv(Sym(1), Sym(1))),
Eqv(Eqv(Sym(1), Sym(1)), Eqv(Sym(1), Sym(1))),
)
// (a = b = c) = (d = e) = (f = g)
F4 ->
Eqv(
Eqv(Sym(1), Eqv(Sym(2), Sym(3))),
Eqv(Eqv(Sym(4), Sym(5)), Eqv(Sym(6), Sym(7))),
)
// (a = a = a) = (a = a = a) = (a = a)
F5 ->
Eqv(
Eqv(Sym(1), Eqv(Sym(1), Sym(1))),
Eqv(Eqv(Sym(1), Eqv(Sym(1), Sym(1))), Eqv(Sym(1), Sym(1))),
)
}
}
fn clauses(formula: Formula) -> List<LRVars> {
formula
|> elim
|> negin
|> disin
|> split
|> unicl
}
fn clause(formula: Formula) -> LRVars {
do_clause(formula, ([], []))
}
fn do_clause(formula: Formula, vars: LRVars) -> LRVars {
when formula is {
Dis(p, q) -> do_clause(p, do_clause(q, vars))
Sym(s) -> (insert_ordered(vars.1st, s, int.compare), vars.2nd)
Not(Sym(s)) -> (vars.1st, insert_ordered(vars.2nd, s, int.compare))
_ -> fail
}
}
fn conjunct(formula: Formula) -> Bool {
when formula is {
Con(_, _) -> True
_ -> False
}
}
/// eliminate connectives other than not, disjunction and conjunction
fn elim(formula: Formula) -> Formula {
when formula is {
Sym(s) -> Sym(s)
Not(p) -> Not(elim(p))
Dis(p, q) -> Dis(elim(p), elim(q))
Con(p, q) -> Con(elim(p), elim(q))
Imp(p, q) -> Dis(Not(elim(p)), elim(q))
Eqv(f1, f2) -> Con(elim(Imp(f1, f2)), elim(Imp(f2, f1)))
}
}
/// -- shift negation to innermost positions
fn negin(formula: Formula) -> Formula {
when formula is {
Not(Not(p)) -> negin(p)
Not(Con(p, q)) -> Dis(negin(Not(p)), negin(Not(q)))
Not(Dis(p, q)) -> Con(negin(Not(p)), negin(Not(q)))
Dis(p, q) -> Dis(negin(p), negin(q))
Con(p, q) -> Con(negin(p), negin(q))
p -> p
}
}
/// shift disjunction within conjunction
fn disin(formula: Formula) -> Formula {
when formula is {
Dis(p, Con(q, r)) -> Con(disin(Dis(p, q)), disin(Dis(p, r)))
Dis(Con(p, q), r) -> Con(disin(Dis(p, r)), disin(Dis(q, r)))
Dis(p, q) -> {
let dp = disin(p)
let dq = disin(q)
if conjunct(dp) || conjunct(dq) {
disin(Dis(dp, dq))
} else {
Dis(dp, dq)
}
}
Con(p, q) -> Con(disin(p), disin(q))
p -> p
}
}
/// split conjunctive proposition into a list of conjuncts
fn split(formula: Formula) -> List<Formula> {
do_split(formula, [])
}
fn do_split(f: Formula, fs: List<Formula>) -> List<Formula> {
when f is {
Con(p, q) -> do_split(p, do_split(q, fs))
_ -> [f, ..fs]
}
}
/// form unique clausal axioms excluding tautologies
fn unicl(formulas: List<Formula>) -> List<LRVars> {
list.foldr(
formulas,
[],
fn(p, xs) {
let cp = clause(p)
if tautclause(cp) {
xs
} else {
insert_ordered(xs, cp, compare_lr_vars)
}
},
)
}
/// does any symbol appear in both consequent and antecedent of clause
fn tautclause(var: LRVars) -> Bool {
list.any(var.1st, list.has(var.2nd, _))
}
/// insertion of an item into an ordered list
fn insert_ordered(es: List<a>, e: a, compare: fn(a, a) -> Ordering) -> List<a> {
when es is {
[] -> [e]
[head, ..tail] ->
when compare(e, head) is {
Less -> [e, ..es]
Greater -> [head, ..insert_ordered(tail, e, compare)]
Equal -> es
}
}
}
fn compare_lr_vars(a: LRVars, b: LRVars) -> Ordering {
when compare_list(a.1st, b.1st) is {
Equal -> compare_list(a.2nd, b.2nd)
ord -> ord
}
}
fn compare_list(xs: List<Int>, ys: List<Int>) -> Ordering {
when xs is {
[] ->
when ys is {
[] -> Equal
_ -> Less
}
[x, ..xs] ->
when ys is {
[] -> Greater
[y, ..ys] -> {
let ord = int.compare(x, y)
if ord == Equal {
compare_list(xs, ys)
} else {
ord
}
}
}
}
}

View File

@ -0,0 +1,198 @@
use aiken/collection/list
use benchmarks/knights/heuristic.{descendants, start_tour, tour_finished}
use benchmarks/knights/queue.{Queue}
use benchmarks/knights/types.{ChessSet, Solution}
// ------------------------------------------------------------------ Benchmarks
test bench_knights_100_4x4() {
run_knights(100, 4) == []
}
test bench_knights_100_6x6() {
run_knights(100, 6) == solution_100_6x6
}
test bench_knights_100_8x8() {
run_knights(100, 8) == solution_100_8x8
}
// ----------------------------------------------------------------------- Setup
fn run_knights(depth: Int, board_size: Int) -> Solution {
depth_search(depth, root(board_size), grow, done) |> queue.to_list
}
fn depth_search(
depth: Int,
xs: Queue<a>,
grow: fn(a) -> List<a>,
done: fn(a) -> Bool,
) -> Queue<a> {
if depth == 0 || queue.is_empty(xs) {
queue.empty
} else if done(queue.head(xs)) {
depth_search(depth - 1, queue.remove_front(xs), grow, done)
|> queue.append_front(queue.head(xs))
} else {
queue.append_all_front(queue.remove_front(xs), grow(queue.head(xs)))
|> depth_search(depth - 1, _, grow, done)
}
}
fn root(size: Int) -> Queue<(Int, ChessSet)> {
queue.append_all_front(queue.empty, mk_starts(size))
}
fn mk_starts(size: Int) -> List<(Int, ChessSet)> {
let it = interval(1, size)
let l =
list.flat_map(
it,
fn(x) { list.map(it, fn(y) { start_tour((x, y), size) }) },
)
let length = list.length(l)
expect length == size * size
list.zip(list.repeat(1 - length, length), l)
}
fn interval(a: Int, b: Int) -> List<Int> {
if a > b {
[]
} else {
[a, ..interval(a + 1, b)]
}
}
fn grow(item: (Int, ChessSet)) -> List<(Int, ChessSet)> {
let (x, y) = item
descendants(y) |> list.map(fn(list_item) { (x + 1, list_item) })
}
fn done(item: (Int, ChessSet)) -> Bool {
tour_finished(item.2nd)
}
// ------------------------------------------------------------------ Fixtures
const solution_100_6x6: Solution =
[
(
0,
ChessSet {
size: 6,
move_number: 36,
start: Some((1, 1)),
visited: [
(3, 2), (5, 3), (6, 1), (4, 2), (3, 4), (2, 6), (4, 5), (6, 6), (5, 4),
(6, 2), (4, 1), (2, 2), (1, 4), (3, 3), (2, 1), (1, 3), (2, 5), (4, 6),
(6, 5), (4, 4), (5, 2), (6, 4), (5, 6), (3, 5), (1, 6), (2, 4), (1, 2),
(3, 1), (4, 3), (5, 1), (6, 3), (5, 5), (3, 6), (1, 5), (2, 3), (1, 1),
],
},
),
(
0,
ChessSet {
size: 6,
move_number: 36,
start: Some((1, 1)),
visited: [
(3, 2), (5, 3), (6, 1), (4, 2), (3, 4), (2, 2), (4, 1), (6, 2), (5, 4),
(6, 6), (4, 5), (2, 6), (1, 4), (3, 3), (2, 1), (1, 3), (2, 5), (4, 6),
(6, 5), (4, 4), (5, 2), (6, 4), (5, 6), (3, 5), (1, 6), (2, 4), (1, 2),
(3, 1), (4, 3), (5, 1), (6, 3), (5, 5), (3, 6), (1, 5), (2, 3), (1, 1),
],
},
),
(
0,
ChessSet {
size: 6,
move_number: 36,
start: Some((1, 1)),
visited: [
(3, 2), (5, 3), (6, 1), (4, 2), (3, 4), (2, 2), (1, 4), (2, 6), (4, 5),
(6, 6), (5, 4), (6, 2), (4, 1), (3, 3), (2, 1), (1, 3), (2, 5), (4, 6),
(6, 5), (4, 4), (5, 2), (6, 4), (5, 6), (3, 5), (1, 6), (2, 4), (1, 2),
(3, 1), (4, 3), (5, 1), (6, 3), (5, 5), (3, 6), (1, 5), (2, 3), (1, 1),
],
},
),
(
0,
ChessSet {
size: 6,
move_number: 36,
start: Some((1, 1)),
visited: [
(3, 2), (5, 3), (6, 1), (4, 2), (3, 4), (2, 6), (1, 4), (2, 2), (4, 1),
(6, 2), (5, 4), (6, 6), (4, 5), (3, 3), (2, 1), (1, 3), (2, 5), (4, 6),
(6, 5), (4, 4), (5, 2), (6, 4), (5, 6), (3, 5), (1, 6), (2, 4), (1, 2),
(3, 1), (4, 3), (5, 1), (6, 3), (5, 5), (3, 6), (1, 5), (2, 3), (1, 1),
],
},
),
]
const solution_100_8x8: Solution =
[
(
0,
ChessSet {
size: 8,
move_number: 64,
start: Some((1, 1)),
visited: [
(3, 2), (4, 4), (5, 6), (6, 4), (8, 5), (7, 7), (6, 5), (8, 4), (7, 2),
(5, 3), (3, 4), (4, 6), (5, 8), (6, 6), (4, 5), (3, 7), (1, 8), (2, 6),
(4, 7), (5, 5), (6, 3), (5, 1), (4, 3), (3, 5), (5, 4), (7, 3), (8, 1),
(6, 2), (4, 1), (2, 2), (1, 4), (3, 3), (2, 5), (1, 3), (2, 1), (4, 2),
(6, 1), (8, 2), (7, 4), (8, 6), (7, 8), (5, 7), (3, 8), (1, 7), (3, 6),
(2, 8), (1, 6), (2, 4), (1, 2), (3, 1), (5, 2), (7, 1), (8, 3), (7, 5),
(8, 7), (6, 8), (7, 6), (8, 8), (6, 7), (4, 8), (2, 7), (1, 5), (2, 3),
(1, 1),
],
},
),
(
0,
ChessSet {
size: 8,
move_number: 64,
start: Some((1, 1)),
visited: [
(3, 2), (4, 4), (5, 6), (7, 7), (8, 5), (6, 4), (7, 2), (8, 4), (6, 5),
(5, 3), (3, 4), (4, 6), (5, 8), (6, 6), (4, 5), (3, 7), (1, 8), (2, 6),
(4, 7), (5, 5), (6, 3), (5, 1), (4, 3), (3, 5), (5, 4), (7, 3), (8, 1),
(6, 2), (4, 1), (2, 2), (1, 4), (3, 3), (2, 5), (1, 3), (2, 1), (4, 2),
(6, 1), (8, 2), (7, 4), (8, 6), (7, 8), (5, 7), (3, 8), (1, 7), (3, 6),
(2, 8), (1, 6), (2, 4), (1, 2), (3, 1), (5, 2), (7, 1), (8, 3), (7, 5),
(8, 7), (6, 8), (7, 6), (8, 8), (6, 7), (4, 8), (2, 7), (1, 5), (2, 3),
(1, 1),
],
},
),
(
0,
ChessSet {
size: 8,
move_number: 64,
start: Some((1, 1)),
visited: [
(3, 2), (4, 4), (6, 5), (8, 4), (7, 2), (5, 3), (3, 4), (4, 6), (5, 8),
(7, 7), (5, 6), (6, 4), (8, 5), (6, 6), (4, 5), (3, 7), (1, 8), (2, 6),
(4, 7), (5, 5), (6, 3), (5, 1), (4, 3), (3, 5), (5, 4), (7, 3), (8, 1),
(6, 2), (4, 1), (2, 2), (1, 4), (3, 3), (2, 5), (1, 3), (2, 1), (4, 2),
(6, 1), (8, 2), (7, 4), (8, 6), (7, 8), (5, 7), (3, 8), (1, 7), (3, 6),
(2, 8), (1, 6), (2, 4), (1, 2), (3, 1), (5, 2), (7, 1), (8, 3), (7, 5),
(8, 7), (6, 8), (7, 6), (8, 8), (6, 7), (4, 8), (2, 7), (1, 5), (2, 3),
(1, 1),
],
},
),
]

View File

@ -0,0 +1,56 @@
use aiken/collection/list
use benchmarks/knights/types.{ChessSet, Tile}
pub fn create_board(size: Int, init_square: Tile) -> ChessSet {
ChessSet {
size,
move_number: 1,
start: Some(init_square),
visited: [init_square],
}
}
pub fn add_piece(board: ChessSet, tile: Tile) -> ChessSet {
ChessSet {
..board,
move_number: board.move_number + 1,
visited: [tile, ..board.visited],
}
}
pub fn first_piece(board: ChessSet) -> Tile {
expect Some(tile) = board.start
tile
}
pub fn last_piece(board: ChessSet) -> Tile {
when board.visited is {
[] -> fail
[x, ..] -> x
}
}
pub fn delete_first(board: ChessSet) -> ChessSet {
let ChessSet { move_number, visited, .. } = board
expect Some(new_visited) = list.init(visited)
ChessSet {
..board,
move_number: move_number - 1,
start: second_last(visited),
visited: new_visited,
}
}
fn second_last(visited: List<a>) -> Option<a> {
when list.reverse(visited) is {
[] -> fail
[_] -> None
[_, a, ..] -> Some(a)
}
}
pub fn is_square_free(board: ChessSet, tile: Tile) -> Bool {
!list.has(board.visited, tile)
}

View File

@ -0,0 +1,169 @@
use aiken/builtin
use aiken/collection/list
use aiken/primitive/int
use benchmarks/knights/chess_set.{
add_piece, create_board, delete_first, first_piece, is_square_free, last_piece,
}
use benchmarks/knights/sort.{quicksort}
use benchmarks/knights/types.{ChessSet, Tile}
type Direction {
UL
UR
DL
DR
LU
LD
RU
RD
}
const direction_list = [UL, UR, DL, DR, LU, LD, RU, RD]
fn move(direction: Direction, tile: Tile) -> Tile {
let (x, y) = tile
when direction is {
UL -> (x - 1, y - 2)
UR -> (x + 1, y - 2)
DL -> (x - 1, y + 2)
DR -> (x + 1, y + 2)
LU -> (x - 2, y - 1)
LD -> (x - 2, y + 1)
RU -> (x + 2, y - 1)
RD -> (x + 2, y + 1)
}
}
pub fn start_tour(st: Tile, size: Int) -> ChessSet {
expect 0 = builtin.remainder_integer(size, 2)
create_board(size, st)
}
pub fn tour_finished(board: ChessSet) -> Bool {
let ChessSet { move_number, size, .. } = board
move_number == size * size && can_jump_first(board)
}
pub fn descendants(board: ChessSet) -> List<ChessSet> {
if and {
can_jump_first(board),
board
|> first_piece
|> add_piece(board, _)
|> dead_end,
} {
[]
} else {
let singles = single_descend(board)
when singles is {
[] ->
board
|> desc_and_no
|> quicksort(compare_chess_set)
|> list.map(fn(t) { t.2nd })
[_] -> singles
_ -> []
}
}
}
pub fn can_jump_first(board: ChessSet) -> Bool {
can_move_to(delete_first(board), first_piece(board))
}
pub fn dead_end(board: ChessSet) -> Bool {
board |> possible_moves |> builtin.null_list
}
pub fn single_descend(board: ChessSet) -> List<ChessSet> {
list.filter_map(
desc_and_no(board),
fn(item) {
let (moves, board) = item
if moves == 1 {
Some(board)
} else {
None
}
},
)
}
pub fn desc_and_no(board: ChessSet) -> List<(Int, ChessSet)> {
board
|> all_descend
|> list.map(
fn(item) {
(item |> delete_first |> possible_moves |> list.length, item)
},
)
}
pub fn can_move_to(board: ChessSet, tile: Tile) -> Bool {
let (x, y) = tile
let size = board.size
and {
x >= 1,
x <= size,
y >= 1,
y <= size,
is_square_free(board, tile),
}
}
fn can_move(board: ChessSet, direction: Direction) -> Bool {
board |> can_move_to(move(direction, last_piece(board)))
}
pub fn all_descend(board: ChessSet) -> List<ChessSet> {
board
|> possible_moves
|> list.map(move_knight(board, _))
}
fn move_knight(board: ChessSet, direction: Direction) -> ChessSet {
add_piece(board, move(direction, last_piece(board)))
}
fn possible_moves(board: ChessSet) -> List<Direction> {
direction_list |> list.filter(can_move(board, _))
}
fn compare_chess_set(a: (Int, ChessSet), b: (Int, ChessSet)) -> Ordering {
if a.1st != b.1st {
int.compare(a.1st, b.1st)
} else {
compare_list(a.2nd.visited, b.2nd.visited)
}
}
fn compare_list(xs: List<Tile>, ys: List<Tile>) -> Ordering {
when xs is {
[] ->
when ys is {
[] -> Equal
_ -> Less
}
[x, ..xs] ->
when ys is {
[] -> Greater
[y, ..ys] -> {
let ord = compare_tile(x, y)
if ord == Equal {
compare_list(xs, ys)
} else {
ord
}
}
}
}
}
fn compare_tile(a: Tile, b: Tile) -> Ordering {
if a.1st == b.1st {
int.compare(a.2nd, b.2nd)
} else {
int.compare(a.1st, b.1st)
}
}

View File

@ -0,0 +1,36 @@
use aiken/collection/list
pub opaque type Queue<a> {
inner: List<a>,
}
pub const empty: Queue<a> = [] |> Queue
pub fn to_list(self: Queue<a>) -> List<a> {
self.inner
}
pub fn is_empty(self: Queue<a>) -> Bool {
when self.inner is {
[] -> True
_ -> False
}
}
pub fn append_front(self: Queue<a>, item: a) -> Queue<a> {
list.push(self.inner, item) |> Queue
}
pub fn append_all_front(self: Queue<a>, items: List<a>) -> Queue<a> {
list.concat(items, self.inner) |> Queue
}
pub fn remove_front(self: Queue<a>) -> Queue<a> {
expect [_, ..rest] = self.inner
rest |> Queue
}
pub fn head(self: Queue<a>) -> a {
expect [q, ..] = self.inner
q
}

View File

@ -0,0 +1,18 @@
use aiken/collection/list
pub fn quicksort(xs: List<a>, compare: fn(a, a) -> Ordering) -> List<a> {
when xs is {
[] -> []
[head, ..tail] -> {
let before =
tail
|> list.filter(fn(x) { compare(x, head) == Less })
|> quicksort(compare)
let after =
tail
|> list.filter(fn(x) { compare(x, head) != Less })
|> quicksort(compare)
list.concat(before, [head, ..after])
}
}
}

View File

@ -0,0 +1,12 @@
pub type Tile =
(Int, Int)
pub type ChessSet {
size: Int,
move_number: Int,
start: Option<Tile>,
visited: List<Tile>,
}
pub type Solution =
List<(Int, ChessSet)>

14
benchmarks/plutus.json Normal file
View File

@ -0,0 +1,14 @@
{
"preamble": {
"title": "aiken/benchmarks",
"description": "Aiken contracts for project 'aiken/benchmarks'",
"version": "0.0.0",
"plutusVersion": "v2",
"compiler": {
"name": "Aiken",
"version": "v1.0.29-alpha+dfce9c1"
},
"license": "Apache-2.0"
},
"validators": []
}

View File

@ -1,41 +1,52 @@
[package]
name = "aiken-lang"
description = "The Aiken compiler"
version = "1.0.13-alpha"
version = "1.1.7"
edition = "2021"
repository = "https://github.com/aiken-lang/aiken"
homepage = "https://github.com/aiken-lang/aiken"
license = "Apache-2.0"
authors = [
"Lucas Rosa <x@rvcas.dev>",
"Kasey White <kwhitemsg@gmail.com>",
"KtorZ <matthias.benkort@gmail.com>",
"Lucas Rosa <x@rvcas.dev>",
"Kasey White <kwhitemsg@gmail.com>",
"KtorZ <matthias.benkort@gmail.com>",
]
rust-version = "1.66.1"
rust-version = "1.70.0"
build = "build.rs"
[dependencies]
blst = "0.3.11"
cryptoxide = "0.4.4"
hex = "0.4.3"
indexmap = "1.9.2"
indoc = "2.0.1"
itertools = "0.10.5"
miette = "5.9.0"
miette.workspace = true
num-bigint = "0.4.3"
ordinal = "0.3.2"
owo-colors = { version = "3.5.0", features = ["supports-colors"] }
pallas-primitives.workspace = true
patricia_tree = "0.8.0"
petgraph = "0.6.3"
pretty = "0.12.3"
serde = { version = "1.0.197", features = ["derive", "rc"] }
strum = "0.24.1"
thiserror = "1.0.39"
uplc = { path = '../uplc', version = "1.1.7" }
vec1 = "1.10.1"
uplc = { path = '../uplc', version = "1.0.13-alpha" }
num-bigint = "0.4.3"
[target.'cfg(not(target_family="wasm"))'.dependencies]
chumsky = "0.9.2"
[target.'cfg(target_family="wasm")'.dependencies]
chumsky = { version = "0.9.2", features = [
"ahash",
"std",
"ahash",
"std",
], default-features = false }
[dev-dependencies]
indoc = "2.0.1"
insta.workspace = true
pretty_assertions = "1.3.0"
[build-dependencies]
built = { version = "0.7.1", features = ["git2"] }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,352 @@
use crate::{
ast::{Annotation, Span},
tipo::{Type, TypeAliasAnnotation, TypeVar},
};
use std::{cell::RefCell, rc::Rc};
pub const BOOL: &str = "Bool";
pub const BOOL_CONSTRUCTORS: &[&str] = &["False", "True"];
pub const BYTE_ARRAY: &str = "ByteArray";
pub const DATA: &str = "Data";
pub const FUZZER: &str = "Fuzzer";
pub const G1_ELEMENT: &str = "G1Element";
pub const G2_ELEMENT: &str = "G2Element";
pub const INT: &str = "Int";
pub const LIST: &str = "List";
pub const MILLER_LOOP_RESULT: &str = "MillerLoopResult";
pub const OPTION: &str = "Option";
pub const OPTION_CONSTRUCTORS: &[&str] = &["Some", "None"];
pub const NEVER: &str = "Never";
pub const NEVER_CONSTRUCTORS: &[&str] = &["__hole", "Never"];
pub const ORDERING: &str = "Ordering";
pub const ORDERING_CONSTRUCTORS: &[&str] = &["Less", "Equal", "Greater"];
pub const PAIR: &str = "Pair";
pub const PAIRS: &str = "Pairs";
pub const PRNG: &str = "PRNG";
pub const PRNG_CONSTRUCTORS: &[&str] = &["Seeded", "Replayed"];
pub const REDEEMER_WRAPPER: &str = "RedeemerWrapper";
pub const STRING: &str = "String";
pub const VOID: &str = "Void";
pub const VOID_CONSTRUCTORS: &[&str] = &["Void"];
pub const SCRIPT_CONTEXT: &str = "__ScriptContext";
pub const SCRIPT_CONTEXT_CONSTRUCTORS: &[&str] = &["__ScriptContext"];
pub const SCRIPT_CONTEXT_TRANSACTION: &str = "__Transaction";
pub const SCRIPT_CONTEXT_REDEEMER: &str = "__Redeemer";
pub const SCRIPT_CONTEXT_PURPOSE: &str = "__ScriptPurpose";
pub const SCRIPT_PURPOSE: &str = "__ScriptPurpose";
pub const SCRIPT_PURPOSE_MINT: &str = "__Mint";
pub const SCRIPT_PURPOSE_SPEND: &str = "__Spend";
pub const SCRIPT_PURPOSE_WITHDRAW: &str = "__Withdraw";
pub const SCRIPT_PURPOSE_PUBLISH: &str = "__Publish";
pub const SCRIPT_PURPOSE_VOTE: &str = "__Vote";
pub const SCRIPT_PURPOSE_PROPOSE: &str = "__Propose";
pub const SCRIPT_PURPOSE_CONSTRUCTORS: &[&str] = &[
SCRIPT_PURPOSE_MINT,
SCRIPT_PURPOSE_SPEND,
SCRIPT_PURPOSE_WITHDRAW,
SCRIPT_PURPOSE_PUBLISH,
SCRIPT_PURPOSE_VOTE,
SCRIPT_PURPOSE_PROPOSE,
];
pub const VALIDATOR_ELSE: &str = "else";
// ----------------------------------------------------------------------------
// Types
impl Type {
pub fn data() -> Rc<Type> {
Rc::new(Type::App {
public: true,
contains_opaque: false,
name: DATA.to_string(),
module: "".to_string(),
args: vec![],
alias: None,
})
}
pub fn int() -> Rc<Type> {
Rc::new(Type::App {
public: true,
contains_opaque: false,
name: INT.to_string(),
module: "".to_string(),
args: vec![],
alias: None,
})
}
pub fn bool() -> Rc<Self> {
Rc::new(Type::App {
args: vec![],
public: true,
contains_opaque: false,
name: BOOL.to_string(),
module: "".to_string(),
alias: None,
})
}
pub fn byte_array() -> Rc<Type> {
Rc::new(Type::App {
args: vec![],
public: true,
contains_opaque: false,
name: BYTE_ARRAY.to_string(),
module: "".to_string(),
alias: None,
})
}
pub fn g1_element() -> Rc<Type> {
Rc::new(Type::App {
public: true,
contains_opaque: false,
module: "".to_string(),
name: G1_ELEMENT.to_string(),
args: vec![],
alias: None,
})
}
pub fn g2_element() -> Rc<Type> {
Rc::new(Type::App {
public: true,
contains_opaque: false,
module: "".to_string(),
name: G2_ELEMENT.to_string(),
args: vec![],
alias: None,
})
}
pub fn miller_loop_result() -> Rc<Type> {
Rc::new(Type::App {
public: true,
contains_opaque: false,
module: "".to_string(),
name: MILLER_LOOP_RESULT.to_string(),
args: vec![],
alias: None,
})
}
pub fn tuple(elems: Vec<Rc<Type>>) -> Rc<Type> {
Rc::new(Type::Tuple { elems, alias: None })
}
pub fn pair(fst: Rc<Type>, snd: Rc<Type>) -> Rc<Type> {
Rc::new(Type::Pair {
fst,
snd,
alias: None,
})
}
pub fn script_purpose() -> Rc<Type> {
Rc::new(Type::App {
args: vec![],
public: true,
contains_opaque: false,
name: SCRIPT_PURPOSE.to_string(),
module: "".to_string(),
alias: None,
})
}
pub fn script_context() -> Rc<Type> {
Rc::new(Type::App {
args: vec![],
public: true,
contains_opaque: false,
name: SCRIPT_CONTEXT.to_string(),
module: "".to_string(),
alias: None,
})
}
pub fn prng() -> Rc<Type> {
Rc::new(Type::App {
args: vec![],
public: true,
contains_opaque: false,
name: PRNG.to_string(),
module: "".to_string(),
alias: None,
})
}
pub fn fuzzer(a: Rc<Type>) -> Rc<Type> {
let prng_annotation = Annotation::Constructor {
location: Span::empty(),
module: None,
name: PRNG.to_string(),
arguments: vec![],
};
Rc::new(Type::Fn {
args: vec![Type::prng()],
ret: Type::option(Type::tuple(vec![Type::prng(), a])),
alias: Some(
TypeAliasAnnotation {
alias: FUZZER.to_string(),
parameters: vec!["a".to_string()],
annotation: Annotation::Fn {
location: Span::empty(),
arguments: vec![prng_annotation.clone()],
ret: Annotation::Constructor {
location: Span::empty(),
module: None,
name: OPTION.to_string(),
arguments: vec![Annotation::Tuple {
location: Span::empty(),
elems: vec![
prng_annotation,
Annotation::Var {
location: Span::empty(),
name: "a".to_string(),
},
],
}],
}
.into(),
},
}
.into(),
),
})
}
pub fn map(k: Rc<Type>, v: Rc<Type>) -> Rc<Type> {
Rc::new(Type::App {
public: true,
contains_opaque: false,
module: "".to_string(),
name: LIST.to_string(),
args: vec![Type::pair(k, v)],
alias: Some(
TypeAliasAnnotation {
alias: PAIRS.to_string(),
parameters: vec!["k".to_string(), "v".to_string()],
annotation: Annotation::Constructor {
location: Span::empty(),
module: None,
name: LIST.to_string(),
arguments: vec![Annotation::Pair {
location: Span::empty(),
fst: Box::new(Annotation::Var {
location: Span::empty(),
name: "k".to_string(),
}),
snd: Box::new(Annotation::Var {
location: Span::empty(),
name: "v".to_string(),
}),
}],
},
}
.into(),
),
})
}
pub fn list(t: Rc<Type>) -> Rc<Type> {
Rc::new(Type::App {
public: true,
contains_opaque: t.contains_opaque(),
name: LIST.to_string(),
module: "".to_string(),
args: vec![t],
alias: None,
})
}
pub fn string() -> Rc<Type> {
Rc::new(Type::App {
args: vec![],
public: true,
contains_opaque: false,
name: STRING.to_string(),
module: "".to_string(),
alias: None,
})
}
pub fn void() -> Rc<Type> {
Rc::new(Type::App {
args: vec![],
public: true,
contains_opaque: false,
name: VOID.to_string(),
module: "".to_string(),
alias: None,
})
}
pub fn option(a: Rc<Type>) -> Rc<Type> {
Rc::new(Type::App {
public: true,
contains_opaque: a.contains_opaque(),
name: OPTION.to_string(),
module: "".to_string(),
args: vec![a],
alias: None,
})
}
pub fn never() -> Rc<Type> {
Rc::new(Type::App {
public: true,
contains_opaque: false,
name: NEVER.to_string(),
module: "".to_string(),
args: vec![],
alias: None,
})
}
pub fn ordering() -> Rc<Type> {
Rc::new(Type::App {
public: true,
contains_opaque: false,
name: ORDERING.to_string(),
module: "".to_string(),
args: vec![],
alias: None,
})
}
pub fn function(args: Vec<Rc<Type>>, ret: Rc<Type>) -> Rc<Type> {
Rc::new(Type::Fn {
ret,
args,
alias: None,
})
}
pub fn generic_var(id: u64) -> Rc<Type> {
let tipo = Rc::new(RefCell::new(TypeVar::Generic { id }));
Rc::new(Type::Var { tipo, alias: None })
}
pub fn unbound_var(id: u64) -> Rc<Type> {
let tipo = Rc::new(RefCell::new(TypeVar::Unbound { id }));
Rc::new(Type::Var { tipo, alias: None })
}
pub fn wrapped_redeemer(redeemer: Rc<Type>) -> Rc<Type> {
Rc::new(Type::App {
public: true,
contains_opaque: false,
module: "".to_string(),
name: REDEEMER_WRAPPER.to_string(),
args: vec![redeemer],
alias: None,
})
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,3 @@
pub trait ExtraData {
fn extra_data(&self) -> Option<String>;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,430 +1,225 @@
use indexmap::IndexSet;
use std::sync::Arc;
use uplc::builtins::DefaultFunction;
use crate::{
ast::{BinOp, UnOp},
ast::{BinOp, Curve, UnOp},
tipo::{Type, ValueConstructor},
};
use indexmap::IndexSet;
use std::rc::Rc;
use uplc::builtins::DefaultFunction;
use super::scope::Scope;
#[derive(Debug, Clone, PartialEq, Copy)]
pub enum ExpectLevel {
Full,
Items,
None,
}
impl From<bool> for ExpectLevel {
fn from(value: bool) -> Self {
if value {
ExpectLevel::Full
} else {
ExpectLevel::None
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum FunctionVariants {
Standard(Vec<String>),
Recursive {
params: Vec<String>,
recursive_nonstatic_params: Vec<String>,
},
Cyclic(Vec<Vec<String>>),
}
#[derive(Debug, Clone, PartialEq)]
pub enum Air {
// Primitives
Int {
scope: Scope,
value: String,
},
String {
scope: Scope,
value: String,
},
ByteArray {
scope: Scope,
bytes: Vec<u8>,
},
CurvePoint {
point: Curve,
},
Bool {
scope: Scope,
value: bool,
},
List {
scope: Scope,
count: usize,
tipo: Arc<Type>,
tipo: Rc<Type>,
tail: bool,
},
Tuple {
scope: Scope,
tipo: Arc<Type>,
tipo: Rc<Type>,
count: usize,
},
Void {
scope: Scope,
Pair {
tipo: Rc<Type>,
},
Void,
Var {
scope: Scope,
constructor: ValueConstructor,
name: String,
variant_name: String,
},
// Functions
Call {
scope: Scope,
count: usize,
tipo: Arc<Type>,
tipo: Rc<Type>,
},
DefineFunc {
scope: Scope,
func_name: String,
module_name: String,
params: Vec<String>,
recursive: bool,
variant_name: String,
variant: FunctionVariants,
},
Fn {
scope: Scope,
params: Vec<String>,
allow_inline: bool,
},
Builtin {
scope: Scope,
count: usize,
func: DefaultFunction,
tipo: Arc<Type>,
tipo: Rc<Type>,
},
// Operators
BinOp {
scope: Scope,
name: BinOp,
tipo: Arc<Type>,
tipo: Rc<Type>,
argument_tipo: Rc<Type>,
},
UnOp {
scope: Scope,
op: UnOp,
},
// Assignment
Let {
scope: Scope,
name: String,
},
UnWrapData {
scope: Scope,
tipo: Arc<Type>,
SoftCastLet {
name: String,
tipo: Rc<Type>,
},
WrapData {
scope: Scope,
tipo: Arc<Type>,
CastFromData {
tipo: Rc<Type>,
full_cast: bool,
},
AssertConstr {
scope: Scope,
constr_index: usize,
CastToData {
tipo: Rc<Type>,
},
AssertBool {
scope: Scope,
is_true: bool,
},
// When
When {
scope: Scope,
tipo: Arc<Type>,
tipo: Rc<Type>,
subject_name: String,
subject_tipo: Rc<Type>,
},
Clause {
scope: Scope,
tipo: Arc<Type>,
subject_tipo: Rc<Type>,
subject_name: String,
complex_clause: bool,
},
ListClause {
scope: Scope,
tipo: Arc<Type>,
subject_tipo: Rc<Type>,
tail_name: String,
next_tail_name: Option<String>,
complex_clause: bool,
},
WrapClause {
scope: Scope,
next_tail_name: Option<(String, String)>,
},
WrapClause,
TupleClause {
scope: Scope,
tipo: Arc<Type>,
subject_tipo: Rc<Type>,
indices: IndexSet<(usize, String)>,
predefined_indices: IndexSet<(usize, String)>,
subject_name: String,
count: usize,
complex_clause: bool,
},
PairClause {
subject_tipo: Rc<Type>,
subject_name: String,
fst_name: Option<String>,
snd_name: Option<String>,
complex_clause: bool,
},
ClauseGuard {
scope: Scope,
subject_name: String,
tipo: Arc<Type>,
subject_tipo: Rc<Type>,
},
ListClauseGuard {
scope: Scope,
tipo: Arc<Type>,
subject_tipo: Rc<Type>,
tail_name: String,
next_tail_name: Option<String>,
inverse: bool,
},
Finally {
scope: Scope,
TupleGuard {
subject_tipo: Rc<Type>,
indices: IndexSet<(usize, String)>,
subject_name: String,
},
PairGuard {
subject_tipo: Rc<Type>,
subject_name: String,
fst_name: Option<String>,
snd_name: Option<String>,
},
Finally,
// If
If {
scope: Scope,
tipo: Arc<Type>,
tipo: Rc<Type>,
},
// Record Creation
Record {
scope: Scope,
Constr {
tag: usize,
tipo: Arc<Type>,
tipo: Rc<Type>,
count: usize,
},
RecordUpdate {
scope: Scope,
highest_index: usize,
indices: Vec<(usize, Arc<Type>)>,
tipo: Arc<Type>,
indices: Vec<(usize, Rc<Type>)>,
tipo: Rc<Type>,
},
// Field Access
RecordAccess {
scope: Scope,
record_index: u64,
tipo: Arc<Type>,
},
FieldsExpose {
scope: Scope,
indices: Vec<(usize, String, Arc<Type>)>,
check_last_item: bool,
indices: Vec<(usize, String, Rc<Type>)>,
is_expect: bool,
},
// ListAccess
ListAccessor {
scope: Scope,
tipo: Arc<Type>,
tipo: Rc<Type>,
names: Vec<String>,
tail: bool,
check_last_item: bool,
},
ListExpose {
scope: Scope,
tipo: Arc<Type>,
tail_head_names: Vec<(String, String)>,
tail: Option<(String, String)>,
expect_level: ExpectLevel,
},
// Tuple Access
TupleAccessor {
scope: Scope,
names: Vec<String>,
tipo: Arc<Type>,
check_last_item: bool,
tipo: Rc<Type>,
is_expect: bool,
},
TupleIndex {
scope: Scope,
tipo: Arc<Type>,
tuple_index: usize,
// Pair Access
PairAccessor {
fst: Option<String>,
snd: Option<String>,
tipo: Rc<Type>,
is_expect: bool,
},
ExtractField {
tipo: Rc<Type>,
},
// Misc.
ErrorTerm {
scope: Scope,
tipo: Arc<Type>,
tipo: Rc<Type>,
validator: bool,
},
Trace {
scope: Scope,
tipo: Arc<Type>,
},
NoOp {
scope: Scope,
},
FieldsEmpty {
scope: Scope,
},
ListEmpty {
scope: Scope,
tipo: Rc<Type>,
},
}
impl Air {
pub fn scope(&self) -> Scope {
match self {
Air::Int { scope, .. }
| Air::String { scope, .. }
| Air::ByteArray { scope, .. }
| Air::Bool { scope, .. }
| Air::List { scope, .. }
| Air::Tuple { scope, .. }
| Air::Void { scope }
| Air::Var { scope, .. }
| Air::Call { scope, .. }
| Air::DefineFunc { scope, .. }
| Air::Fn { scope, .. }
| Air::Builtin { scope, .. }
| Air::BinOp { scope, .. }
| Air::UnOp { scope, .. }
| Air::Let { scope, .. }
| Air::UnWrapData { scope, .. }
| Air::WrapData { scope, .. }
| Air::AssertConstr { scope, .. }
| Air::AssertBool { scope, .. }
| Air::When { scope, .. }
| Air::Clause { scope, .. }
| Air::ListClause { scope, .. }
| Air::WrapClause { scope }
| Air::TupleClause { scope, .. }
| Air::ClauseGuard { scope, .. }
| Air::ListClauseGuard { scope, .. }
| Air::Finally { scope }
| Air::If { scope, .. }
| Air::Record { scope, .. }
| Air::RecordUpdate { scope, .. }
| Air::RecordAccess { scope, .. }
| Air::FieldsExpose { scope, .. }
| Air::FieldsEmpty { scope }
| Air::ListEmpty { scope }
| Air::ListAccessor { scope, .. }
| Air::ListExpose { scope, .. }
| Air::TupleAccessor { scope, .. }
| Air::TupleIndex { scope, .. }
| Air::ErrorTerm { scope, .. }
| Air::Trace { scope, .. }
| Air::NoOp { scope, .. } => scope.clone(),
}
}
pub fn scope_mut(&mut self) -> &mut Scope {
match self {
Air::Int { scope, .. }
| Air::String { scope, .. }
| Air::ByteArray { scope, .. }
| Air::Bool { scope, .. }
| Air::List { scope, .. }
| Air::Tuple { scope, .. }
| Air::Void { scope }
| Air::Var { scope, .. }
| Air::Call { scope, .. }
| Air::DefineFunc { scope, .. }
| Air::Fn { scope, .. }
| Air::Builtin { scope, .. }
| Air::BinOp { scope, .. }
| Air::UnOp { scope, .. }
| Air::Let { scope, .. }
| Air::UnWrapData { scope, .. }
| Air::WrapData { scope, .. }
| Air::AssertConstr { scope, .. }
| Air::AssertBool { scope, .. }
| Air::When { scope, .. }
| Air::Clause { scope, .. }
| Air::ListClause { scope, .. }
| Air::WrapClause { scope }
| Air::TupleClause { scope, .. }
| Air::ClauseGuard { scope, .. }
| Air::ListClauseGuard { scope, .. }
| Air::Finally { scope }
| Air::If { scope, .. }
| Air::Record { scope, .. }
| Air::RecordUpdate { scope, .. }
| Air::RecordAccess { scope, .. }
| Air::FieldsExpose { scope, .. }
| Air::FieldsEmpty { scope }
| Air::ListEmpty { scope }
| Air::ListAccessor { scope, .. }
| Air::ListExpose { scope, .. }
| Air::TupleAccessor { scope, .. }
| Air::TupleIndex { scope, .. }
| Air::ErrorTerm { scope, .. }
| Air::Trace { scope, .. }
| Air::NoOp { scope, .. } => scope,
}
}
pub fn tipo(&self) -> Option<Arc<Type>> {
match self {
Air::Int { .. } => Some(
Type::App {
public: true,
module: String::new(),
name: "Int".to_string(),
args: vec![],
}
.into(),
),
Air::String { .. } => Some(
Type::App {
public: true,
module: String::new(),
name: "String".to_string(),
args: vec![],
}
.into(),
),
Air::ByteArray { .. } => Some(
Type::App {
public: true,
module: String::new(),
name: "ByteArray".to_string(),
args: vec![],
}
.into(),
),
Air::Bool { .. } => Some(
Type::App {
public: true,
module: String::new(),
name: "Bool".to_string(),
args: vec![],
}
.into(),
),
Air::Void { .. } => Some(
Type::App {
public: true,
module: String::new(),
name: "Void".to_string(),
args: vec![],
}
.into(),
),
Air::WrapData { .. } => Some(
Type::App {
public: true,
module: String::new(),
name: "Data".to_string(),
args: vec![],
}
.into(),
),
Air::Var { constructor, .. } => Some(constructor.tipo.clone()),
Air::List { tipo, .. }
| Air::Tuple { tipo, .. }
| Air::Call { tipo, .. }
| Air::Builtin { tipo, .. }
| Air::BinOp { tipo, .. }
| Air::UnWrapData { tipo, .. }
| Air::When { tipo, .. }
| Air::Clause { tipo, .. }
| Air::ListClause { tipo, .. }
| Air::TupleClause { tipo, .. }
| Air::ClauseGuard { tipo, .. }
| Air::If { tipo, .. }
| Air::ListClauseGuard { tipo, .. }
| Air::Record { tipo, .. }
| Air::RecordUpdate { tipo, .. }
| Air::RecordAccess { tipo, .. }
| Air::ListAccessor { tipo, .. }
| Air::ListExpose { tipo, .. }
| Air::TupleAccessor { tipo, .. }
| Air::TupleIndex { tipo, .. }
| Air::ErrorTerm { tipo, .. }
| Air::Trace { tipo, .. } => Some(tipo.clone()),
Air::DefineFunc { .. }
| Air::Fn { .. }
| Air::Let { .. }
| Air::WrapClause { .. }
| Air::AssertConstr { .. }
| Air::AssertBool { .. }
| Air::Finally { .. }
| Air::FieldsExpose { .. }
| Air::FieldsEmpty { .. }
| Air::ListEmpty { .. }
| Air::NoOp { .. } => None,
Air::UnOp { op, .. } => match op {
UnOp::Not => Some(
Type::App {
public: true,
module: String::new(),
name: "Bool".to_string(),
args: vec![],
}
.into(),
),
UnOp::Negate => Some(
Type::App {
public: true,
module: String::new(),
name: "Int".to_string(),
args: vec![],
}
.into(),
),
},
}
}
NoOp,
FieldsEmpty,
ListEmpty,
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,57 @@
use std::collections::HashMap;
use vec1::{vec1, Vec1};
#[derive(Clone)]
pub struct AirInterner {
identifiers: HashMap<String, Vec1<usize>>,
current: usize,
}
impl Default for AirInterner {
fn default() -> Self {
Self::new()
}
}
/// Interner that uses previous uniques to prevent future unique collisions
/// when performing optimizations
impl AirInterner {
pub fn new() -> Self {
Self {
identifiers: HashMap::new(),
current: 0,
}
}
pub fn intern(&mut self, text: String) {
if let Some(u) = self.identifiers.get_mut(&text) {
u.push(self.current);
self.current += 1;
} else {
self.identifiers.insert(text, vec1!(self.current));
self.current += 1;
}
}
pub fn pop_text(&mut self, text: String) {
if let Some(mut u) = self.identifiers.remove(&text) {
if u.len() != 1 {
u.pop().unwrap();
self.identifiers.insert(text, u);
}
} else {
unreachable!("Looking up a missing text: {}", text);
}
}
pub fn lookup_interned(&self, text: &String) -> String {
if let Some(u) = self.identifiers.get(text) {
format!("{}_id_{}", text, *u.last())
} else {
unreachable!("Looking up a missing text: {}", text);
}
}
}

View File

@ -1,147 +0,0 @@
#[derive(Debug, Clone, Default, Eq, PartialEq)]
pub struct Scope(pub(self) Vec<u64>);
impl From<Vec<u64>> for Scope {
fn from(value: Vec<u64>) -> Self {
Self(value)
}
}
impl Scope {
pub fn push(&mut self, value: u64) {
self.0.push(value);
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
/// Find the common ancestor with the replacement,
/// remove it from `self`, and then prepend the
/// `replacement` to `self`.
pub fn replace(&mut self, mut replacement: Scope) {
let common = self.common_ancestor(&replacement);
// we know that common will always be in the front of the
// scope Vec so we can always drain `0..common.len()`.
self.0.drain(0..common.0.len());
replacement.0.extend(self.0.iter());
self.0 = replacement.0;
}
pub fn common_ancestor(&self, other: &Self) -> Scope {
let longest_length = self.0.len().max(other.0.len());
if *self.0 == *other.0 {
return self.clone();
}
for index in 0..longest_length {
if self.0.get(index).is_none() {
return self.clone();
} else if other.0.get(index).is_none() {
return other.clone();
} else if self.0[index] != other.0[index] {
return Scope(self.0[0..index].to_vec());
}
}
Scope::default()
}
}
#[cfg(test)]
mod test {
use pretty_assertions::assert_eq;
use super::Scope;
#[test]
fn common_ancestor_equal_vecs() {
let ancestor = Scope(vec![1, 2, 3, 4, 5, 6]);
let descendant = Scope(vec![1, 2, 3, 4, 5, 6]);
let result = ancestor.common_ancestor(&descendant);
assert_eq!(result, Scope(vec![1, 2, 3, 4, 5, 6]))
}
#[test]
fn common_ancestor_equal_ancestor() {
let ancestor = Scope(vec![1, 2, 3, 4]);
let descendant = Scope(vec![1, 2, 3, 4, 5, 6]);
let result = ancestor.common_ancestor(&descendant);
assert_eq!(result, Scope(vec![1, 2, 3, 4]));
}
#[test]
fn common_ancestor_not_subset() {
let ancestor = Scope(vec![1, 2, 3, 4, 5]);
let descendant = Scope(vec![1, 2, 3, 7, 8]);
let result = ancestor.common_ancestor(&descendant);
assert_eq!(result, Scope(vec![1, 2, 3]));
}
#[test]
fn common_ancestor_not_found() {
let ancestor = Scope(vec![1, 2, 3, 4, 5, 6]);
let descendant = Scope(vec![4, 5, 6]);
let result = ancestor.common_ancestor(&descendant);
assert_eq!(result, Scope::default());
}
#[test]
fn common_ancestor_no_shared_values() {
let ancestor = Scope(vec![1, 2, 3]);
let descendant = Scope(vec![4, 5, 6]);
let result = ancestor.common_ancestor(&descendant);
assert_eq!(result, Scope::default());
}
#[test]
fn replace_same_value() {
let mut value = Scope(vec![1, 2, 3, 4, 5, 6]);
let replacement = Scope(vec![1, 2, 3, 4, 5, 6]);
value.replace(replacement);
assert_eq!(value, Scope(vec![1, 2, 3, 4, 5, 6]));
}
#[test]
fn replace_with_pattern() {
let mut value = Scope(vec![1, 2, 3, 4, 5]);
let replacement = Scope(vec![1, 2, 8, 9]);
value.replace(replacement);
assert_eq!(value, Scope(vec![1, 2, 8, 9, 3, 4, 5]));
}
#[test]
fn replace_with_no_pattern() {
let mut value = Scope(vec![1, 2, 3, 4, 5]);
let replacement = Scope(vec![8, 9]);
value.replace(replacement);
assert_eq!(value, Scope(vec![8, 9, 1, 2, 3, 4, 5]));
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,316 @@
use std::{fmt::Display, rc::Rc};
use itertools::Itertools;
use uplc::{builder::CONSTR_FIELDS_EXPOSER, builtins::DefaultFunction};
use crate::expr::Type;
use super::{
builder::CodeGenSpecialFuncs,
decision_tree::{get_tipo_by_path, CaseTest, Path},
tree::AirTree,
};
#[derive(Clone, Debug)]
pub enum Builtin {
HeadList(Rc<Type>),
ExtractField(Rc<Type>),
TailList,
UnConstrFields,
FstPair(Rc<Type>),
SndPair(Rc<Type>),
}
impl PartialEq for Builtin {
fn eq(&self, other: &Self) -> bool {
matches!(
(self, other),
(Builtin::HeadList(_), Builtin::HeadList(_))
| (Builtin::ExtractField(_), Builtin::ExtractField(_))
| (Builtin::TailList, Builtin::TailList)
| (Builtin::UnConstrFields, Builtin::UnConstrFields)
| (Builtin::FstPair(_), Builtin::FstPair(_))
| (Builtin::SndPair(_), Builtin::SndPair(_))
)
}
}
impl Eq for Builtin {}
impl Builtin {
fn produce_air(self, special_funcs: &mut CodeGenSpecialFuncs, arg: AirTree) -> AirTree {
match self {
Builtin::HeadList(t) => AirTree::builtin(DefaultFunction::HeadList, t, vec![arg]),
Builtin::ExtractField(t) => AirTree::extract_field(t, arg),
Builtin::TailList => AirTree::builtin(
DefaultFunction::TailList,
Type::list(Type::data()),
vec![arg],
),
Builtin::UnConstrFields => AirTree::call(
special_funcs.use_function_tree(CONSTR_FIELDS_EXPOSER.to_string()),
Type::list(Type::data()),
vec![arg],
),
Builtin::FstPair(t) => AirTree::builtin(DefaultFunction::FstPair, t, vec![arg]),
Builtin::SndPair(t) => AirTree::builtin(DefaultFunction::SndPair, t, vec![arg]),
}
}
pub fn tipo(&self) -> Rc<Type> {
match self {
Builtin::HeadList(t) => t.clone(),
Builtin::ExtractField(t) => t.clone(),
Builtin::TailList => Type::list(Type::data()),
Builtin::UnConstrFields => Type::list(Type::data()),
Builtin::FstPair(t) => t.clone(),
Builtin::SndPair(t) => t.clone(),
}
}
}
impl Display for Builtin {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Builtin::HeadList(_) => write!(f, "head"),
Builtin::ExtractField(_) => write!(f, "extractfield"),
Builtin::TailList => write!(f, "tail"),
Builtin::UnConstrFields => write!(f, "unconstrfields"),
Builtin::FstPair(_) => write!(f, "fst"),
Builtin::SndPair(_) => write!(f, "snd"),
}
}
}
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct Builtins {
pub vec: Vec<Builtin>,
}
impl Default for Builtins {
fn default() -> Self {
Self::new()
}
}
impl Builtins {
pub fn new() -> Self {
Builtins { vec: vec![] }
}
pub fn new_from_list_case(case: CaseTest) -> Self {
Self {
vec: match case {
CaseTest::List(i) | CaseTest::ListWithTail(i) => {
(0..i).fold(vec![], |mut acc, _index| {
acc.push(Builtin::TailList);
acc
})
}
_ => unreachable!(),
},
}
}
pub fn new_from_path(subject_tipo: Rc<Type>, path: Vec<Path>) -> Self {
Self {
vec: path
.into_iter()
.fold((vec![], vec![]), |(mut builtins, mut rebuilt_path), i| {
rebuilt_path.push(i.clone());
let is_list = matches!(i, Path::List(_));
match i {
Path::Pair(i) => {
if i == 0 {
builtins.push(Builtin::FstPair(get_tipo_by_path(
subject_tipo.clone(),
&rebuilt_path,
)));
} else if i == 1 {
builtins.push(Builtin::SndPair(get_tipo_by_path(
subject_tipo.clone(),
&rebuilt_path,
)));
} else {
unreachable!()
}
(builtins, rebuilt_path)
}
Path::List(i) | Path::Tuple(i) => {
for _ in 0..i {
builtins.push(Builtin::TailList);
}
if is_list {
builtins.push(Builtin::HeadList(get_tipo_by_path(
subject_tipo.clone(),
&rebuilt_path,
)));
} else {
builtins.push(Builtin::ExtractField(get_tipo_by_path(
subject_tipo.clone(),
&rebuilt_path,
)));
}
(builtins, rebuilt_path)
}
Path::Constr(_rc, i) => {
builtins.push(Builtin::UnConstrFields);
for _ in 0..i {
builtins.push(Builtin::TailList);
}
builtins.push(Builtin::ExtractField(get_tipo_by_path(
subject_tipo.clone(),
&rebuilt_path,
)));
(builtins, rebuilt_path)
}
Path::ListTail(i) => {
for _ in 0..i {
builtins.push(Builtin::TailList);
}
(builtins, rebuilt_path)
}
Path::OpaqueConstr(_) => (builtins, rebuilt_path),
}
})
.0,
}
}
pub fn pop(&mut self) {
self.vec.pop();
}
pub fn len(&self) -> usize {
self.vec.len()
}
pub fn is_empty(&self) -> bool {
self.vec.is_empty()
}
pub fn merge(mut self, other: Self) -> Self {
self.vec.extend(other.vec);
self
}
pub fn produce_air(
self,
special_funcs: &mut CodeGenSpecialFuncs,
prev_name: String,
subject_tipo: Rc<Type>,
then: AirTree,
) -> AirTree {
let (_, _, name_builtins) = self.vec.into_iter().fold(
(prev_name, subject_tipo, vec![]),
|(prev_name, prev_tipo, mut acc), item| {
let next_name = format!("{}_{}", prev_name, item);
let next_tipo = item.tipo();
acc.push((prev_name, prev_tipo, next_name.clone(), item));
(next_name, next_tipo, acc)
},
);
name_builtins
.into_iter()
.rfold(then, |then, (prev_name, prev_tipo, next_name, builtin)| {
AirTree::let_assignment(
next_name,
builtin.produce_air(special_funcs, AirTree::local_var(prev_name, prev_tipo)),
then,
)
})
}
}
impl Display for Builtins {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.vec.iter().map(|i| i.to_string()).join("_"))
}
}
#[derive(Clone)]
pub struct TreeSet {
children: Vec<TreeNode>,
}
#[derive(Clone)]
pub struct TreeNode {
node: Builtin,
children: Vec<TreeNode>,
}
impl TreeNode {
fn diff_union_builtins(&mut self, builtins: Builtins) -> Builtins {
if let Some((first, rest)) = builtins.vec.split_first() {
if let Some(item) = self.children.iter_mut().find(|item| first == &item.node) {
item.diff_union_builtins(Builtins { vec: rest.to_vec() })
} else {
self.children
.extend(TreeSet::new_from_builtins(builtins.clone()).children);
builtins
}
} else {
builtins
}
}
}
impl Default for TreeSet {
fn default() -> Self {
Self::new()
}
}
impl TreeSet {
pub fn new() -> Self {
TreeSet { children: vec![] }
}
pub fn new_from_builtins(builtins: Builtins) -> Self {
TreeSet {
children: builtins
.vec
.into_iter()
.map(|item| TreeNode {
node: item,
children: vec![],
})
.rev()
.reduce(|prev, mut current| {
current.children.push(prev);
current
})
.into_iter()
.collect_vec(),
}
}
pub fn diff_union_builtins(&mut self, builtins: Builtins) -> Builtins {
if let Some((first, rest)) = builtins.vec.split_first() {
if let Some(item) = self.children.iter_mut().find(|item| first == &item.node) {
item.diff_union_builtins(Builtins { vec: rest.to_vec() })
} else {
self.children
.extend(TreeSet::new_from_builtins(builtins.clone()).children);
builtins
}
} else {
builtins
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -5,13 +5,19 @@ use std::sync::{
pub mod ast;
pub mod builtins;
pub mod error;
pub mod expr;
pub mod format;
pub mod gen_uplc;
pub mod levenshtein;
pub mod line_numbers;
pub mod parser;
pub mod plutus_version;
pub mod pretty;
pub mod test_framework;
pub mod tipo;
pub mod utils;
pub mod version;
#[derive(Debug, Default, Clone)]
pub struct IdGenerator {
@ -28,5 +34,37 @@ impl IdGenerator {
}
}
#[macro_export]
macro_rules! aiken_fn {
($module_types:expr, $id_gen:expr, $src:expr) => {{
let (untyped_module, _) = $crate::parser::module($src, $crate::ast::ModuleKind::Lib)
.expect("failed to parse module.");
let module_name = "";
let mut warnings = vec![];
let typed_module = untyped_module
.infer(
$id_gen,
$crate::ast::ModuleKind::Lib,
module_name,
$module_types,
$crate::ast::Tracing::silent(),
&mut warnings,
None,
)
.unwrap();
if let Some($crate::ast::Definition::Fn(typed_fn)) =
typed_module.definitions.into_iter().last()
{
typed_fn
} else {
unreachable!()
}
}};
}
#[cfg(test)]
mod tests;

View File

@ -0,0 +1,126 @@
use std::fmt::{self, Display};
#[derive(Debug, PartialEq, Eq, Clone, serde::Serialize, serde::Deserialize)]
pub struct LineNumbers {
line_starts: Vec<usize>,
length: usize,
last: Option<usize>,
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub struct LineColumn {
pub line: usize,
pub column: usize,
}
impl Display for LineColumn {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
f.write_str(&format!("L{};{}", self.line, self.column))
}
}
impl LineNumbers {
pub fn new(src: &str) -> Self {
let line_starts: Vec<usize> = std::iter::once(0)
.chain(src.match_indices('\n').map(|(i, _)| i + 1))
.collect();
let length = src.len();
Self {
length,
last: line_starts.last().cloned(),
line_starts: if length > 0 { line_starts } else { Vec::new() },
}
}
/// Get the line number for a byte index
pub fn line_number(&self, byte_index: usize) -> Option<usize> {
self.line_starts
.binary_search(&byte_index)
.map(|l| Some(l + 1))
.unwrap_or_else(|next_index| {
if Some(next_index) >= self.last {
None
} else {
Some(next_index)
}
})
}
pub fn line_and_column_number(&self, byte_index: usize) -> Option<LineColumn> {
let line = self.line_number(byte_index)?;
let column = byte_index - self.line_starts.get(line - 1).copied().unwrap_or_default() + 1;
Some(LineColumn { line, column })
}
#[allow(dead_code)]
pub fn byte_index(&self, line: usize, character: usize) -> usize {
match self.line_starts.get(line) {
Some(line_index) => *line_index + character,
None => self.length,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use chumsky::text::Character;
use indoc::indoc;
fn assert_line_column(src: &str, ix: usize, lcol: Option<LineColumn>) {
let lines = LineNumbers::new(src);
println!("{lines:?}");
let byte = src
.as_bytes()
.get(ix)
.map(|b| {
if b.is_ascii() {
format!("{}", b.to_char())
} else {
format!("{b}")
}
})
.unwrap_or_else(|| "OUT-OF-BOUNDS".to_string());
assert_eq!(
lines.line_and_column_number(ix),
lcol,
"\n{src}\n--> at index {ix} ({byte})\n",
);
}
#[test]
fn out_of_range_byte_index() {
let src = indoc! { r#""# };
assert_line_column(src, 42, None);
assert_line_column(src, 0, None);
}
#[test]
fn basic() {
let src = indoc! { r#"
foo
bar
"# };
assert_line_column(src, 0, Some(LineColumn { line: 1, column: 1 }));
assert_line_column(src, 2, Some(LineColumn { line: 1, column: 3 }));
assert_line_column(src, 4, Some(LineColumn { line: 2, column: 1 }));
}
#[test]
fn unicode() {
let src = indoc! { r#"
💩
foo
"# };
assert_line_column(src, 0, Some(LineColumn { line: 1, column: 1 }));
assert_line_column(src, 2, Some(LineColumn { line: 1, column: 3 }));
assert_line_column(src, 5, Some(LineColumn { line: 2, column: 1 }));
}
}

View File

@ -10,15 +10,15 @@ pub mod pattern;
pub mod token;
mod utils;
use crate::{ast, line_numbers::LineNumbers};
pub use annotation::parser as annotation;
pub use definition::parser as definition;
pub use expr::parser as expression;
pub use pattern::parser as pattern;
use crate::ast;
use chumsky::prelude::*;
pub use definition::{import::parser as import, parser as definition};
use error::ParseError;
pub use expr::parser as expression;
use extra::ModuleExtra;
use indexmap::IndexMap;
pub use pattern::parser as pattern;
pub fn module(
src: &str,
@ -28,10 +28,54 @@ pub fn module(
let stream = chumsky::Stream::from_iter(ast::Span::create(tokens.len(), 1), tokens.into_iter());
let definitions = definition().repeated().then_ignore(end()).parse(stream)?;
let definitions = import()
.repeated()
.map(|imports| {
let mut store = IndexMap::new();
for import in imports.into_iter() {
let key = (import.module, import.as_name);
match store.remove(&key) {
None => {
store.insert(key, (import.location, import.unqualified));
}
Some((location, unqualified)) => {
let mut merged_unqualified = Vec::new();
merged_unqualified.extend(unqualified);
merged_unqualified.extend(import.unqualified);
store.insert(key, (location, merged_unqualified));
}
}
}
store
.into_iter()
.map(|((module, as_name), (location, unqualified))| {
ast::Definition::Use(ast::Use {
module,
as_name,
location,
unqualified,
package: (),
})
})
.collect::<Vec<ast::UntypedDefinition>>()
})
.then(definition().repeated())
.map(|(imports, others)| {
let mut defs = Vec::new();
defs.extend(imports);
defs.extend(others);
defs
})
.then_ignore(end())
.parse(stream)?;
let lines = LineNumbers::new(src);
let module = ast::UntypedModule {
kind,
lines,
definitions,
docs: vec![],
name: "".to_string(),
@ -45,6 +89,16 @@ pub fn module(
mod tests {
use crate::assert_module;
#[test]
fn merge_imports() {
assert_module!(
r#"
use aiken/list.{bar, foo}
use aiken/list.{baz}
"#
);
}
#[test]
fn windows_newline() {
assert_module!("use aiken/list\r\n");

View File

@ -1,8 +1,9 @@
use chumsky::prelude::*;
use crate::ast;
use super::{error::ParseError, token::Token};
use crate::{
ast::{self, well_known},
builtins::PRELUDE,
};
use chumsky::prelude::*;
pub fn parser() -> impl Parser<Token, ast::Annotation, Error = ParseError> {
recursive(|expression| {
@ -14,6 +15,31 @@ pub fn parser() -> impl Parser<Token, ast::Annotation, Error = ParseError> {
name,
}
}),
// Pair
select! {Token::Name { name } if name == PRELUDE => name}
.then_ignore(just(Token::Dot))
.or_not()
.then_ignore(select! {Token::UpName { name } if name == well_known::PAIR => name})
.ignore_then(
expression
.clone()
.separated_by(just(Token::Comma))
.exactly(2)
.delimited_by(just(Token::Less), just(Token::Greater)),
)
.map_with_span(|elems: Vec<ast::Annotation>, span| ast::Annotation::Pair {
location: span,
fst: elems
.first()
.expect("Pair should have exactly 2 elements")
.to_owned()
.into(),
snd: elems
.last()
.expect("Pair should have exactly 2 elements")
.to_owned()
.into(),
}),
// Tuple
expression
.clone()

View File

@ -1,16 +1,16 @@
use chumsky::prelude::*;
use super::Chain;
use crate::{
expr::UntypedExpr,
parser::{token::Token, ParseError},
};
use chumsky::prelude::*;
pub(crate) fn parser() -> impl Parser<Token, Chain, Error = ParseError> {
just(Token::Dot)
.ignore_then(select! {
Token::Name { name } => name,
})
.ignore_then(choice((
select! { Token::Else => "else".to_string() },
select! { Token::Name { name } => name, },
)))
.map_with_span(Chain::FieldAccess)
}
@ -28,3 +28,18 @@ pub(crate) fn constructor() -> impl Parser<Token, UntypedExpr, Error = ParseErro
}),
})
}
#[cfg(test)]
mod tests {
use crate::assert_expr;
#[test]
fn field_access_else_1() {
assert_expr!("foo.else");
}
#[test]
fn field_access_else_2() {
assert_expr!("foo.bar.else");
}
}

View File

@ -0,0 +1,12 @@
---
source: crates/aiken-lang/src/parser/chain/field_access.rs
description: "Code:\n\nfoo.else"
---
FieldAccess {
location: 0..8,
label: "else",
container: Var {
location: 0..3,
name: "foo",
},
}

View File

@ -0,0 +1,16 @@
---
source: crates/aiken-lang/src/parser/chain/field_access.rs
description: "Code:\n\nfoo.bar.else"
---
FieldAccess {
location: 0..12,
label: "else",
container: FieldAccess {
location: 0..7,
label: "bar",
container: Var {
location: 0..3,
name: "foo",
},
},
}

View File

@ -1,9 +1,8 @@
use chumsky::prelude::*;
use crate::{
ast,
parser::{annotation, error::ParseError, literal, token::Token, utils},
parser::{annotation, error::ParseError, expr::pure_expression, token::Token, utils},
};
use chumsky::prelude::*;
pub fn parser() -> impl Parser<Token, ast::UntypedDefinition, Error = ParseError> {
utils::optional_flag(Token::Pub)
@ -15,7 +14,11 @@ pub fn parser() -> impl Parser<Token, ast::UntypedDefinition, Error = ParseError
.or_not(),
)
.then_ignore(just(Token::Equal))
.then(value())
.then(recursive(|sequence| {
recursive(|expression| pure_expression(sequence.clone(), expression))
.then(sequence.repeated())
.foldl(|current, next| current.append_in_sequence(next))
}))
.map_with_span(|(((public, name), annotation), value), span| {
ast::UntypedDefinition::ModuleConstant(ast::ModuleConstant {
doc: None,
@ -23,40 +26,32 @@ pub fn parser() -> impl Parser<Token, ast::UntypedDefinition, Error = ParseError
public,
name,
annotation,
value: Box::new(value),
tipo: (),
value,
})
})
}
pub fn value() -> impl Parser<Token, ast::Constant, Error = ParseError> {
let constant_string_parser =
select! {Token::String {value} => value}.map_with_span(|value, span| {
ast::Constant::String {
location: span,
value,
}
});
#[cfg(test)]
mod tests {
use crate::assert_definition;
let constant_int_parser =
literal::int().map_with_span(|(value, base), location| ast::Constant::Int {
location,
value,
base,
});
let constant_bytearray_parser =
literal::bytearray(
|bytes, preferred_format, location| ast::Constant::ByteArray {
location,
bytes,
preferred_format,
},
#[test]
fn g1_element_constant() {
assert_definition!(
r#"
pub const point =
#<Bls12_381, G1>"950dfd33da2682260c76038dfb8bad6e84ae9d599a3c151815945ac1e6ef6b1027cd917f3907479d20d636ce437a41f5"
"#
);
}
choice((
constant_string_parser,
constant_int_parser,
constant_bytearray_parser,
))
#[test]
fn g2_element_constant() {
assert_definition!(
r#"
pub const point =
#<Bls12_381, G2>"b0629fa1158c2d23a10413fe91d381a84d25e31d041cd0377d25828498fd02011b35893938ced97535395e4815201e67108bcd4665e0db25d602d76fa791fab706c54abf5e1a9e44b4ac1e6badf3d2ac0328f5e30be341677c8bac5dda7682f1"
"#
);
}
}

View File

@ -1,9 +1,8 @@
use chumsky::prelude::*;
use crate::{
ast,
parser::{annotation, error::ParseError, token::Token, utils},
};
use chumsky::prelude::*;
pub fn parser() -> impl Parser<Token, ast::UntypedDefinition, Error = ParseError> {
let unlabeled_constructor_type_args = annotation()
@ -54,16 +53,26 @@ pub fn parser() -> impl Parser<Token, ast::UntypedDefinition, Error = ParseError
|(((public, opaque), (name, parameters)), constructors), span| {
ast::UntypedDefinition::DataType(ast::DataType {
location: span,
constructors: constructors
.into_iter()
.map(|mut constructor| {
if constructor.sugar {
constructor.name = name.clone();
}
constructors: if constructors.is_empty() {
vec![ast::RecordConstructor {
location: span,
arguments: vec![],
doc: None,
name: name.clone(),
sugar: true,
}]
} else {
constructors
.into_iter()
.map(|mut constructor| {
if constructor.sugar {
constructor.name.clone_from(&name);
}
constructor
})
.collect(),
constructor
})
.collect()
},
doc: None,
name,
opaque,
@ -119,4 +128,25 @@ mod tests {
"#
);
}
#[test]
fn record_sugar() {
assert_definition!(
r#"
pub type Foo {
wow: Int,
}
"#
);
}
#[test]
fn empty_record_sugar() {
assert_definition!(
r#"
pub type Foo {
}
"#
);
}
}

View File

@ -1,10 +1,9 @@
use chumsky::prelude::*;
use crate::{
ast,
expr::UntypedExpr,
parser::{annotation, error::ParseError, expr, token::Token, utils},
parser::{annotation, error::ParseError, expr, pattern, token::Token, utils},
};
use chumsky::prelude::*;
pub fn parser() -> impl Parser<Token, ast::UntypedDefinition, Error = ParseError> {
utils::optional_flag(Token::Pub)
@ -41,7 +40,7 @@ pub fn parser() -> impl Parser<Token, ast::UntypedDefinition, Error = ParseError
public,
return_annotation,
return_type: (),
can_error: true,
on_test_failure: ast::OnTestFailure::FailImmediately,
})
},
)
@ -51,39 +50,45 @@ pub fn param(is_validator_param: bool) -> impl Parser<Token, ast::UntypedArg, Er
choice((
select! {Token::Name {name} => name}
.then(select! {Token::DiscardName {name} => name})
.map_with_span(|(label, name), span| ast::ArgName::Discarded {
label,
name,
location: span,
.map_with_span(|(label, name), span| {
ast::ArgBy::ByName(ast::ArgName::Discarded {
label,
name,
location: span,
})
}),
select! {Token::DiscardName {name} => name}.map_with_span(|name, span| {
ast::ArgName::Discarded {
ast::ArgBy::ByName(ast::ArgName::Discarded {
label: name.clone(),
name,
location: span,
}
})
}),
select! {Token::Name {name} => name}
.then(select! {Token::Name {name} => name})
.map_with_span(move |(label, name), span| ast::ArgName::Named {
label,
.map_with_span(|(label, name), span| {
ast::ArgBy::ByName(ast::ArgName::Named {
label,
name,
location: span,
})
}),
select! {Token::Name {name} => name}.map_with_span(|name, span| {
ast::ArgBy::ByName(ast::ArgName::Named {
label: name.clone(),
name,
location: span,
is_validator_param,
}),
select! {Token::Name {name} => name}.map_with_span(move |name, span| ast::ArgName::Named {
label: name.clone(),
name,
location: span,
is_validator_param,
})
}),
pattern().map(ast::ArgBy::ByPattern),
))
.then(just(Token::Colon).ignore_then(annotation()).or_not())
.map_with_span(|(arg_name, annotation), span| ast::Arg {
.map_with_span(move |(by, annotation), span| ast::UntypedArg {
location: span,
annotation,
tipo: (),
arg_name,
doc: None,
is_validator_param,
by,
})
}
@ -108,4 +113,47 @@ mod tests {
"#
);
}
#[test]
fn function_assignment_only() {
assert_definition!(
r#"
fn run() {
let x = 1 + 1
}
"#
);
}
#[test]
fn function_by_pattern_no_annotation() {
assert_definition!(
r#"
fn foo(Foo { my_field }) {
my_field * 2
}
"#
);
}
#[test]
fn function_by_pattern_with_annotation() {
assert_definition!(
r#"
fn foo(Foo { my_field }: Foo) {
my_field * 2
}
"#
);
}
#[test]
fn function_by_pattern_with_alias() {
assert_definition!(
r#"
fn foo(Foo { my_field, .. } as x) {
my_field * x.my_other_field
}
"#
);
}
}

View File

@ -1,11 +1,10 @@
use chumsky::prelude::*;
use crate::{
ast,
parser::{error::ParseError, token::Token},
};
use chumsky::prelude::*;
pub fn parser() -> impl Parser<Token, ast::UntypedDefinition, Error = ParseError> {
pub fn parser() -> impl Parser<Token, ast::UntypedUse, Error = ParseError> {
let unqualified_import = choice((
select! {Token::Name { name } => name}.then(
just(Token::As)
@ -22,7 +21,6 @@ pub fn parser() -> impl Parser<Token, ast::UntypedDefinition, Error = ParseError
name,
location: span,
as_name,
layer: Default::default(),
});
let unqualified_imports = just(Token::Dot)
@ -44,30 +42,28 @@ pub fn parser() -> impl Parser<Token, ast::UntypedDefinition, Error = ParseError
.then(as_name);
just(Token::Use).ignore_then(module_path).map_with_span(
|((module, unqualified), as_name), span| {
ast::UntypedDefinition::Use(ast::Use {
module,
as_name,
unqualified: unqualified.unwrap_or_default(),
package: (),
location: span,
})
|((module, unqualified), as_name), span| ast::Use {
module,
as_name,
unqualified: unqualified.unwrap_or_default(),
package: (),
location: span,
},
)
}
#[cfg(test)]
mod tests {
use crate::assert_definition;
use crate::assert_import;
#[test]
fn import_basic() {
assert_definition!("use aiken/list");
assert_import!("use aiken/list");
}
#[test]
fn import_unqualified() {
assert_definition!(
assert_import!(
r#"
use std/address.{Address as A, thing as w}
"#
@ -76,6 +72,6 @@ mod tests {
#[test]
fn import_alias() {
assert_definition!("use aiken/list as foo");
assert_import!("use aiken/list as foo");
}
}

View File

@ -3,25 +3,22 @@ use chumsky::prelude::*;
pub mod constant;
mod data_type;
mod function;
mod import;
pub mod import;
mod test;
mod type_alias;
mod validator;
use super::{error::ParseError, token::Token};
use crate::ast;
pub use constant::parser as constant;
pub use data_type::parser as data_type;
pub use function::parser as function;
pub use import::parser as import;
pub use test::parser as test;
pub use type_alias::parser as type_alias;
pub use validator::parser as validator;
use super::{error::ParseError, token::Token};
use crate::ast;
pub fn parser() -> impl Parser<Token, ast::UntypedDefinition, Error = ParseError> {
choice((
import(),
data_type(),
type_alias(),
validator(),

View File

@ -0,0 +1,60 @@
---
source: crates/aiken-lang/src/parser/definition/test.rs
description: "Code:\n\ntest foo(x via f, y via g) {\n True\n}\n"
---
Test(
Function {
arguments: [
ArgVia {
arg: UntypedArg {
by: ByName(
Named {
name: "x",
label: "x",
location: 9..10,
},
),
location: 9..10,
annotation: None,
doc: None,
is_validator_param: false,
},
via: Var {
location: 15..16,
name: "f",
},
},
ArgVia {
arg: UntypedArg {
by: ByName(
Named {
name: "y",
label: "y",
location: 18..19,
},
),
location: 18..19,
annotation: None,
doc: None,
is_validator_param: false,
},
via: Var {
location: 24..25,
name: "g",
},
},
],
body: Var {
location: 33..37,
name: "True",
},
doc: None,
location: 0..26,
name: "foo",
public: false,
return_annotation: None,
return_type: (),
end_position: 38,
on_test_failure: FailImmediately,
},
)

View File

@ -0,0 +1,45 @@
---
source: crates/aiken-lang/src/parser/definition/test.rs
description: "Code:\n\ntest foo(x via fuzz.any_int) {\n True\n}\n"
---
Test(
Function {
arguments: [
ArgVia {
arg: UntypedArg {
by: ByName(
Named {
name: "x",
label: "x",
location: 9..10,
},
),
location: 9..10,
annotation: None,
doc: None,
is_validator_param: false,
},
via: FieldAccess {
location: 15..27,
label: "any_int",
container: Var {
location: 15..19,
name: "fuzz",
},
},
},
],
body: Var {
location: 35..39,
name: "True",
},
doc: None,
location: 0..28,
name: "foo",
public: false,
return_annotation: None,
return_type: (),
end_position: 40,
on_test_failure: FailImmediately,
},
)

View File

@ -0,0 +1,52 @@
---
source: crates/aiken-lang/src/parser/definition/test.rs
description: "Code:\n\ntest foo(x: Int via foo()) {\n True\n}\n"
---
Test(
Function {
arguments: [
ArgVia {
arg: UntypedArg {
by: ByName(
Named {
name: "x",
label: "x",
location: 9..10,
},
),
location: 9..15,
annotation: Some(
Constructor {
location: 12..15,
module: None,
name: "Int",
arguments: [],
},
),
doc: None,
is_validator_param: false,
},
via: Call {
arguments: [],
fun: Var {
location: 20..23,
name: "foo",
},
location: 20..25,
},
},
],
body: Var {
location: 33..37,
name: "True",
},
doc: None,
location: 0..26,
name: "foo",
public: false,
return_annotation: None,
return_type: (),
end_position: 38,
on_test_failure: FailImmediately,
},
)

View File

@ -0,0 +1,21 @@
---
source: crates/aiken-lang/src/parser/definition/test.rs
description: "Code:\n\ntest foo() {\n True\n}\n"
---
Test(
Function {
arguments: [],
body: Var {
location: 17..21,
name: "True",
},
doc: None,
location: 0..10,
name: "foo",
public: false,
return_annotation: None,
return_type: (),
end_position: 22,
on_test_failure: FailImmediately,
},
)

View File

@ -14,18 +14,25 @@ Test(
location: 45..50,
name: "False",
},
pattern: Constructor {
is_record: false,
location: 38..42,
name: "True",
arguments: [],
module: None,
constructor: (),
with_spread: false,
tipo: (),
patterns: [
AssignmentPattern {
pattern: Constructor {
is_record: false,
location: 38..42,
name: "True",
arguments: [],
module: None,
constructor: (),
spread_location: None,
tipo: (),
},
annotation: None,
location: 38..42,
},
],
kind: Expect {
backpassing: false,
},
kind: Expect,
annotation: None,
},
Var {
location: 54..59,
@ -40,6 +47,6 @@ Test(
return_annotation: None,
return_type: (),
end_position: 60,
can_error: true,
on_test_failure: SucceedEventually,
},
)

View File

@ -1,101 +1,161 @@
---
source: crates/aiken-lang/src/parser/definition/validator.rs
description: "Code:\n\nvalidator {\n fn foo(datum, rdmr, ctx) {\n True\n }\n\n fn bar(rdmr, ctx) {\n True\n }\n}\n"
description: "Code:\n\nvalidator thing {\n spend (datum, rdmr, ctx) {\n True\n }\n\n mint (rdmr, ctx) {\n True\n }\n}\n"
---
Validator(
Validator {
doc: None,
end_position: 90,
fun: Function {
arguments: [
Arg {
arg_name: Named {
name: "datum",
label: "datum",
location: 21..26,
is_validator_param: false,
},
location: 21..26,
annotation: None,
tipo: (),
},
Arg {
arg_name: Named {
name: "rdmr",
label: "rdmr",
location: 28..32,
is_validator_param: false,
},
location: 28..32,
annotation: None,
tipo: (),
},
Arg {
arg_name: Named {
name: "ctx",
label: "ctx",
location: 34..37,
is_validator_param: false,
},
location: 34..37,
annotation: None,
tipo: (),
},
],
body: Var {
location: 45..49,
name: "True",
},
doc: None,
location: 14..38,
name: "foo",
public: false,
return_annotation: None,
return_type: (),
end_position: 52,
can_error: true,
},
other_fun: Some(
end_position: 95,
handlers: [
Function {
arguments: [
Arg {
arg_name: Named {
name: "rdmr",
label: "rdmr",
location: 64..68,
is_validator_param: false,
},
location: 64..68,
UntypedArg {
by: ByName(
Named {
name: "datum",
label: "datum",
location: 27..32,
},
),
location: 27..32,
annotation: None,
tipo: (),
doc: None,
is_validator_param: false,
},
Arg {
arg_name: Named {
name: "ctx",
label: "ctx",
location: 70..73,
is_validator_param: false,
},
location: 70..73,
UntypedArg {
by: ByName(
Named {
name: "rdmr",
label: "rdmr",
location: 34..38,
},
),
location: 34..38,
annotation: None,
tipo: (),
doc: None,
is_validator_param: false,
},
UntypedArg {
by: ByName(
Named {
name: "ctx",
label: "ctx",
location: 40..43,
},
),
location: 40..43,
annotation: None,
doc: None,
is_validator_param: false,
},
],
body: Var {
location: 81..85,
location: 51..55,
name: "True",
},
doc: None,
location: 57..74,
name: "bar",
public: false,
return_annotation: None,
location: 20..44,
name: "spend",
public: true,
return_annotation: Some(
Constructor {
location: 26..44,
module: None,
name: "Bool",
arguments: [],
},
),
return_type: (),
end_position: 88,
can_error: true,
end_position: 58,
on_test_failure: FailImmediately,
},
),
Function {
arguments: [
UntypedArg {
by: ByName(
Named {
name: "rdmr",
label: "rdmr",
location: 69..73,
},
),
location: 69..73,
annotation: None,
doc: None,
is_validator_param: false,
},
UntypedArg {
by: ByName(
Named {
name: "ctx",
label: "ctx",
location: 75..78,
},
),
location: 75..78,
annotation: None,
doc: None,
is_validator_param: false,
},
],
body: Var {
location: 86..90,
name: "True",
},
doc: None,
location: 63..79,
name: "mint",
public: true,
return_annotation: Some(
Constructor {
location: 68..79,
module: None,
name: "Bool",
arguments: [],
},
),
return_type: (),
end_position: 93,
on_test_failure: FailImmediately,
},
],
location: 0..9,
name: "thing",
params: [],
fallback: Function {
arguments: [
UntypedArg {
by: ByName(
Discarded {
name: "_",
label: "_",
location: 0..9,
},
),
location: 0..9,
annotation: None,
doc: None,
is_validator_param: false,
},
],
body: ErrorTerm {
location: 0..9,
},
doc: None,
location: 0..9,
name: "else",
public: true,
return_annotation: Some(
Constructor {
location: 0..9,
module: None,
name: "Bool",
arguments: [],
},
),
return_type: (),
end_position: 8,
on_test_failure: FailImmediately,
},
},
)

View File

@ -0,0 +1,24 @@
---
source: crates/aiken-lang/src/parser/definition/data_type.rs
description: "Code:\n\npub type Foo {\n}\n"
---
DataType(
DataType {
constructors: [
RecordConstructor {
location: 0..16,
name: "Foo",
arguments: [],
doc: None,
sugar: true,
},
],
doc: None,
location: 0..16,
name: "Foo",
opaque: false,
parameters: [],
public: true,
typed_parameters: [],
},
)

View File

@ -0,0 +1,161 @@
---
source: crates/aiken-lang/src/parser/definition/validator.rs
description: "Code:\n\nvalidator thing {\n spend (datum, rdmr, ctx) {\n True\n }\n\n mint (rdmr, ctx) {\n True\n }\n\n else (_) {\n fail\n }\n}\n"
---
Validator(
Validator {
doc: None,
end_position: 122,
handlers: [
Function {
arguments: [
UntypedArg {
by: ByName(
Named {
name: "datum",
label: "datum",
location: 27..32,
},
),
location: 27..32,
annotation: None,
doc: None,
is_validator_param: false,
},
UntypedArg {
by: ByName(
Named {
name: "rdmr",
label: "rdmr",
location: 34..38,
},
),
location: 34..38,
annotation: None,
doc: None,
is_validator_param: false,
},
UntypedArg {
by: ByName(
Named {
name: "ctx",
label: "ctx",
location: 40..43,
},
),
location: 40..43,
annotation: None,
doc: None,
is_validator_param: false,
},
],
body: Var {
location: 51..55,
name: "True",
},
doc: None,
location: 20..44,
name: "spend",
public: true,
return_annotation: Some(
Constructor {
location: 26..44,
module: None,
name: "Bool",
arguments: [],
},
),
return_type: (),
end_position: 58,
on_test_failure: FailImmediately,
},
Function {
arguments: [
UntypedArg {
by: ByName(
Named {
name: "rdmr",
label: "rdmr",
location: 69..73,
},
),
location: 69..73,
annotation: None,
doc: None,
is_validator_param: false,
},
UntypedArg {
by: ByName(
Named {
name: "ctx",
label: "ctx",
location: 75..78,
},
),
location: 75..78,
annotation: None,
doc: None,
is_validator_param: false,
},
],
body: Var {
location: 86..90,
name: "True",
},
doc: None,
location: 63..79,
name: "mint",
public: true,
return_annotation: Some(
Constructor {
location: 68..79,
module: None,
name: "Bool",
arguments: [],
},
),
return_type: (),
end_position: 93,
on_test_failure: FailImmediately,
},
],
location: 0..9,
name: "thing",
params: [],
fallback: Function {
arguments: [
UntypedArg {
by: ByName(
Discarded {
name: "_",
label: "_",
location: 104..105,
},
),
location: 104..105,
annotation: None,
doc: None,
is_validator_param: false,
},
],
body: ErrorTerm {
location: 113..117,
},
doc: None,
location: 103..106,
name: "else",
public: true,
return_annotation: Some(
Constructor {
location: 103..106,
module: None,
name: "Bool",
arguments: [],
},
),
return_type: (),
end_position: 120,
on_test_failure: FailImmediately,
},
},
)

View File

@ -0,0 +1,51 @@
---
source: crates/aiken-lang/src/parser/definition/function.rs
description: "Code:\n\nfn run() {\n let x = 1 + 1\n}\n"
---
Fn(
Function {
arguments: [],
body: Assignment {
location: 13..26,
value: BinOp {
location: 21..26,
name: AddInt,
left: UInt {
location: 21..22,
value: "1",
base: Decimal {
numeric_underscore: false,
},
},
right: UInt {
location: 25..26,
value: "1",
base: Decimal {
numeric_underscore: false,
},
},
},
patterns: [
AssignmentPattern {
pattern: Var {
location: 17..18,
name: "x",
},
annotation: None,
location: 17..18,
},
],
kind: Let {
backpassing: false,
},
},
doc: None,
location: 0..8,
name: "run",
public: false,
return_annotation: None,
return_type: (),
end_position: 27,
on_test_failure: FailImmediately,
},
)

View File

@ -0,0 +1,62 @@
---
source: crates/aiken-lang/src/parser/definition/function.rs
description: "Code:\n\nfn foo(Foo { my_field }) {\n my_field * 2\n}\n"
---
Fn(
Function {
arguments: [
UntypedArg {
by: ByPattern(
Constructor {
is_record: true,
location: 7..23,
name: "Foo",
arguments: [
CallArg {
label: Some(
"my_field",
),
location: 13..21,
value: Var {
location: 13..21,
name: "my_field",
},
},
],
module: None,
constructor: (),
spread_location: None,
tipo: (),
},
),
location: 7..23,
annotation: None,
doc: None,
is_validator_param: false,
},
],
body: BinOp {
location: 31..43,
name: MultInt,
left: Var {
location: 31..39,
name: "my_field",
},
right: UInt {
location: 42..43,
value: "2",
base: Decimal {
numeric_underscore: false,
},
},
},
doc: None,
location: 0..24,
name: "foo",
public: false,
return_annotation: None,
return_type: (),
end_position: 44,
on_test_failure: FailImmediately,
},
)

View File

@ -0,0 +1,69 @@
---
source: crates/aiken-lang/src/parser/definition/function.rs
description: "Code:\n\nfn foo(Foo { my_field, .. } as x) {\n my_field * x.my_other_field\n}\n"
---
Fn(
Function {
arguments: [
UntypedArg {
by: ByPattern(
Assign {
name: "x",
location: 7..32,
pattern: Constructor {
is_record: true,
location: 7..27,
name: "Foo",
arguments: [
CallArg {
label: Some(
"my_field",
),
location: 13..21,
value: Var {
location: 13..21,
name: "my_field",
},
},
],
module: None,
constructor: (),
spread_location: Some(
23..25,
),
tipo: (),
},
},
),
location: 7..32,
annotation: None,
doc: None,
is_validator_param: false,
},
],
body: BinOp {
location: 40..67,
name: MultInt,
left: Var {
location: 40..48,
name: "my_field",
},
right: FieldAccess {
location: 51..67,
label: "my_other_field",
container: Var {
location: 51..52,
name: "x",
},
},
},
doc: None,
location: 0..33,
name: "foo",
public: false,
return_annotation: None,
return_type: (),
end_position: 68,
on_test_failure: FailImmediately,
},
)

View File

@ -0,0 +1,69 @@
---
source: crates/aiken-lang/src/parser/definition/function.rs
description: "Code:\n\nfn foo(Foo { my_field }: Foo) {\n my_field * 2\n}\n"
---
Fn(
Function {
arguments: [
UntypedArg {
by: ByPattern(
Constructor {
is_record: true,
location: 7..23,
name: "Foo",
arguments: [
CallArg {
label: Some(
"my_field",
),
location: 13..21,
value: Var {
location: 13..21,
name: "my_field",
},
},
],
module: None,
constructor: (),
spread_location: None,
tipo: (),
},
),
location: 7..28,
annotation: Some(
Constructor {
location: 25..28,
module: None,
name: "Foo",
arguments: [],
},
),
doc: None,
is_validator_param: false,
},
],
body: BinOp {
location: 36..48,
name: MultInt,
left: Var {
location: 36..44,
name: "my_field",
},
right: UInt {
location: 47..48,
value: "2",
base: Decimal {
numeric_underscore: false,
},
},
},
doc: None,
location: 0..29,
name: "foo",
public: false,
return_annotation: None,
return_type: (),
end_position: 49,
on_test_failure: FailImmediately,
},
)

View File

@ -11,10 +11,11 @@ Fn(
then: ErrorTerm {
location: 0..15,
},
text: String {
label: String {
location: 0..15,
value: "aiken::todo",
},
arguments: [],
},
doc: None,
location: 0..12,
@ -23,6 +24,6 @@ Fn(
return_annotation: None,
return_type: (),
end_position: 14,
can_error: true,
on_test_failure: FailImmediately,
},
)

View File

@ -11,10 +11,11 @@ Fn(
then: ErrorTerm {
location: 0..11,
},
text: String {
label: String {
location: 0..11,
value: "aiken::todo",
},
arguments: [],
},
doc: None,
location: 0..8,
@ -23,6 +24,6 @@ Fn(
return_annotation: None,
return_type: (),
end_position: 10,
can_error: true,
on_test_failure: FailImmediately,
},
)

View File

@ -0,0 +1,53 @@
---
source: crates/aiken-lang/src/parser/definition/constant.rs
description: "Code:\n\npub const point =\n #<Bls12_381, G1>\"950dfd33da2682260c76038dfb8bad6e84ae9d599a3c151815945ac1e6ef6b1027cd917f3907479d20d636ce437a41f5\"\n"
---
ModuleConstant(
ModuleConstant {
doc: None,
location: 0..134,
public: true,
name: "point",
annotation: None,
value: CurvePoint {
location: 20..134,
point: Bls12_381(
G1(
blst_p1 {
x: blst_fp {
l: [
6044239372598254900,
11111890802926526657,
302563157772145122,
17359147598889707489,
6255098506247414666,
1773881592225990778,
],
},
y: blst_fp {
l: [
9961536754182800925,
16512912018612749997,
10822258563185590636,
17742512098199848220,
16542676355910829810,
1246663995533626329,
],
},
z: blst_fp {
l: [
8505329371266088957,
17002214543764226050,
6865905132761471162,
8632934651105793861,
6631298214892334189,
1582556514881692819,
],
},
},
),
),
preferred_format: HexadecimalString,
},
},
)

View File

@ -0,0 +1,95 @@
---
source: crates/aiken-lang/src/parser/definition/constant.rs
description: "Code:\n\npub const point =\n #<Bls12_381, G2>\"b0629fa1158c2d23a10413fe91d381a84d25e31d041cd0377d25828498fd02011b35893938ced97535395e4815201e67108bcd4665e0db25d602d76fa791fab706c54abf5e1a9e44b4ac1e6badf3d2ac0328f5e30be341677c8bac5dda7682f1\"\n"
---
ModuleConstant(
ModuleConstant {
doc: None,
location: 0..230,
public: true,
name: "point",
annotation: None,
value: CurvePoint {
location: 20..230,
point: Bls12_381(
G2(
blst_p2 {
x: blst_fp2 {
fp: [
blst_fp {
l: [
17730081354175209597,
14393386882433024580,
15392237588654399813,
13132804324748058634,
437180824693959563,
1209861931331675905,
],
},
blst_fp {
l: [
16640134302799489459,
13200372101402265278,
3491868243815184488,
15749231165976205625,
10700844509881097270,
978652262052845623,
],
},
],
},
y: blst_fp2 {
fp: [
blst_fp {
l: [
15138882304466955413,
4159460337006967255,
16059739792181277381,
4673287545394659101,
6265740687822174786,
1492317236631555918,
],
},
blst_fp {
l: [
7482650483077279660,
1528034342759119680,
1732030343867801117,
8394128533480400141,
6497663211870147931,
683724859415636652,
],
},
],
},
z: blst_fp2 {
fp: [
blst_fp {
l: [
8505329371266088957,
17002214543764226050,
6865905132761471162,
8632934651105793861,
6631298214892334189,
1582556514881692819,
],
},
blst_fp {
l: [
0,
0,
0,
0,
0,
0,
],
},
],
},
},
),
),
preferred_format: HexadecimalString,
},
},
)

View File

@ -2,17 +2,15 @@
source: crates/aiken-lang/src/parser/definition/import.rs
description: "Code:\n\nuse aiken/list as foo"
---
Use(
Use {
as_name: Some(
"foo",
),
location: 0..21,
module: [
"aiken",
"list",
],
package: (),
unqualified: [],
},
)
Use {
as_name: Some(
"foo",
),
location: 0..21,
module: [
"aiken",
"list",
],
package: (),
unqualified: [],
}

View File

@ -2,15 +2,13 @@
source: crates/aiken-lang/src/parser/definition/import.rs
description: "Code:\n\nuse aiken/list"
---
Use(
Use {
as_name: None,
location: 0..14,
module: [
"aiken",
"list",
],
package: (),
unqualified: [],
},
)
Use {
as_name: None,
location: 0..14,
module: [
"aiken",
"list",
],
package: (),
unqualified: [],
}

View File

@ -2,32 +2,28 @@
source: crates/aiken-lang/src/parser/definition/import.rs
description: "Code:\n\nuse std/address.{Address as A, thing as w}\n"
---
Use(
Use {
as_name: None,
location: 0..42,
module: [
"std",
"address",
],
package: (),
unqualified: [
UnqualifiedImport {
location: 17..29,
name: "Address",
as_name: Some(
"A",
),
layer: Value,
},
UnqualifiedImport {
location: 31..41,
name: "thing",
as_name: Some(
"w",
),
layer: Value,
},
],
},
)
Use {
as_name: None,
location: 0..42,
module: [
"std",
"address",
],
package: (),
unqualified: [
UnqualifiedImport {
location: 17..29,
name: "Address",
as_name: Some(
"A",
),
},
UnqualifiedImport {
location: 31..41,
name: "thing",
as_name: Some(
"w",
),
},
],
}

View File

@ -0,0 +1,39 @@
---
source: crates/aiken-lang/src/parser/definition/data_type.rs
description: "Code:\n\npub type Foo {\n wow: Int,\n}\n"
---
DataType(
DataType {
constructors: [
RecordConstructor {
location: 13..28,
name: "Foo",
arguments: [
RecordConstructorArg {
label: Some(
"wow",
),
annotation: Constructor {
location: 22..25,
module: None,
name: "Int",
arguments: [],
},
location: 17..25,
tipo: (),
doc: None,
},
],
doc: None,
sugar: true,
},
],
doc: None,
location: 0..28,
name: "Foo",
opaque: false,
parameters: [],
public: true,
typed_parameters: [],
},
)

View File

@ -1,62 +1,112 @@
---
source: crates/aiken-lang/src/parser/definition/validator.rs
description: "Code:\n\nvalidator {\n fn foo(datum, rdmr, ctx) {\n True\n }\n}\n"
description: "Code:\n\nvalidator hello {\n spend (datum, rdmr, ctx) {\n True\n }\n}\n"
---
Validator(
Validator {
doc: None,
end_position: 54,
fun: Function {
end_position: 60,
handlers: [
Function {
arguments: [
UntypedArg {
by: ByName(
Named {
name: "datum",
label: "datum",
location: 27..32,
},
),
location: 27..32,
annotation: None,
doc: None,
is_validator_param: false,
},
UntypedArg {
by: ByName(
Named {
name: "rdmr",
label: "rdmr",
location: 34..38,
},
),
location: 34..38,
annotation: None,
doc: None,
is_validator_param: false,
},
UntypedArg {
by: ByName(
Named {
name: "ctx",
label: "ctx",
location: 40..43,
},
),
location: 40..43,
annotation: None,
doc: None,
is_validator_param: false,
},
],
body: Var {
location: 51..55,
name: "True",
},
doc: None,
location: 20..44,
name: "spend",
public: true,
return_annotation: Some(
Constructor {
location: 26..44,
module: None,
name: "Bool",
arguments: [],
},
),
return_type: (),
end_position: 58,
on_test_failure: FailImmediately,
},
],
location: 0..9,
name: "hello",
params: [],
fallback: Function {
arguments: [
Arg {
arg_name: Named {
name: "datum",
label: "datum",
location: 21..26,
is_validator_param: false,
},
location: 21..26,
UntypedArg {
by: ByName(
Discarded {
name: "_",
label: "_",
location: 0..9,
},
),
location: 0..9,
annotation: None,
tipo: (),
},
Arg {
arg_name: Named {
name: "rdmr",
label: "rdmr",
location: 28..32,
is_validator_param: false,
},
location: 28..32,
annotation: None,
tipo: (),
},
Arg {
arg_name: Named {
name: "ctx",
label: "ctx",
location: 34..37,
is_validator_param: false,
},
location: 34..37,
annotation: None,
tipo: (),
doc: None,
is_validator_param: false,
},
],
body: Var {
location: 45..49,
name: "True",
body: ErrorTerm {
location: 0..9,
},
doc: None,
location: 14..38,
name: "foo",
public: false,
return_annotation: None,
location: 0..9,
name: "else",
public: true,
return_annotation: Some(
Constructor {
location: 0..9,
module: None,
name: "Bool",
arguments: [],
},
),
return_type: (),
end_position: 52,
can_error: true,
end_position: 8,
on_test_failure: FailImmediately,
},
other_fun: None,
location: 0..9,
params: [],
},
)

View File

@ -1,30 +1,44 @@
use chumsky::prelude::*;
use crate::{
ast,
ast::OnTestFailure,
expr::UntypedExpr,
parser::{error::ParseError, expr, token::Token},
parser::{
annotation,
chain::{call::parser as call, field_access, tuple_index::parser as tuple_index, Chain},
error::ParseError,
expr::{self, bytearray, int as uint, list, string, tuple, var},
pattern,
token::Token,
},
};
use chumsky::prelude::*;
pub fn parser() -> impl Parser<Token, ast::UntypedDefinition, Error = ParseError> {
// TODO: can remove Token::Bang after a few releases (curr v1.0.11)
just(Token::Bang)
.ignored()
.or_not()
.then_ignore(just(Token::Test))
.then(select! {Token::Name {name} => name})
.then_ignore(just(Token::LeftParen))
.then_ignore(just(Token::RightParen))
.then(just(Token::Fail).ignored().or_not())
just(Token::Test)
.ignore_then(select! {Token::Name {name} => name})
.then(
via()
.separated_by(just(Token::Comma))
.allow_trailing()
.delimited_by(just(Token::LeftParen), just(Token::RightParen)),
)
.then(
just(Token::Fail)
.ignore_then(just(Token::Once).ignored().or_not().map(|once| {
once.map(|_| OnTestFailure::SucceedImmediately)
.unwrap_or(OnTestFailure::SucceedEventually)
}))
.or_not(),
)
.map_with_span(|name, span| (name, span))
.then(
expr::sequence()
.or_not()
.delimited_by(just(Token::LeftBrace), just(Token::RightBrace)),
)
.map_with_span(|((((old_fail, name), fail), span_end), body), span| {
.map_with_span(|((((name, arguments), fail), span_end), body), span| {
ast::UntypedDefinition::Test(ast::Function {
arguments: vec![],
arguments,
body: body.unwrap_or_else(|| UntypedExpr::todo(None, span)),
doc: None,
location: span_end,
@ -33,15 +47,101 @@ pub fn parser() -> impl Parser<Token, ast::UntypedDefinition, Error = ParseError
public: false,
return_annotation: None,
return_type: (),
can_error: fail.is_some() || old_fail.is_some(),
on_test_failure: fail.unwrap_or(OnTestFailure::FailImmediately),
})
})
}
pub fn via() -> impl Parser<Token, ast::UntypedArgVia, Error = ParseError> {
choice((
select! {Token::DiscardName {name} => name}.map_with_span(|name, span| {
ast::ArgBy::ByName(ast::ArgName::Discarded {
label: name.clone(),
name,
location: span,
})
}),
select! {Token::Name {name} => name}.map_with_span(|name, location| {
ast::ArgBy::ByName(ast::ArgName::Named {
label: name.clone(),
name,
location,
})
}),
pattern().map(ast::ArgBy::ByPattern),
))
.then(just(Token::Colon).ignore_then(annotation()).or_not())
.map_with_span(|(arg_name, annotation), location| (arg_name, annotation, location))
.then_ignore(just(Token::Via))
.then(fuzzer())
.map(|((by, annotation, location), via)| ast::ArgVia {
arg: ast::UntypedArg {
by,
annotation,
location,
doc: None,
is_validator_param: false,
},
via,
})
}
pub fn fuzzer<'a>() -> impl Parser<Token, UntypedExpr, Error = ParseError> + 'a {
recursive(|expression| {
let chain = choice((
tuple_index(),
field_access::parser(),
call(expression.clone()),
));
let int = || {
just(Token::Minus)
.to(ast::UnOp::Negate)
.map_with_span(|op, span| (op, span))
.or_not()
.then(uint())
.map(|(op, value)| match op {
None => value,
Some((op, location)) => UntypedExpr::UnOp {
op,
location,
value: Box::new(value),
},
})
};
choice((
int(),
string(),
bytearray(),
tuple(expression.clone()),
list(expression.clone()),
var(),
))
.then(chain.repeated())
.foldl(|expr, chain| match chain {
Chain::Call(args, span) => expr.call(args, span),
Chain::FieldAccess(label, span) => expr.field_access(label, span),
Chain::TupleIndex(index, span) => expr.tuple_index(index, span),
})
})
}
#[cfg(test)]
mod tests {
use crate::assert_definition;
#[test]
fn def_test() {
assert_definition!(
r#"
test foo() {
True
}
"#
);
}
#[test]
fn def_test_fail() {
assert_definition!(
@ -54,4 +154,37 @@ mod tests {
"#
);
}
#[test]
fn def_property_test() {
assert_definition!(
r#"
test foo(x via fuzz.any_int) {
True
}
"#
);
}
#[test]
fn def_invalid_property_test() {
assert_definition!(
r#"
test foo(x via f, y via g) {
True
}
"#
);
}
#[test]
fn def_property_test_annotated_fuzzer() {
assert_definition!(
r#"
test foo(x: Int via foo()) {
True
}
"#
);
}
}

View File

@ -1,62 +1,112 @@
use chumsky::prelude::*;
use super::function::param;
use crate::{
ast,
parser::{error::ParseError, token::Token},
ast::{self, well_known},
expr::UntypedExpr,
parser::{annotation, error::ParseError, expr, token::Token},
};
use super::function;
use chumsky::prelude::*;
pub fn parser() -> impl Parser<Token, ast::UntypedDefinition, Error = ParseError> {
just(Token::Validator)
.ignore_then(
function::param(true)
.ignore_then(select! {Token::Name {name} => name})
.then(
param(true)
.separated_by(just(Token::Comma))
.allow_trailing()
.delimited_by(just(Token::LeftParen), just(Token::RightParen))
.map_with_span(|arguments, span| (arguments, span))
.or_not(),
)
// so far: validator my_validator(arg1: Whatever)
.then(
function()
select! {Token::Name {name} => name}
.then(args_and_body())
.map_with_span(|(name, mut function), span| {
function.name = name;
function.location.start = span.start;
function
})
.repeated()
.at_least(1)
.at_most(2)
.delimited_by(just(Token::LeftBrace), just(Token::RightBrace))
.map(|defs| {
defs.into_iter().map(|def| {
let ast::UntypedDefinition::Fn(fun) = def else {
unreachable!("It should be a fn definition");
};
.then(
just(Token::Else)
.ignore_then(args_and_body().map_with_span(|mut function, span| {
function.name = well_known::VALIDATOR_ELSE.to_string();
function.location.start = span.start;
fun
})
}),
function
}))
.or_not(),
)
.delimited_by(just(Token::LeftBrace), just(Token::RightBrace)),
)
.map_with_span(|(opt_extra_params, mut functions), span| {
let (params, params_span) = opt_extra_params.unwrap_or((
vec![],
ast::Span {
start: 0,
end: span.start + "validator".len(),
},
));
.map_with_span(
|((name, opt_extra_params), (handlers, opt_catch_all)), span| {
let (params, params_span) = opt_extra_params.unwrap_or((
vec![],
ast::Span {
start: 0,
end: span.start + "validator".len(),
},
));
ast::UntypedDefinition::Validator(ast::Validator {
doc: None,
fun: functions
.next()
.expect("unwrapping safe because there's 'at_least(1)' function"),
other_fun: functions.next(),
location: ast::Span {
let location = ast::Span {
start: span.start,
// capture the span from the optional params
end: params_span.end,
},
params,
end_position: span.end - 1,
})
})
};
ast::UntypedDefinition::Validator(ast::Validator {
doc: None,
name,
handlers,
location,
params,
end_position: span.end - 1,
fallback: opt_catch_all
.unwrap_or(ast::UntypedValidator::default_fallback(location)),
})
},
)
}
pub fn args_and_body() -> impl Parser<Token, ast::UntypedFunction, Error = ParseError> {
param(false)
.separated_by(just(Token::Comma))
.allow_trailing()
.delimited_by(just(Token::LeftParen), just(Token::RightParen))
.map_with_span(|arguments, span| (arguments, span))
.then(just(Token::RArrow).ignore_then(annotation()).or_not())
.then(
expr::sequence()
.or_not()
.delimited_by(just(Token::LeftBrace), just(Token::RightBrace)),
)
.map_with_span(
|(((arguments, args_span), return_annotation), body), span| {
let location = ast::Span {
start: span.start,
end: return_annotation
.as_ref()
.map(|l| l.location().end)
.unwrap_or_else(|| args_span.end),
};
ast::Function {
arguments,
body: body.unwrap_or_else(|| UntypedExpr::todo(None, span)),
doc: None,
location,
end_position: span.end - 1,
name: "temp".to_string(),
public: true,
return_annotation: return_annotation
.or(Some(ast::Annotation::boolean(location))),
return_type: (),
on_test_failure: ast::OnTestFailure::FailImmediately,
}
},
)
}
#[cfg(test)]
@ -67,8 +117,8 @@ mod tests {
fn validator() {
assert_definition!(
r#"
validator {
fn foo(datum, rdmr, ctx) {
validator hello {
spend (datum, rdmr, ctx) {
True
}
}
@ -80,16 +130,37 @@ mod tests {
fn double_validator() {
assert_definition!(
r#"
validator {
fn foo(datum, rdmr, ctx) {
validator thing {
spend (datum, rdmr, ctx) {
True
}
fn bar(rdmr, ctx) {
mint (rdmr, ctx) {
True
}
}
"#
);
}
#[test]
fn fallback() {
assert_definition!(
r#"
validator thing {
spend (datum, rdmr, ctx) {
True
}
mint (rdmr, ctx) {
True
}
else (_) {
fail
}
}
"#
);
}
}

View File

@ -1,4 +1,7 @@
use crate::{ast::Span, parser::token::Token};
use crate::{
ast::{CurveType, Span},
parser::token::Token,
};
use indoc::formatdoc;
use miette::Diagnostic;
use owo_colors::{OwoColorize, Stream::Stdout};
@ -6,9 +9,33 @@ use std::collections::HashSet;
#[derive(Debug, Clone, Diagnostic, thiserror::Error)]
#[error("{kind}\n")]
#[diagnostic(
help(
"{}",
match kind {
ErrorKind::Unexpected(..) if !expected.is_empty() => {
format!(
"I am looking for one of the following patterns:\n{}",
expected
.iter()
.map(|x| format!(
"→ {}",
x.to_aiken()
.if_supports_color(Stdout, |s| s.purple())
))
.collect::<Vec<_>>()
.join("\n")
)
},
_ => {
kind.help().map(|x| x.to_string()).unwrap_or_default()
}
}
)
)]
pub struct ParseError {
pub kind: ErrorKind,
#[label]
#[label("{}", .label.unwrap_or_default())]
pub span: Span,
#[allow(dead_code)]
while_parsing: Option<(Span, &'static str)>,
@ -25,6 +52,26 @@ impl ParseError {
self
}
pub fn expected_but_got(expected: Pattern, got: Pattern, span: Span) -> Self {
Self {
kind: ErrorKind::Unexpected(got),
expected: HashSet::from_iter([expected]),
span,
while_parsing: None,
label: None,
}
}
pub fn invalid_assignment_right_hand_side(span: Span) -> Self {
Self {
kind: ErrorKind::UnfinishedAssignmentRightHandSide,
span,
while_parsing: None,
expected: HashSet::new(),
label: Some("invalid assignment right-hand side"),
}
}
pub fn invalid_tuple_index(span: Span, index: String, suffix: Option<String>) -> Self {
let hint = suffix.map(|suffix| format!("Did you mean '{index}{suffix}'?"));
Self {
@ -36,13 +83,39 @@ impl ParseError {
}
}
pub fn invalid_when_clause_guard(span: Span) -> Self {
pub fn deprecated_when_clause_guard(span: Span) -> Self {
Self {
kind: ErrorKind::InvalidWhenClause,
kind: ErrorKind::DeprecatedWhenClause,
span,
while_parsing: None,
expected: HashSet::new(),
label: Some("invalid clause guard"),
label: Some("deprecated"),
}
}
pub fn point_not_on_curve(curve: CurveType, span: Span) -> Self {
Self {
kind: ErrorKind::PointNotOnCurve { curve },
span,
while_parsing: None,
expected: HashSet::new(),
label: Some("out off curve"),
}
}
pub fn unknown_point_curve(curve: String, point: Option<String>, span: Span) -> Self {
let label = if point.is_some() {
Some("unknown curve")
} else {
Some("unknown point")
};
Self {
kind: ErrorKind::UnknownCurvePoint { curve, point },
span,
while_parsing: None,
expected: HashSet::new(),
label,
}
}
@ -75,6 +148,26 @@ impl ParseError {
label: None,
}
}
pub fn match_on_curve(span: Span) -> Self {
Self {
kind: ErrorKind::PatternMatchOnCurvePoint,
span,
while_parsing: None,
expected: HashSet::new(),
label: Some("cannot pattern-match on curve point"),
}
}
pub fn match_string(span: Span) -> Self {
Self {
kind: ErrorKind::PatternMatchOnString,
span,
while_parsing: None,
expected: HashSet::new(),
label: Some("cannot pattern-match on string"),
}
}
}
impl PartialEq for ParseError {
@ -124,7 +217,7 @@ pub enum ErrorKind {
UnexpectedEnd,
#[error("{0}")]
#[diagnostic(help("{}", .0.help().unwrap_or_else(|| Box::new(""))))]
#[diagnostic(help("{}", .0.help().unwrap_or_else(|| Box::new("")))) ]
Unexpected(Pattern),
#[error("I discovered an invalid tuple index.")]
@ -134,6 +227,25 @@ pub enum ErrorKind {
hint: Option<String>,
},
#[error("I spotted an unfinished assignment.")]
#[diagnostic(
help(
"{} and {} bindings must be followed by a valid, complete, expression.",
"let".if_supports_color(Stdout, |s| s.yellow()),
"expect".if_supports_color(Stdout, |s| s.yellow()),
),
)]
UnfinishedAssignmentRightHandSide,
#[error("I tripped over a {}", fmt_curve_type(.curve))]
PointNotOnCurve { curve: CurveType },
#[error("I tripped over a {}", fmt_unknown_curve(.curve, .point))]
UnknownCurvePoint {
curve: String,
point: Option<String>,
},
#[error("I tripped over a malformed hexadecimal digits.")]
#[diagnostic(help("{}", formatdoc! {
r#"When numbers starts with '0x', they are treated as hexadecimal numbers. Thus, only digits from 0-9 or letter from a-f (or A-F) can be used following a '0x' number declaration. Plus, hexadecimal digits always go by pairs, so the total number of digits must be even (not counting leading zeros)."#
@ -157,33 +269,55 @@ pub enum ErrorKind {
}))]
MalformedBase16StringLiteral,
#[error("I came across a bytearray declared using two different notations")]
#[error("I came across a bytearray declared using two different notations.")]
#[diagnostic(url("https://aiken-lang.org/language-tour/primitive-types#bytearray"))]
#[diagnostic(help("Either use decimal or hexadecimal notation, but don't mix them."))]
HybridNotationInByteArray,
#[error("I failed to understand a when clause guard.")]
#[diagnostic(url("https://aiken-lang.org/language-tour/control-flow#checking-equality-and-ordering-in-patterns"))]
#[error("I found a now-deprecated clause guard in a when/is expression.")]
#[diagnostic(help("{}", formatdoc! {
r#"Clause guards are not as capable as standard expressions. While you can combine multiple clauses using '{operator_or}' and '{operator_and}', you can't do any arithmetic in there. They are mainly meant to compare pattern variables to some known constants using simple binary operators.
For example, the following clauses are well-formed:
{good} (x, _) if x == 10 -> ...
{good} (_, y) if y > 0 && y < 10 -> ...
{good} (x, y) if x && (y > 0 || y < 10) -> ...
However, those aren't:
{bad} (x, _) if x % 3 == 0 -> ...
{bad} (x, y) if x + y > 42 -> ...
r#"Clause guards have been removed from Aiken. They were underused, considered potentially harmful and created needless complexity in the compiler. If you were using clause guards, our apologies, but you can now update your code and move the clause guards patterns inside a nested if/else expression.
"#
, operator_or = "||".if_supports_color(Stdout, |s| s.yellow())
, operator_and = "&&".if_supports_color(Stdout, |s| s.yellow())
, good = "✔️".if_supports_color(Stdout, |s| s.green())
, bad = "✖️".if_supports_color(Stdout, |s| s.red())
}))]
InvalidWhenClause,
DeprecatedWhenClause,
#[error("I choked on a curve point in a bytearray pattern.")]
#[diagnostic(help(
"You can pattern-match on bytearrays just fine, but not on G1 nor G2 elements. Use if/else with an equality if you have to compare those."
))]
PatternMatchOnCurvePoint,
#[error("I refuse to cooperate and match a utf-8 string.")]
#[diagnostic(help(
"You can pattern-match on bytearrays but not on strings. Note that I can parse utf-8 encoded bytearrays just fine, so you probably want to drop the extra '@' and only manipulate bytearrays wherever you need to. On-chain, strings shall be avoided as much as possible."
))]
PatternMatchOnString,
}
fn fmt_curve_type(curve: &CurveType) -> String {
match curve {
CurveType::Bls12_381(point) => {
format!("{point} point that is not in the bls12_381 curve")
}
}
}
fn fmt_unknown_curve(curve: &String, point: &Option<String>) -> String {
match point {
Some(point) => {
format!(
"{} which is an unknown point for curve {}",
point.if_supports_color(Stdout, |s| s.purple()),
curve.if_supports_color(Stdout, |s| s.purple()),
)
}
None => {
format!(
"{} which is an unknown curve",
curve.if_supports_color(Stdout, |s| s.purple())
)
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Diagnostic, thiserror::Error)]
@ -194,15 +328,6 @@ pub enum Pattern {
#[error("I found an unexpected token '{0}'.")]
#[diagnostic(help("Try removing it!"))]
Token(Token),
#[error("I found an unexpected literal value.")]
#[diagnostic(help("Try removing it!"))]
Literal,
#[error("I found an unexpected type name.")]
#[diagnostic(help("Try removing it!"))]
TypeIdent,
#[error("I found an unexpected identifier.")]
#[diagnostic(help("Try removing it!"))]
TermIdent,
#[error("I found an unexpected end of input.")]
End,
#[error("I found a malformed list spread pattern.")]
@ -211,11 +336,6 @@ pub enum Pattern {
#[error("I found an out-of-bound byte literal.")]
#[diagnostic(help("Bytes must be between 0-255."))]
Byte,
#[error("I found an unexpected pattern.")]
#[diagnostic(help(
"If no label is provided then only variables\nmatching a field name are allowed."
))]
RecordPunning,
#[error("I found an unexpected label.")]
#[diagnostic(help("You can only use labels surrounded by curly braces"))]
Label,
@ -224,11 +344,27 @@ pub enum Pattern {
Discard,
}
impl Pattern {
fn to_aiken(&self) -> String {
use Pattern::*;
match self {
Token(tok) => tok.to_string(),
Char(c) => c.to_string(),
End => "<END OF FILE>".to_string(),
Match => "A pattern (a discard, a var, etc...)".to_string(),
Byte => "A byte between [0; 255]".to_string(),
Label => "A label".to_string(),
Discard => "_".to_string(),
}
}
}
impl From<char> for Pattern {
fn from(c: char) -> Self {
Self::Char(c)
}
}
impl From<Token> for Pattern {
fn from(tok: Token) -> Self {
Self::Token(tok)

View File

@ -0,0 +1,72 @@
use chumsky::prelude::*;
use crate::{
ast::LogicalOpChainKind,
expr::UntypedExpr,
parser::{error::ParseError, token::Token},
};
pub fn parser(
expression: Recursive<'_, Token, UntypedExpr, ParseError>,
) -> impl Parser<Token, UntypedExpr, Error = ParseError> + '_ {
choice((
just(Token::And).to(LogicalOpChainKind::And),
just(Token::Or).to(LogicalOpChainKind::Or),
))
.then(
expression
.separated_by(just(Token::Comma))
.allow_trailing()
.delimited_by(just(Token::LeftBrace), just(Token::RightBrace)),
)
.map_with_span(|(kind, exprs), span| UntypedExpr::LogicalOpChain {
kind,
expressions: exprs,
location: span,
})
}
#[cfg(test)]
mod tests {
use crate::assert_expr;
#[test]
fn and_chain() {
assert_expr!(
r#"
and {
1 == 2,
something,
}
"#
);
}
#[test]
fn or_chain() {
assert_expr!(
r#"
or {
1 == 2,
something,
}
"#
);
}
#[test]
fn and_or_chain() {
assert_expr!(
r#"
or {
1 == 2,
something,
and {
1 == 2,
something,
},
}
"#
);
}
}

View File

@ -1,10 +1,9 @@
use chumsky::prelude::*;
use crate::{
ast,
expr::{FnStyle, UntypedExpr},
parser::{error::ParseError, token::Token},
};
use chumsky::prelude::*;
pub fn parser() -> impl Parser<Token, UntypedExpr, Error = ParseError> {
select! {
@ -41,27 +40,27 @@ pub fn parser() -> impl Parser<Token, UntypedExpr, Error = ParseError> {
};
let arguments = vec![
ast::Arg {
arg_name: ast::ArgName::Named {
ast::UntypedArg {
by: ast::ArgBy::ByName(ast::ArgName::Named {
name: "left".to_string(),
label: "left".to_string(),
location,
is_validator_param: false,
},
}),
is_validator_param: false,
annotation: arg_annotation.clone(),
doc: None,
location,
tipo: (),
},
ast::Arg {
arg_name: ast::ArgName::Named {
ast::UntypedArg {
by: ast::ArgBy::ByName(ast::ArgName::Named {
name: "right".to_string(),
label: "right".to_string(),
location,
is_validator_param: false,
},
}),
is_validator_param: false,
annotation: arg_annotation,
doc: None,
location,
tipo: (),
},
];

View File

@ -1,10 +1,9 @@
use chumsky::prelude::*;
use crate::{
ast,
expr::{FnStyle, UntypedExpr},
parser::{annotation, error::ParseError, token::Token},
parser::{annotation, error::ParseError, pattern, token::Token},
};
use chumsky::prelude::*;
pub fn parser(
sequence: Recursive<'_, Token, UntypedExpr, ParseError>,
@ -33,25 +32,28 @@ pub fn params() -> impl Parser<Token, ast::UntypedArg, Error = ParseError> {
// TODO: return a better error when a label is provided `UnexpectedLabel`
choice((
select! {Token::DiscardName {name} => name}.map_with_span(|name, span| {
ast::ArgName::Discarded {
ast::ArgBy::ByName(ast::ArgName::Discarded {
label: name.clone(),
name,
location: span,
}
})
}),
select! {Token::Name {name} => name}.map_with_span(|name, span| ast::ArgName::Named {
label: name.clone(),
name,
location: span,
is_validator_param: false,
select! {Token::Name {name} => name}.map_with_span(|name, span| {
ast::ArgBy::ByName(ast::ArgName::Named {
label: name.clone(),
name,
location: span,
})
}),
pattern().map(ast::ArgBy::ByPattern),
))
.then(just(Token::Colon).ignore_then(annotation()).or_not())
.map_with_span(|(arg_name, annotation), span| ast::Arg {
.map_with_span(|(by, annotation), span| ast::UntypedArg {
is_validator_param: false,
location: span,
annotation,
tipo: (),
arg_name,
doc: None,
by,
})
}
@ -63,4 +65,19 @@ mod tests {
fn anonymous_function_basic() {
assert_expr!(r#"fn (a: Int) -> Int { a + 1 }"#);
}
#[test]
fn anonymous_function_by_pattern_no_annotation() {
assert_expr!(r#"fn (Foo { my_field }) { my_field * 2 }"#);
}
#[test]
fn anonymous_function_by_pattern_with_annotation() {
assert_expr!(r#"fn (Foo { my_field } : Foo) { my_field * 2 }"#);
}
#[test]
fn anonymous_function_by_pattern_with_alias() {
assert_expr!(r#"fn (Foo { my_field, .. } as x) { my_field * my_other_field }"#);
}
}

View File

@ -1,28 +1,52 @@
use chumsky::prelude::*;
use crate::{
ast,
ast::{self, Span},
expr::UntypedExpr,
parser::{annotation, error::ParseError, pattern, token::Token},
};
use chumsky::prelude::*;
pub fn let_(
r: Recursive<'_, Token, UntypedExpr, ParseError>,
) -> impl Parser<Token, UntypedExpr, Error = ParseError> + '_ {
just(Token::Let)
.ignore_then(pattern())
.then(just(Token::Colon).ignore_then(annotation()).or_not())
.then_ignore(just(Token::Equal))
.ignore_then(assignment_patterns())
.then(choice((just(Token::Equal), just(Token::LArrow))))
.then(r.clone())
.map_with_span(
move |((pattern, annotation), value), span| UntypedExpr::Assignment {
.validate(move |((patterns, kind), value), span, emit| {
if matches!(value, UntypedExpr::Assignment { .. }) {
emit(ParseError::invalid_assignment_right_hand_side(span))
}
let patterns = patterns
.try_into()
.expect("We use at_least(1) so this should never be empty");
UntypedExpr::Assignment {
location: span,
value: Box::new(value),
pattern,
kind: ast::AssignmentKind::Let,
annotation,
},
)
patterns,
kind: ast::AssignmentKind::Let {
backpassing: kind == Token::LArrow,
},
}
})
}
fn assignment_patterns() -> impl Parser<Token, Vec<ast::AssignmentPattern>, Error = ParseError> {
assignment_pattern()
.separated_by(just(Token::Comma))
.allow_trailing()
.at_least(1)
}
pub fn assignment_pattern() -> impl Parser<Token, ast::AssignmentPattern, Error = ParseError> {
pattern()
.then(just(Token::Colon).ignore_then(annotation()).or_not())
.map_with_span(|(pattern, annotation), span| ast::AssignmentPattern {
pattern,
annotation,
location: span,
})
}
pub fn expect(
@ -30,35 +54,37 @@ pub fn expect(
) -> impl Parser<Token, UntypedExpr, Error = ParseError> + '_ {
just(Token::Expect)
.ignore_then(
pattern()
.then(just(Token::Colon).ignore_then(annotation()).or_not())
.then_ignore(just(Token::Equal))
assignment_patterns()
.then(choice((just(Token::Equal), just(Token::LArrow))))
.or_not(),
)
.then(r.clone())
.map_with_span(move |(opt_pattern, value), span| {
let (pattern, annotation) = opt_pattern.unwrap_or_else(|| {
(
ast::UntypedPattern::Constructor {
is_record: false,
location: span,
name: "True".to_string(),
arguments: vec![],
module: None,
constructor: (),
with_spread: false,
tipo: (),
},
.validate(move |(opt_pattern, value), span, emit| {
if matches!(value, UntypedExpr::Assignment { .. }) {
emit(ParseError::invalid_assignment_right_hand_side(span))
}
let (patterns, kind) = opt_pattern.unwrap_or_else(|| {
let filler_true = ast::AssignmentPattern::new(
ast::UntypedPattern::true_(span),
None,
)
Span::empty(),
);
(vec![filler_true], Token::Equal)
});
let patterns = patterns
.try_into()
.expect("We use at_least(1) so this should never be empty");
UntypedExpr::Assignment {
location: span,
patterns,
value: Box::new(value),
pattern,
kind: ast::AssignmentKind::Expect,
annotation,
kind: ast::AssignmentKind::Expect {
backpassing: kind == Token::LArrow,
},
}
})
}
@ -86,4 +112,42 @@ mod tests {
fn expect_trace_if_false() {
assert_expr!("expect foo?");
}
#[test]
fn expect_unfinished_let() {
assert_expr!(
"
let a =
// foo
let b = 42
"
);
}
#[test]
fn expect_let_in_let() {
assert_expr!("let a = { let b = 42 }");
}
#[test]
fn expect_let_in_let_return() {
assert_expr!(
"
let a = {
let b = 42
b
}
"
);
}
#[test]
fn expect_let_in_let_parens() {
assert_expr!("let a = ( let b = 42 )");
}
#[test]
fn expect_expect_let() {
assert_expr!("expect { let a = 42 } = foo");
}
}

View File

@ -17,6 +17,16 @@ pub fn parser(
just(Token::RightParen),
),
))
.map_with_span(|e, span| {
if matches!(e, UntypedExpr::Assignment { .. }) {
UntypedExpr::Sequence {
location: span,
expressions: vec![e],
}
} else {
e
}
})
}
#[cfg(test)]
@ -24,15 +34,24 @@ mod tests {
use crate::assert_expr;
#[test]
fn block_basic() {
fn block_let() {
assert_expr!(
r#"
let b = {
let x = 4
x + 5
}
"#
);
}
#[test]
fn block_single() {
assert_expr!(
r#"{
foo
}
"#
);
}
}

View File

@ -1,13 +1,43 @@
use chumsky::prelude::*;
use uplc::machine::runtime::Compressable;
use crate::parser::{error::ParseError, expr::UntypedExpr, literal::bytearray, token::Token};
use crate::{
ast,
parser::{error::ParseError, expr::UntypedExpr, literal::bytearray, token::Token},
};
pub fn parser() -> impl Parser<Token, UntypedExpr, Error = ParseError> {
bytearray(|bytes, preferred_format, location| UntypedExpr::ByteArray {
location,
bytes,
preferred_format,
})
bytearray(
|bytes, preferred_format, curve, location, emit| match curve {
Some(curve @ ast::CurveType::Bls12_381(point)) => {
let point = match point {
ast::Bls12_381PointType::G1 => {
blst::blst_p1::uncompress(&bytes).map(ast::Bls12_381Point::G1)
}
ast::Bls12_381PointType::G2 => {
blst::blst_p2::uncompress(&bytes).map(ast::Bls12_381Point::G2)
}
};
let point = point.unwrap_or_else(|_err| {
emit(ParseError::point_not_on_curve(curve, location));
ast::Bls12_381Point::default()
});
UntypedExpr::CurvePoint {
location,
point: ast::Curve::Bls12_381(point).into(),
preferred_format,
}
}
None => UntypedExpr::ByteArray {
location,
bytes,
preferred_format,
},
},
)
}
#[cfg(test)]
@ -28,4 +58,19 @@ mod tests {
fn bytearray_utf8_encoded() {
assert_expr!("\"aiken\"");
}
#[test]
fn bytearray_utf8_escaped() {
assert_expr!("\"\\\"aiken\\\"\"");
}
#[test]
fn g1_element() {
assert_expr!("#<Bls12_381, G1>\"950dfd33da2682260c76038dfb8bad6e84ae9d599a3c151815945ac1e6ef6b1027cd917f3907479d20d636ce437a41f5\"");
}
#[test]
fn g2_element() {
assert_expr!("#<Bls12_381, G2>\"b0629fa1158c2d23a10413fe91d381a84d25e31d041cd0377d25828498fd02011b35893938ced97535395e4815201e67108bcd4665e0db25d602d76fa791fab706c54abf5e1a9e44b4ac1e6badf3d2ac0328f5e30be341677c8bac5dda7682f1\"");
}
}

View File

@ -1,20 +1,11 @@
use chumsky::prelude::*;
use super::anonymous_binop::parser as anonymous_binop;
use super::anonymous_function::parser as anonymous_function;
use super::assignment;
use super::block::parser as block;
use super::bytearray::parser as bytearray;
use super::if_else::parser as if_else;
use super::int::parser as int;
use super::list::parser as list;
use super::record::parser as record;
use super::record_update::parser as record_update;
use super::string::parser as string;
use super::tuple::parser as tuple;
use super::var::parser as var;
use super::when::parser as when;
use super::{
and_or_chain, anonymous_binop::parser as anonymous_binop,
anonymous_function::parser as anonymous_function, assignment, block::parser as block,
bytearray::parser as bytearray, if_else::parser as if_else, int::parser as int,
list::parser as list, pair::parser as pair, record::parser as record,
record_update::parser as record_update, string::parser as string, tuple::parser as tuple,
var::parser as var, when::parser as when,
};
use crate::{
expr::UntypedExpr,
parser::{
@ -23,6 +14,7 @@ use crate::{
token::Token,
},
};
use chumsky::prelude::*;
pub fn parser<'a>(
sequence: Recursive<'a, Token, UntypedExpr, ParseError>,
@ -33,6 +25,7 @@ pub fn parser<'a>(
field_access::parser(),
call(expression.clone()),
));
chain_start(sequence, expression)
.then(chain.repeated())
.foldl(|expr, chain| match chain {
@ -57,9 +50,11 @@ pub fn chain_start<'a>(
choice((
string(),
int(),
pair(expression.clone()),
record_update(expression.clone()),
record(expression.clone()),
field_access::constructor(),
and_or_chain(expression.clone()),
var(),
tuple(expression.clone()),
bytearray(),

View File

@ -1,14 +1,13 @@
use chumsky::prelude::*;
use crate::{
ast::TraceKind,
expr::UntypedExpr,
parser::{
error::ParseError,
error::{ParseError, Pattern},
expr::{string, when::clause},
token::Token,
},
};
use chumsky::prelude::*;
pub fn parser<'a>(
expression: Recursive<'a, Token, UntypedExpr, ParseError>,
@ -29,13 +28,36 @@ pub fn parser<'a>(
.map_with_span(UntypedExpr::fail),
just(Token::Trace)
.ignore_then(choice((string::hybrid(), expression.clone())))
.then(
choice((just(Token::Colon), just(Token::Comma)))
.then(
choice((string::hybrid(), expression.clone()))
.separated_by(just(Token::Comma)),
)
.validate(|(token, arguments), span, emit| {
if token != Token::Colon {
emit(ParseError::expected_but_got(
Pattern::Token(Token::Colon),
Pattern::Token(token),
span.map(|start, _end| (start, start + 1)),
))
}
arguments
})
.or_not()
.map(|opt| opt.unwrap_or_default()),
)
.then(sequence.clone().or_not())
.map_with_span(|(text, then_), span| UntypedExpr::Trace {
kind: TraceKind::Trace,
location: span,
then: Box::new(then_.unwrap_or_else(|| UntypedExpr::todo(None, span))),
text: Box::new(text),
}),
.map_with_span(
|((label, arguments), continuation), span| UntypedExpr::Trace {
kind: TraceKind::Trace,
location: span,
then: Box::new(continuation.unwrap_or_else(|| UntypedExpr::todo(None, span))),
label: Box::new(label),
arguments,
},
),
))
}
@ -115,6 +137,26 @@ mod tests {
);
}
#[test]
fn trace_string() {
assert_expr!(
r#"
trace @"foo"
a
"#
);
}
#[test]
fn trace_bytearray() {
assert_expr!(
r#"
trace "foo"
a
"#
);
}
#[test]
fn trace_expr() {
assert_expr!(
@ -129,7 +171,25 @@ mod tests {
fn trace_expr_todo() {
assert_expr!(
r#"
trace some_var
trace some_var
"#
);
}
#[test]
fn trace_labelled() {
assert_expr!(
r#"
trace foo: "bar"
"#
);
}
#[test]
fn trace_variadic() {
assert_expr!(
r#"
trace "foo": @"bar", baz
"#
);
}

View File

@ -1,41 +1,21 @@
use chumsky::prelude::*;
use super::block;
use crate::{
ast,
expr::UntypedExpr,
parser::{error::ParseError, token::Token},
parser::{annotation, error::ParseError, pattern, token::Token},
};
use super::block;
use chumsky::prelude::*;
pub fn parser<'a>(
sequence: Recursive<'a, Token, UntypedExpr, ParseError>,
expression: Recursive<'a, Token, UntypedExpr, ParseError>,
) -> impl Parser<Token, UntypedExpr, Error = ParseError> + 'a {
just(Token::If)
.ignore_then(
expression
.clone()
.then(block(sequence.clone()))
.map_with_span(|(condition, body), span| ast::IfBranch {
condition,
body,
location: span,
}),
)
.ignore_then(if_branch(sequence.clone(), expression.clone()))
.then(
just(Token::Else)
.ignore_then(just(Token::If))
.ignore_then(
expression
.clone()
.then(block(sequence.clone()))
.map_with_span(|(condition, body), span| ast::IfBranch {
condition,
body,
location: span,
}),
)
.ignore_then(if_branch(sequence.clone(), expression))
.repeated(),
)
.then_ignore(just(Token::Else))
@ -53,6 +33,52 @@ pub fn parser<'a>(
})
}
fn if_branch<'a>(
sequence: Recursive<'a, Token, UntypedExpr, ParseError>,
expression: Recursive<'a, Token, UntypedExpr, ParseError>,
) -> impl Parser<Token, ast::UntypedIfBranch, Error = ParseError> + 'a {
expression
.then(
just(Token::Is)
.ignore_then(
pattern()
.then_ignore(just(Token::Colon))
.or_not()
.then(annotation())
.map_with_span(|(pattern, annotation), span| (pattern, annotation, span)),
)
.or_not(),
)
.then(block(sequence))
.map_with_span(|((condition, is), body), span| {
let is = is.map(|(pattern, annotation, is_span)| {
let pattern = pattern.unwrap_or_else(|| match &condition {
UntypedExpr::Var { name, location } => ast::Pattern::Var {
name: name.clone(),
location: *location,
},
_ => ast::Pattern::Discard {
location: is_span,
name: "_".to_string(),
},
});
ast::AssignmentPattern {
pattern,
annotation: Some(annotation),
location: is_span,
}
});
ast::IfBranch {
condition,
body,
is,
location: span,
}
})
}
#[cfg(test)]
mod tests {
use crate::assert_expr;
@ -71,4 +97,64 @@ mod tests {
"#
);
}
#[test]
fn if_else_ambiguous_record() {
assert_expr!(
r#"
if ec1 == Infinity {
ec2
} else if ec1 == Foo { foo } {
ec1
} else {
Infinity
}
"#
);
}
#[test]
fn if_else_with_soft_cast() {
assert_expr!(
r#"
if ec1 is Some(x): Option<Int> {
ec2
} else if ec1 is Foo { foo }: Foo {
ec1
} else if ec1 is Option<Int> {
let Some(x) = ec1
x
} else {
Infinity
}
"#
);
}
#[test]
fn if_soft_cast_discard_assign() {
assert_expr!(
r#"
if foo() is Foo {
todo
} else {
todo
}
"#
);
}
#[test]
fn if_soft_cast_not_var_condition() {
assert_expr!(
r#"
if foo() is Foo { a }: Foo {
todo
} else {
todo
}
"#
);
}
}

View File

@ -1,6 +1,7 @@
use chumsky::prelude::*;
use vec1::Vec1;
mod and_or_chain;
mod anonymous_binop;
pub mod anonymous_function;
pub mod assignment;
@ -11,6 +12,7 @@ mod fail_todo_trace;
mod if_else;
mod int;
mod list;
mod pair;
mod record;
mod record_update;
mod sequence;
@ -19,6 +21,9 @@ mod tuple;
mod var;
pub mod when;
use super::{error::ParseError, token::Token};
use crate::{ast, expr::UntypedExpr};
pub use and_or_chain::parser as and_or_chain;
pub use anonymous_function::parser as anonymous_function;
pub use block::parser as block;
pub use bytearray::parser as bytearray;
@ -27,6 +32,7 @@ pub use fail_todo_trace::parser as fail_todo_trace;
pub use if_else::parser as if_else;
pub use int::parser as int;
pub use list::parser as list;
pub use pair::parser as pair;
pub use record::parser as record;
pub use record_update::parser as record_update;
pub use sequence::parser as sequence;
@ -35,9 +41,6 @@ pub use tuple::parser as tuple;
pub use var::parser as var;
pub use when::parser as when;
use super::{error::ParseError, token::Token};
use crate::{ast, expr::UntypedExpr};
pub fn parser(
sequence: Recursive<'_, Token, UntypedExpr, ParseError>,
) -> impl Parser<Token, UntypedExpr, Error = ParseError> + '_ {
@ -140,28 +143,62 @@ pub fn pure_expression<'a>(
.boxed();
// Conjunction
//
// NOTE: This can be written in a nicer way with `foldl_with` in chumsky =^ 1.0.0.
// DO NOT however try to write this as:
//
// comparison
// .clone()
// .then(op)
// .repeated
// .then(comparison)
// .foldr(...)
//
// This has somehow incredibly slow performances in Chumsky. Hence the approach below.
let op = just(Token::AmperAmper).to(ast::BinOp::And);
let conjunction = comparison
.clone()
.map(|e| vec![e])
.clone()
.then(op.then(comparison).repeated())
.foldl(|a, (op, b)| UntypedExpr::BinOp {
location: a.location().union(b.location()),
name: op,
left: Box::new(a),
right: Box::new(b),
.foldl(|a, (_op, b)| {
let mut tail = vec![b];
tail.extend(a);
tail
})
.map(|xs| {
xs.into_iter()
.reduce(|right, left| UntypedExpr::BinOp {
location: left.location().union(right.location()),
name: ast::BinOp::And,
left: Box::new(left),
right: Box::new(right),
})
.unwrap()
})
.boxed();
// NOTE: see comment about conjunctions just above.
// Disjunction
let op = just(Token::VbarVbar).to(ast::BinOp::Or);
let disjunction = conjunction
.clone()
.map(|e| vec![e])
.then(op.then(conjunction).repeated())
.foldl(|a, (op, b)| UntypedExpr::BinOp {
location: a.location().union(b.location()),
name: op,
left: Box::new(a),
right: Box::new(b),
.foldl(|a, (_op, b)| {
let mut tail = vec![b];
tail.extend(a);
tail
})
.map(|xs| {
xs.into_iter()
.reduce(|right, left| UntypedExpr::BinOp {
location: left.location().union(right.location()),
name: ast::BinOp::Or,
left: Box::new(left),
right: Box::new(right),
})
.unwrap()
})
.boxed();

View File

@ -0,0 +1,54 @@
use crate::{
ast::well_known,
builtins::PRELUDE,
expr::UntypedExpr,
parser::{error::ParseError, token::Token},
};
use chumsky::prelude::*;
pub fn parser(
r: Recursive<'_, Token, UntypedExpr, ParseError>,
) -> impl Parser<Token, UntypedExpr, Error = ParseError> + '_ {
select! {Token::Name { name } if name == PRELUDE => name}
.then_ignore(just(Token::Dot))
.or_not()
.then_ignore(select! {Token::UpName { name } if name == well_known::PAIR => name})
.ignore_then(
r.clone()
.separated_by(just(Token::Comma))
.exactly(2)
.allow_trailing()
.delimited_by(
choice((just(Token::LeftParen), just(Token::NewLineLeftParen))),
just(Token::RightParen),
)
.map_with_span(|elems, location| UntypedExpr::Pair {
location,
fst: elems
.first()
.expect("Pair should have exactly 2 elements")
.to_owned()
.into(),
snd: elems
.last()
.expect("Pair should have exactly 2 elements")
.to_owned()
.into(),
}),
)
}
#[cfg(test)]
mod tests {
use crate::assert_expr;
#[test]
fn basic_pair() {
assert_expr!(r#"Pair(1, 2)"#);
}
#[test]
fn pair_from_prelude() {
assert_expr!(r#"aiken.Pair(1, 2)"#);
}
}

View File

@ -72,6 +72,38 @@ pub fn parser(
},
),
))
// NOTE: There's an ambiguity when the record shorthand syntax is used
// from within an if-else statement in the case of single-variable if-branch.
//
// For example, imagine the following:
//
// ```
// if season == Summer {
// foo
// } else {
// bar
// }
// ```
//
// Without that next odd parser combinator, the parser would parse:
//
// ```
// if season == Summer { foo }
// else {
// bar
// }
// ```
//
// And immediately choke on the next `else` because the if-branch body has
// already been consumed and interpreted as a record definition. So the next
// combinator ensures that we give priority back to an if-then statement rather
// than to the record definition.
.then_ignore(
just(Token::RightBrace)
.ignore_then(just(Token::Else))
.not()
.rewind(),
)
.map(|(value, name)| ast::CallArg {
location: value.location(),
value,
@ -155,6 +187,11 @@ pub fn parser(
mod tests {
use crate::assert_expr;
#[test]
fn record_enum() {
assert_expr!(r#"Winter"#);
}
#[test]
fn record_create_labeled() {
assert_expr!(r#"User { name: "Aiken", age, thing: 2 }"#);

View File

@ -1,9 +1,8 @@
use chumsky::prelude::*;
use crate::{
expr::UntypedExpr,
parser::{error::ParseError, token::Token},
};
use chumsky::prelude::*;
pub fn parser() -> impl Parser<Token, UntypedExpr, Error = ParseError> {
recursive(|sequence| {

View File

@ -0,0 +1,32 @@
---
source: crates/aiken-lang/src/parser/expr/and_or_chain.rs
description: "Code:\n\nand {\n 1 == 2,\n something,\n}\n"
---
LogicalOpChain {
kind: And,
expressions: [
BinOp {
location: 8..14,
name: Eq,
left: UInt {
location: 8..9,
value: "1",
base: Decimal {
numeric_underscore: false,
},
},
right: UInt {
location: 13..14,
value: "2",
base: Decimal {
numeric_underscore: false,
},
},
},
Var {
location: 18..27,
name: "something",
},
],
location: 0..30,
}

View File

@ -0,0 +1,60 @@
---
source: crates/aiken-lang/src/parser/expr/and_or_chain.rs
description: "Code:\n\nor {\n 1 == 2,\n something,\n and {\n 1 == 2,\n something,\n },\n}\n"
---
LogicalOpChain {
kind: Or,
expressions: [
BinOp {
location: 7..13,
name: Eq,
left: UInt {
location: 7..8,
value: "1",
base: Decimal {
numeric_underscore: false,
},
},
right: UInt {
location: 12..13,
value: "2",
base: Decimal {
numeric_underscore: false,
},
},
},
Var {
location: 17..26,
name: "something",
},
LogicalOpChain {
kind: And,
expressions: [
BinOp {
location: 40..46,
name: Eq,
left: UInt {
location: 40..41,
value: "1",
base: Decimal {
numeric_underscore: false,
},
},
right: UInt {
location: 45..46,
value: "2",
base: Decimal {
numeric_underscore: false,
},
},
},
Var {
location: 52..61,
name: "something",
},
],
location: 30..66,
},
],
location: 0..69,
}

View File

@ -6,13 +6,14 @@ Fn {
location: 0..28,
fn_style: Plain,
arguments: [
Arg {
arg_name: Named {
name: "a",
label: "a",
location: 4..5,
is_validator_param: false,
},
UntypedArg {
by: ByName(
Named {
name: "a",
label: "a",
location: 4..5,
},
),
location: 4..10,
annotation: Some(
Constructor {
@ -22,7 +23,8 @@ Fn {
arguments: [],
},
),
tipo: (),
doc: None,
is_validator_param: false,
},
],
body: BinOp {

View File

@ -0,0 +1,55 @@
---
source: crates/aiken-lang/src/parser/expr/anonymous_function.rs
description: "Code:\n\nfn (Foo { my_field }) { my_field * 2 }"
---
Fn {
location: 0..38,
fn_style: Plain,
arguments: [
UntypedArg {
by: ByPattern(
Constructor {
is_record: true,
location: 4..20,
name: "Foo",
arguments: [
CallArg {
label: Some(
"my_field",
),
location: 10..18,
value: Var {
location: 10..18,
name: "my_field",
},
},
],
module: None,
constructor: (),
spread_location: None,
tipo: (),
},
),
location: 4..20,
annotation: None,
doc: None,
is_validator_param: false,
},
],
body: BinOp {
location: 24..36,
name: MultInt,
left: Var {
location: 24..32,
name: "my_field",
},
right: UInt {
location: 35..36,
value: "2",
base: Decimal {
numeric_underscore: false,
},
},
},
return_annotation: None,
}

View File

@ -0,0 +1,58 @@
---
source: crates/aiken-lang/src/parser/expr/anonymous_function.rs
description: "Code:\n\nfn (Foo { my_field, .. } as x) { my_field * my_other_field }"
---
Fn {
location: 0..60,
fn_style: Plain,
arguments: [
UntypedArg {
by: ByPattern(
Assign {
name: "x",
location: 4..29,
pattern: Constructor {
is_record: true,
location: 4..24,
name: "Foo",
arguments: [
CallArg {
label: Some(
"my_field",
),
location: 10..18,
value: Var {
location: 10..18,
name: "my_field",
},
},
],
module: None,
constructor: (),
spread_location: Some(
20..22,
),
tipo: (),
},
},
),
location: 4..29,
annotation: None,
doc: None,
is_validator_param: false,
},
],
body: BinOp {
location: 33..58,
name: MultInt,
left: Var {
location: 33..41,
name: "my_field",
},
right: Var {
location: 44..58,
name: "my_other_field",
},
},
return_annotation: None,
}

View File

@ -0,0 +1,62 @@
---
source: crates/aiken-lang/src/parser/expr/anonymous_function.rs
description: "Code:\n\nfn (Foo { my_field } : Foo) { my_field * 2 }"
---
Fn {
location: 0..44,
fn_style: Plain,
arguments: [
UntypedArg {
by: ByPattern(
Constructor {
is_record: true,
location: 4..20,
name: "Foo",
arguments: [
CallArg {
label: Some(
"my_field",
),
location: 10..18,
value: Var {
location: 10..18,
name: "my_field",
},
},
],
module: None,
constructor: (),
spread_location: None,
tipo: (),
},
),
location: 4..26,
annotation: Some(
Constructor {
location: 23..26,
module: None,
name: "Foo",
arguments: [],
},
),
doc: None,
is_validator_param: false,
},
],
body: BinOp {
location: 30..42,
name: MultInt,
left: Var {
location: 30..38,
name: "my_field",
},
right: UInt {
location: 41..42,
value: "2",
base: Decimal {
numeric_underscore: false,
},
},
},
return_annotation: None,
}

View File

@ -0,0 +1,21 @@
---
source: crates/aiken-lang/src/parser/expr/pair.rs
description: "Code:\n\nPair(1, 2)"
---
Pair {
location: 4..10,
fst: UInt {
location: 5..6,
value: "1",
base: Decimal {
numeric_underscore: false,
},
},
snd: UInt {
location: 8..9,
value: "2",
base: Decimal {
numeric_underscore: false,
},
},
}

Some files were not shown because too many files have changed in this diff Show More