Showing preview only (8,958K chars total). Download the full file or copy to clipboard to get everything.
Repository: VineLang/vine
Branch: main
Commit: 6fe363a55f66
Files: 746
Total size: 8.4 MB
Directory structure:
gitextract_yoww9v3l/
├── .gitattributes
├── .github/
│ └── workflows/
│ ├── change-base.yml
│ ├── checks.yml
│ ├── docs.yml
│ ├── integration.yml
│ └── issues.yml
├── .gitignore
├── .vscode/
│ └── settings.json
├── Cargo.toml
├── LICENSE-APACHE
├── LICENSE-MIT
├── README.md
├── cli/
│ ├── Cargo.toml
│ ├── cli.nix
│ └── src/
│ ├── bin/
│ │ ├── ivy.rs
│ │ └── vine.rs
│ ├── common.rs
│ ├── ivy_cli.rs
│ ├── lib.rs
│ └── vine_cli.rs
├── cspell.json
├── docs/
│ ├── .gitignore
│ ├── compiler/
│ │ ├── architecture.typ
│ │ ├── compiler.typ
│ │ └── sfg.typ
│ ├── docs.nix
│ ├── docs.typ
│ ├── features/
│ │ ├── conditions.typ
│ │ ├── control_flow/
│ │ │ ├── blocks.typ
│ │ │ ├── conditionals.typ
│ │ │ ├── control_flow.typ
│ │ │ └── loops.typ
│ │ ├── features.typ
│ │ ├── inverse.typ
│ │ ├── io.typ
│ │ ├── methods.typ
│ │ ├── modules.typ
│ │ ├── patterns.typ
│ │ ├── references.typ
│ │ ├── root.typ
│ │ ├── traits/
│ │ │ ├── fork_drop.typ
│ │ │ ├── intro.typ
│ │ │ ├── standard.typ
│ │ │ └── traits.typ
│ │ ├── types/
│ │ │ ├── composite.typ
│ │ │ ├── enums.typ
│ │ │ ├── primitives.typ
│ │ │ ├── standard.typ
│ │ │ ├── structs.typ
│ │ │ └── types.typ
│ │ ├── usual.typ
│ │ ├── values_spaces_places.typ
│ │ └── variables.typ
│ ├── img.typ
│ ├── ivy_ivm/
│ │ ├── extrinsics.typ
│ │ ├── interaction_system.typ
│ │ ├── ivm.typ
│ │ ├── ivy.typ
│ │ ├── ivy_ivm.typ
│ │ └── statistics.typ
│ ├── lib.typ
│ ├── main.typ
│ ├── root.css
│ ├── starting/
│ │ ├── hello_world.typ
│ │ ├── installation.typ
│ │ └── starting.typ
│ ├── theme.css
│ └── tooling/
│ ├── cli.typ
│ ├── debug.typ
│ ├── editor.typ
│ ├── repl.typ
│ └── tooling.typ
├── dprint.json
├── flake.nix
├── ivm/
│ ├── Cargo.toml
│ └── src/
│ ├── addr.rs
│ ├── allocator.rs
│ ├── ext.rs
│ ├── flags.rs
│ ├── global.rs
│ ├── heap.rs
│ ├── instruction.rs
│ ├── interact.rs
│ ├── ivm.rs
│ ├── lib.rs
│ ├── parallel.rs
│ ├── port.rs
│ ├── stats.rs
│ ├── wire.rs
│ └── word.rs
├── ivy/
│ ├── Cargo.toml
│ ├── examples/
│ │ ├── cat.iv
│ │ ├── fib_repl.iv
│ │ ├── fizzbuzz.iv
│ │ └── hihi.iv
│ └── src/
│ ├── ast.rs
│ ├── host/
│ │ ├── ext.rs
│ │ ├── readback.rs
│ │ └── serialize.rs
│ ├── host.rs
│ ├── lexer.rs
│ ├── lib.rs
│ ├── optimize/
│ │ ├── eta_reduce.rs
│ │ ├── inline_globals.rs
│ │ ├── inline_vars.rs
│ │ ├── pre_reduce.rs
│ │ └── prune.rs
│ ├── optimize.rs
│ ├── parser.rs
│ └── repl.rs
├── lsp/
│ ├── Cargo.toml
│ ├── client/
│ │ ├── .gitignore
│ │ ├── .vscodeignore
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── extension.ts
│ │ │ ├── ivy-config.json
│ │ │ ├── ivy-grammar.json
│ │ │ ├── vine-config.json
│ │ │ └── vine-grammar.json
│ │ └── tsconfig.json
│ ├── grammars.nix
│ ├── src/
│ │ └── lib.rs
│ ├── tree-sitter-ivy/
│ │ ├── .gitignore
│ │ ├── grammar.js
│ │ ├── package.json
│ │ ├── queries/
│ │ │ ├── highlights.scm
│ │ │ └── textobjects.scm
│ │ ├── test.nu
│ │ └── tree-sitter.json
│ └── tree-sitter-vine/
│ ├── .gitignore
│ ├── grammar.js
│ ├── package.json
│ ├── queries/
│ │ ├── highlights.scm
│ │ ├── injections.scm
│ │ └── textobjects.scm
│ ├── test.nu
│ └── tree-sitter.json
├── root/
│ ├── Ext.vi
│ ├── IO/
│ │ ├── File.vi
│ │ └── IO.vi
│ ├── data/
│ │ ├── Array.vi
│ │ ├── Heap.vi
│ │ ├── Iterator.vi
│ │ ├── List.vi
│ │ ├── Map.vi
│ │ ├── Set.vi
│ │ └── data.vi
│ ├── debug/
│ │ ├── Show.vi
│ │ └── debug.vi
│ ├── derive.vi
│ ├── logical/
│ │ ├── Bool.vi
│ │ ├── Default.vi
│ │ ├── Nullable.vi
│ │ ├── Option.vi
│ │ ├── Result.vi
│ │ └── logical.vi
│ ├── numeric/
│ │ ├── F32/
│ │ │ └── F32.vi
│ │ ├── F64/
│ │ │ ├── F64.vi
│ │ │ ├── common.vi
│ │ │ ├── exp.vi
│ │ │ └── ln.vi
│ │ ├── Float/
│ │ │ ├── Float.vi
│ │ │ ├── parse.vi
│ │ │ └── to_string.vi
│ │ ├── I32.vi
│ │ ├── Int.vi
│ │ ├── N32.vi
│ │ ├── N64.vi
│ │ ├── Nat/
│ │ │ ├── Nat.vi
│ │ │ └── div_rem.vi
│ │ └── numeric.vi
│ ├── ops/
│ │ ├── Index.vi
│ │ ├── Range.vi
│ │ ├── arithmetic.vi
│ │ ├── bitwise.vi
│ │ ├── comparison.vi
│ │ ├── elementwise.vi
│ │ ├── flex.vi
│ │ └── ops.vi
│ ├── prelude.vi
│ ├── rng/
│ │ ├── Pcg32.vi
│ │ └── rng.vi
│ ├── root.vi
│ ├── unicode/
│ │ ├── Char.vi
│ │ ├── String.vi
│ │ └── unicode.vi
│ └── util.vi
├── rust-toolchain.toml
├── rustfmt.toml
├── style.nix
├── tests/
│ ├── aoc_2024/
│ │ ├── README.md
│ │ ├── day_01.vi
│ │ ├── day_02.vi
│ │ ├── day_03.vi
│ │ ├── day_04.vi
│ │ ├── day_05.vi
│ │ ├── day_06.vi
│ │ ├── day_07.vi
│ │ ├── day_08.vi
│ │ ├── day_09.vi
│ │ ├── day_10.vi
│ │ ├── day_11.vi
│ │ ├── day_12.vi
│ │ ├── day_13.vi
│ │ ├── day_14.vi
│ │ ├── day_15.vi
│ │ ├── day_16.vi
│ │ ├── day_17.vi
│ │ ├── day_18.vi
│ │ ├── day_19.vi
│ │ ├── day_20.vi
│ │ ├── day_21.vi
│ │ ├── day_22.vi
│ │ ├── day_23.vi
│ │ ├── day_24.vi
│ │ ├── day_25.vi
│ │ └── input/
│ │ ├── day_01
│ │ ├── day_02
│ │ ├── day_03
│ │ ├── day_04
│ │ ├── day_05
│ │ ├── day_06
│ │ ├── day_07
│ │ ├── day_08
│ │ ├── day_09
│ │ ├── day_10
│ │ ├── day_11
│ │ ├── day_12
│ │ ├── day_13
│ │ ├── day_14
│ │ ├── day_15
│ │ ├── day_16
│ │ ├── day_17
│ │ ├── day_18
│ │ ├── day_19
│ │ ├── day_20
│ │ ├── day_21
│ │ ├── day_22
│ │ ├── day_23
│ │ ├── day_24
│ │ └── day_25
│ ├── compile/
│ │ ├── opaque_ext_fn.vi
│ │ └── pre_reduce_opaque_fn.vi
│ ├── examples/
│ │ ├── cat
│ │ ├── fib
│ │ ├── fib_repl
│ │ ├── fizzbuzz
│ │ ├── guessing_game
│ │ ├── hello_world
│ │ ├── mandelbrot
│ │ ├── mandelbrot_sixel
│ │ ├── mandelbrot_tga
│ │ ├── primeness
│ │ ├── stream_primes
│ │ ├── sub_min
│ │ └── sum_divisors
│ ├── fail/
│ │ ├── atypical.vi
│ │ ├── bad_try.vi
│ │ ├── continue_what.vi
│ │ ├── hallo_world.vi
│ │ ├── inconfigurable.vi
│ │ ├── inflexible.vi
│ │ ├── informal.vi
│ │ ├── is_not.vi
│ │ ├── loader/
│ │ │ ├── ambiguous/
│ │ │ │ └── ambiguous.vi
│ │ │ ├── ambiguous.vi
│ │ │ ├── dir/
│ │ │ │ ├── child.vi
│ │ │ │ └── dir.vi
│ │ │ ├── file.vi
│ │ │ ├── foo.vi
│ │ │ └── loader.vi
│ │ ├── occurs.vi
│ │ ├── opaque_private.vi
│ │ ├── other_dual.vi
│ │ ├── recursive_type_alias.vi
│ │ ├── unsafe_.vi
│ │ └── visibility.vi
│ ├── fmt/
│ │ ├── comment.vi
│ │ ├── match.vi
│ │ ├── objects.vi
│ │ └── uses.vi
│ ├── input/
│ │ ├── brainfuck
│ │ ├── cat
│ │ ├── empty
│ │ ├── fib_repl
│ │ ├── fib_repl_iv
│ │ ├── guessing_game
│ │ ├── lambda
│ │ └── life
│ ├── ivy/
│ │ ├── cat
│ │ ├── fib_repl
│ │ ├── fizzbuzz
│ │ └── hihi
│ ├── misc/
│ │ └── basic_test.vi
│ ├── programs/
│ │ ├── array_from_list.vi
│ │ ├── array_order.vi
│ │ ├── array_smoothsort.vi
│ │ ├── array_to_list.vi
│ │ ├── basic_diverge.vi
│ │ ├── brainfuck.vi
│ │ ├── break_result.vi
│ │ ├── centimanes.vi
│ │ ├── classify_primes.vi
│ │ ├── cli_args.vi
│ │ ├── cond_diverge.vi
│ │ ├── configurable.vi
│ │ ├── cubes.vi
│ │ ├── cyclist.vi
│ │ ├── div_by_zero.vi
│ │ ├── empty_loop.vi
│ │ ├── f32_ops.vi
│ │ ├── f32_roundabout.vi
│ │ ├── f64_no_inline.vi
│ │ ├── f64_ops.vi
│ │ ├── f64_roundabout.vi
│ │ ├── file.vi
│ │ ├── final_countdown.vi
│ │ ├── find_primes.vi
│ │ ├── heap.vi
│ │ ├── int_edges.vi
│ │ ├── invalid_extrinsics.vi
│ │ ├── inverse.vi
│ │ ├── iterator_party.vi
│ │ ├── lambda.vi
│ │ ├── lcs.vi
│ │ ├── life.vi
│ │ ├── log_brute.vi
│ │ ├── logic.vi
│ │ ├── loop_break_continue.vi
│ │ ├── loop_vi_loop.vi
│ │ ├── main.vi
│ │ ├── mandelbrot_f64.vi
│ │ ├── map_ops.vi
│ │ ├── map_test.vi
│ │ ├── maybe_set.vi
│ │ ├── n64_div_rem.vi
│ │ ├── nat_div.vi
│ │ ├── nat_edges.vi
│ │ ├── no_return.vi
│ │ ├── nothing_lasts_forever.vi
│ │ ├── opaque.vi
│ │ ├── option_party.vi
│ │ ├── par.vi
│ │ ├── pretty_div.vi
│ │ ├── primenesses.vi
│ │ ├── quine.vi
│ │ ├── regex.vi
│ │ ├── segmented_sieve.vi
│ │ ├── sieve.vi
│ │ ├── so_random.vi
│ │ ├── sort.vi
│ │ ├── specializations.vi
│ │ ├── square_case.vi
│ │ ├── the_greatest_show.vi
│ │ ├── tiny_f64.vi
│ │ ├── verbose_add.vi
│ │ └── when_break_continue.vi
│ ├── repl/
│ │ ├── F64_misc.vi
│ │ ├── N64.vi
│ │ ├── Nat.vi
│ │ ├── advanced_repl.vi
│ │ ├── basic_repl.vi
│ │ ├── distribute_inverse.vi
│ │ ├── elementwise.vi
│ │ ├── extrinsics.vi
│ │ ├── f32_to_string.vi
│ │ ├── heap.vi
│ │ ├── holes.vi
│ │ ├── i32_misc.vi
│ │ ├── index.vi
│ │ ├── misc.vi
│ │ ├── objects.vi
│ │ ├── parse_error.vi
│ │ ├── parse_floats.vi
│ │ ├── randomness.vi
│ │ ├── set.vi
│ │ ├── shadow.vi
│ │ ├── slice_and_dice.vi
│ │ └── string_ops.vi
│ ├── snaps/
│ │ ├── aoc_2024/
│ │ │ ├── day_01/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_02/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_03/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_04/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_05/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_06/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_07/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_08/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_09/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_10/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_11/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_12/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_13/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_14/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_15/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_16/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_17/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_18/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_19/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_20/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_21/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_22/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_23/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_24/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ └── day_25/
│ │ │ ├── output.txt
│ │ │ └── stats
│ │ ├── compile/
│ │ │ ├── opaque_ext_fn.iv
│ │ │ └── pre_reduce_opaque_fn.iv
│ │ ├── examples/
│ │ │ ├── cat/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── fib/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── fib_repl/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── fizzbuzz/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── guessing_game/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── hello_world/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── mandelbrot/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── mandelbrot_sixel/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── mandelbrot_tga/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── primeness/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── stream_primes/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── sub_min/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ └── sum_divisors/
│ │ │ ├── output.txt
│ │ │ └── stats
│ │ ├── fail/
│ │ │ ├── atypical.error
│ │ │ ├── bad_try.error
│ │ │ ├── continue_what.error
│ │ │ ├── hallo_world.error
│ │ │ ├── inconfigurable.error
│ │ │ ├── inflexible.error
│ │ │ ├── informal.error
│ │ │ ├── is_not.error
│ │ │ ├── loader.error
│ │ │ ├── occurs.error
│ │ │ ├── opaque_private.error
│ │ │ ├── other_dual.error
│ │ │ ├── recursive_type_alias.error
│ │ │ ├── unsafe_.error
│ │ │ └── visibility.error
│ │ ├── fmt/
│ │ │ ├── comment.fmt.vi
│ │ │ ├── match.fmt.vi
│ │ │ ├── objects.fmt.vi
│ │ │ └── uses.fmt.vi
│ │ ├── ivy/
│ │ │ ├── cat/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── fib_repl/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── fizzbuzz/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ └── hihi/
│ │ │ ├── output.txt
│ │ │ └── stats
│ │ ├── misc/
│ │ │ ├── basic_test/
│ │ │ │ └── stderr.txt
│ │ │ ├── missing_no.error
│ │ │ └── reconfigure.txt
│ │ ├── programs/
│ │ │ ├── array_from_list/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── array_order/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── array_smoothsort/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── array_to_list/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── basic_diverge/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── brainfuck/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── break_result/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── centimanes/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── classify_primes/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── cli_args/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── cond_diverge/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── configurable/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── cubes/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── cyclist/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── div_by_zero/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── empty_loop/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── f32_ops/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── f32_roundabout/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── f64_no_inline/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── f64_ops/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── f64_roundabout/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── file/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── final_countdown/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── find_primes/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── heap/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── int_edges/
│ │ │ │ └── stats
│ │ │ ├── invalid_extrinsics/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── inverse/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── iterator_party/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── lambda/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── lcs/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── life/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── log_brute/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── logic/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── loop_break_continue/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── loop_vi_loop/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── main/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── mandelbrot_f64/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── map_ops/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── map_test/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── maybe_set/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── n64_div_rem/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── nat_div/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── nat_edges/
│ │ │ │ └── stats
│ │ │ ├── no_return/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── nothing_lasts_forever/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── opaque/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── option_party/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── par/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── pretty_div/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── primenesses/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── quine/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── regex/
│ │ │ │ └── stats
│ │ │ ├── segmented_sieve/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── sieve/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── so_random/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── sort/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── specializations/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── square_case/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── the_greatest_show/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── tiny_f64/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── verbose_add/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ └── when_break_continue/
│ │ │ ├── output.txt
│ │ │ └── stats
│ │ └── repl/
│ │ ├── F64_misc.repl.vi
│ │ ├── N64.repl.vi
│ │ ├── Nat.repl.vi
│ │ ├── advanced_repl.repl.vi
│ │ ├── basic_repl.repl.vi
│ │ ├── distribute_inverse.repl.vi
│ │ ├── elementwise.repl.vi
│ │ ├── extrinsics.repl.vi
│ │ ├── f32_to_string.repl.vi
│ │ ├── heap.repl.vi
│ │ ├── holes.repl.vi
│ │ ├── i32_misc.repl.vi
│ │ ├── index.repl.vi
│ │ ├── misc.repl.vi
│ │ ├── objects.repl.vi
│ │ ├── parse_error.repl.vi
│ │ ├── parse_floats.repl.vi
│ │ ├── randomness.repl.vi
│ │ ├── set.repl.vi
│ │ ├── shadow.repl.vi
│ │ ├── slice_and_dice.repl.vi
│ │ └── string_ops.repl.vi
│ ├── snaps.nu
│ ├── tests.nix
│ └── verify/
│ ├── int_edges.py
│ ├── nat_edges.py
│ └── regex.rs
├── util/
│ ├── Cargo.toml
│ └── src/
│ ├── bicycle.rs
│ ├── idx.rs
│ ├── lexer.rs
│ ├── lib.rs
│ ├── multi_iter.rs
│ ├── nat.rs
│ ├── parser.rs
│ └── unwrap_vec.rs
└── vine/
├── Cargo.toml
├── examples/
│ ├── cat.vi
│ ├── fib.vi
│ ├── fib_repl.vi
│ ├── fizzbuzz.vi
│ ├── guessing_game.vi
│ ├── hello_world.vi
│ ├── mandelbrot.vi
│ ├── mandelbrot_sixel.vi
│ ├── mandelbrot_tga.vi
│ ├── primeness.vi
│ ├── stream_primes.vi
│ ├── sub_min.vi
│ └── sum_divisors.vi
└── src/
├── compiler.rs
├── components/
│ ├── analyzer/
│ │ └── effect.rs
│ ├── analyzer.rs
│ ├── charter.rs
│ ├── distiller.rs
│ ├── emitter.rs
│ ├── finder/
│ │ └── candidates.rs
│ ├── finder.rs
│ ├── lexer.rs
│ ├── loader.rs
│ ├── matcher.rs
│ ├── normalizer.rs
│ ├── parser.rs
│ ├── resolver.rs
│ ├── specializer.rs
│ └── synthesizer.rs
├── components.rs
├── features/
│ ├── annotation.rs
│ ├── assert.rs
│ ├── block.rs
│ ├── builtin.rs
│ ├── cast.rs
│ ├── coerce.rs
│ ├── composite.rs
│ ├── condition.rs
│ ├── const_.rs
│ ├── debug.rs
│ ├── do_.rs
│ ├── enum_.rs
│ ├── flex.rs
│ ├── fn_.rs
│ ├── for_.rs
│ ├── generics.rs
│ ├── hole.rs
│ ├── if_.rs
│ ├── impl_.rs
│ ├── import.rs
│ ├── index.rs
│ ├── inline_ivy.rs
│ ├── inverse.rs
│ ├── labels.rs
│ ├── let_.rs
│ ├── list.rs
│ ├── local.rs
│ ├── loop_.rs
│ ├── match_.rs
│ ├── method.rs
│ ├── mod_.rs
│ ├── numeric.rs
│ ├── ops.rs
│ ├── path.rs
│ ├── place.rs
│ ├── range.rs
│ ├── reference.rs
│ ├── string.rs
│ ├── struct_.rs
│ ├── trait_.rs
│ ├── try_.rs
│ ├── type_.rs
│ ├── union.rs
│ ├── when.rs
│ └── while_.rs
├── features.rs
├── lib.rs
├── structures/
│ ├── annotations.rs
│ ├── ast/
│ │ └── visit.rs
│ ├── ast.rs
│ ├── chart.rs
│ ├── checkpoint.rs
│ ├── diag.rs
│ ├── resolutions.rs
│ ├── signatures.rs
│ ├── specializations.rs
│ ├── template.rs
│ ├── tir.rs
│ ├── types.rs
│ └── vir.rs
├── structures.rs
├── tools/
│ ├── doc.rs
│ ├── fmt/
│ │ └── doc.rs
│ ├── fmt.rs
│ ├── repl/
│ │ ├── command.rs
│ │ └── show.rs
│ └── repl.rs
└── tools.rs
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitattributes
================================================
*.vi linguist-language=rust
================================================
FILE: .github/workflows/change-base.yml
================================================
name: Change Base
on:
pull_request:
types: [opened]
branches: [main]
jobs:
change-base:
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@v3
- run: |
gh pr edit ${{ github.event.pull_request.number }} --base dev
env:
GH_TOKEN: ${{ github.token }}
================================================
FILE: .github/workflows/checks.yml
================================================
name: Checks
on:
pull_request:
merge_group:
push:
branches:
- main
jobs:
checks:
runs-on: self-hosted
timeout-minutes: 20
steps:
- uses: actions/checkout@v3
- run: nix flake check -L
================================================
FILE: .github/workflows/docs.yml
================================================
name: Docs
on:
push:
permissions:
contents: read
pages: write
id-token: write
jobs:
build:
runs-on: self-hosted
timeout-minutes: 10
steps:
- uses: actions/checkout@v3
- run: nix build .#docs -L
- run: nix run nixpkgs#wrangler -- pages deploy result --project-name vine-dev --branch ${{ github.ref_name }}
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
- uses: actions/configure-pages@v3
if: github.ref_name == 'main'
- uses: actions/upload-pages-artifact@v3
if: github.ref_name == 'main'
with:
path: "result"
- id: deployment
if: github.ref_name == 'main'
uses: actions/deploy-pages@v4
================================================
FILE: .github/workflows/integration.yml
================================================
name: Integration
on:
workflow_dispatch:
push:
branches:
- dev
jobs:
integration-test:
runs-on: self-hosted
timeout-minutes: 15
permissions: read-all
strategy:
fail-fast: false
matrix:
command:
- build github:nilscrm/liana#checks.x86_64-linux.example
- flake check github:nilscrm/sat-vi
- flake check github:nilscrm/vine-page-rank
- flake check github:nilscrm/quant-vi
steps:
- uses: actions/checkout@v3
- run: nix ${{ matrix.command }} --override-input vine . -L
integration-tests:
needs: [integration-test]
if: always()
runs-on: ubuntu-latest
steps:
- name: Aggregate integration test results
run: |
[[ "${{ needs.integration-test.result }}" == "success" ]]
mainline:
needs: [integration-tests]
if: ${{ github.ref_name == 'dev' }}
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: write
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- run: |
git fetch origin main
if ! git merge-base --is-ancestor @ origin/main; then
git push origin `git rev-parse @`:main
fi
notify:
needs: [mainline]
if: ${{ always() && github.ref_name == 'dev' }}
runs-on: ubuntu-latest
permissions:
contents: read
issues: write
steps:
- uses: actions/checkout@v3
- name: open issue
if: ${{ needs.mainline.result == 'skipped' || needs.mainline.result == 'failure' }}
run: |
gh issue reopen 484
gh issue edit 484 --add-assignee ${{ github.event.sender.login }}
env:
GH_TOKEN: ${{ github.token }}
- name: close issue
if: ${{ needs.mainline.result == 'success' }}
run: |
git fetch origin main
if [[ `git rev-parse dev` == `git rev-parse origin/main` ]]; then
gh issue close 484
gh issue edit 484 --remove-assignee @me,`gh issue view 484 --json assignees --jq '[.assignees.[].login] | join(",")'`
fi
env:
GH_TOKEN: ${{ github.token }}
================================================
FILE: .github/workflows/issues.yml
================================================
name: Close linked issues on PR merge
on:
pull_request:
types: [closed]
branches: [main, dev]
jobs:
close-linked-issues:
runs-on: ubuntu-latest
timeout-minutes: 10
permissions: write-all
if: github.event.pull_request.merged
steps:
- uses: actions/checkout@v3
- uses: hustcer/setup-nu@v3
- name: close linked issues
shell: nu {0}
run: |
let number = ${{ github.event.pull_request.number }}
let body = gh pr view $number --json body | from json | get body
let issues = $body | parse --regex '(?i)(?:(?:clos|resolv)e[sd]?|fix(?:e[sd])?):?\s*#(?P<issue>\d+)'
let comment = $"- #($number)"
$issues | each { gh issue close $in.issue --reason completed --comment $comment } | ignore
env:
GH_TOKEN: ${{ github.token }}
================================================
FILE: .gitignore
================================================
.DS_Store
target
tests/snaps/**/compiled.iv
tests/snaps/**/timing.txt
# Nix build outputs
result
================================================
FILE: .vscode/settings.json
================================================
{
"[json]": {
"editor.defaultFormatter": "dprint.dprint"
},
"[jsonc]": {
"editor.defaultFormatter": "dprint.dprint"
},
"[markdown]": {
"editor.defaultFormatter": "dprint.dprint"
},
"[rust]": {
"editor.defaultFormatter": "rust-lang.rust-analyzer"
},
"[toml]": {
"editor.defaultFormatter": "dprint.dprint"
},
"[yaml]": {
"editor.defaultFormatter": "dprint.dprint"
},
"vine.cli": ["cargo", "run", "--bin", "vine", "--release", "--"],
"vine.lspOptions": ["--no-root"],
"vine.entrypoints": [
"vine/examples/*.vi",
"tests/programs/*.vi",
"tests/aoc_2024/*.vi",
"tests/compile/*.vi",
"tests/misc/*.vi",
"root/"
],
"rust-analyzer.check.command": "clippy",
"editor.formatOnSave": true,
"editor.tabSize": 2
}
================================================
FILE: Cargo.toml
================================================
[workspace]
resolver = "2"
members = ["cli", "ivm", "ivy", "lsp", "util", "vine"]
================================================
FILE: LICENSE-APACHE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
================================================
FILE: LICENSE-MIT
================================================
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
================================================
FILE: README.md
================================================
<h1 align="center">
<img src="./docs/img/favicon-1024.png" width="128" align="center">
<p>The Vine Programming Language</p>
</h1>
Vine is an experimental new programming language based on interaction nets.
Vine is a multi-paradigm language, featuring seamless interop between functional
and imperative patterns. See [`vine/examples/`](./vine/examples/) for examples
of Vine.
```sh
cargo run -r --bin vine run vine/examples/$NAME.vi
```
If you're curious to learn more, take a look at the
[Vine Docs](https://vine.dev/docs/), and join the
[Vine Discord server](https://discord.gg/bgUPV8KjDv).
## Sub-Projects
Vine compiles to [Ivy](./ivy/), a low-level interaction-combinator programming
language.
Ivy code runs on the [IVM](./ivm/), a performant interaction combinator runtime.
================================================
FILE: cli/Cargo.toml
================================================
[package]
name = "vine-cli"
version = "0.0.0"
edition = "2024"
[dependencies]
anyhow = "1.0.87"
clap = { version = "4.5.17", features = ["derive", "env"] }
clap_complete = "4.5.52"
glob = "0.3.3"
notify = "8.2.0"
rustyline = "14.0.0"
ivm = { path = "../ivm" }
ivy = { path = "../ivy" }
vine = { path = "../vine", optional = true }
vine-lsp = { path = "../lsp", optional = true }
vine-util = { path = "../util" }
[lints.clippy]
absolute_paths = "warn"
[features]
vine = ["dep:vine", "dep:vine-lsp"]
default = ["vine"]
[[bin]]
name = "vine"
required-features = ["vine"]
================================================
FILE: cli/cli.nix
================================================
{
pkgs,
craneLib,
}:
let
self.internal.ivyConfig = {
pname = "ivy";
version = "0.0.0";
src = pkgs.lib.fileset.toSource {
root = ./..;
fileset = pkgs.lib.fileset.unions [
../Cargo.toml
../util
../ivm
../ivy
../cli
../vine/Cargo.toml
../lsp/Cargo.toml
];
};
cargoLock = ../Cargo.lock;
preBuild = ''
mkdir -p vine/src lsp/src
touch vine/src/lib.rs lsp/src/lib.rs
'';
cargoExtraArgs = "--no-default-features --bin ivy";
doCheck = false;
cargoArtifacts = craneLib.buildDepsOnly self.internal.ivyConfig;
};
self.packages.ivy = craneLib.buildPackage self.internal.ivyConfig;
self.internal.vineConfig = {
pname = "vine";
version = "0.0.0";
src = pkgs.lib.fileset.toSource {
root = ./..;
fileset = pkgs.lib.fileset.unions [
../Cargo.toml
../util
../ivm
../ivy
../vine/Cargo.toml
../vine/src
../lsp
../cli
];
};
cargoLock = ../Cargo.lock;
outputHashes = {
"git+https://github.com/tjjfvi/class?rev=99738e6#99738e67dd8fb3b97d65e6fc59b92f04c11519a4" =
"sha256-ye8DqeDRXsNpTWpGGlvWxSSc1AiXOLud99dHpB/VhZg=";
};
cargoExtraArgs = "--bin vine";
VINE_ROOT_PATH = "../lib/root";
doCheck = false;
doInstallCargoArtifacts = true;
cargoArtifacts = craneLib.buildDepsOnly self.internal.vineConfig;
};
self.packages.vine-no-root = craneLib.buildPackage self.internal.vineConfig;
self.checks.clippy = craneLib.cargoClippy self.internal.vineConfig;
self.packages.vine = pkgs.runCommand "vine" { } ''
mkdir $out
cp -r ${self.packages.vine-no-root}/* $out
mkdir $out/lib
cp -r ${../root} $out/lib/root
'';
in
self
================================================
FILE: cli/src/bin/ivy.rs
================================================
use anyhow::Result;
use vine_cli::IvyCommand;
fn main() -> Result<()> {
IvyCommand::execute()
}
================================================
FILE: cli/src/bin/vine.rs
================================================
use anyhow::Result;
use vine_cli::VineCommand;
fn main() -> Result<()> {
VineCommand::execute()
}
================================================
FILE: cli/src/common.rs
================================================
use std::{
io::{self, Read, Write},
process::exit,
sync::{Mutex, MutexGuard},
};
use clap::Args;
use ivm::{
IVM,
ext::Extrinsics,
flags::Flags,
heap::Heap,
port::{Port, Tag},
stats::Stats,
};
use ivy::{ast::Nets, host::Host, optimize::Optimizer};
#[derive(Debug, Default, Args)]
pub struct Optimizations {
#[arg(long)]
no_opt: bool,
}
impl Optimizations {
pub fn apply(&self, nets: &mut Nets, entrypoints: &[String]) {
if !self.no_opt {
Optimizer::default().optimize(nets, entrypoints)
}
}
}
#[derive(Debug, Args)]
pub struct RunArgs {
#[arg(long)]
no_stats: bool,
#[arg(long)]
no_perf: bool,
#[arg(long, short, default_value = "0")]
workers: usize,
#[arg(long, alias = "depth", short = 'd')]
breadth_first: bool,
#[arg(long, short = 'H', value_parser = parse_size)]
heap: Option<usize>,
pub args: Vec<String>,
}
impl RunArgs {
/// Run the nets capturing any stdout and stderr.
pub fn output(&self, nets: &Nets) -> (RunResult, Vec<u8>) {
pub struct SharedWriter<'a>(pub MutexGuard<'a, Vec<u8>>);
impl Write for SharedWriter<'_> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.0.extend_from_slice(buf);
Ok(buf.len())
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
let input: &[u8] = &[];
let output = Mutex::default();
let result = self.run(nets, || input, || SharedWriter(output.lock().unwrap()));
(result, output.into_inner().unwrap())
}
/// Run the nets forwarding stdout and stderr, exiting if any errors occur.
pub fn check(&self, nets: &Nets, debug_hint: bool) {
self.run(nets, io::stdin, io::stdout).check(debug_hint);
}
pub fn run<R: Read, W: Write>(
&self,
nets: &Nets,
io_input_fn: impl Copy + Fn() -> R + Send + Sync,
io_output_fn: impl Copy + Fn() -> W + Send + Sync,
) -> RunResult {
let mut host = &mut Host::default();
let heap = match self.heap {
Some(size) => Heap::with_size(size).expect("heap allocation failed"),
None => Heap::new(),
};
let mut extrinsics = Extrinsics::default();
host.register_default_extrinsics(&mut extrinsics);
host.register_runtime_extrinsics(&mut extrinsics, &self.args, io_input_fn, io_output_fn);
host.insert_nets(nets);
let main = host.get("::").expect("missing main");
let mut ivm = IVM::new(&heap, &extrinsics);
let node = unsafe { ivm.new_node(Tag::Comb, Host::label_to_u16("x", &mut host.comb_labels)) };
ivm.link_wire(node.1, Port::new_ext_val(host.new_io()));
ivm.link(Port::new_global(main), node.0);
if self.breadth_first {
ivm.normalize_breadth_first();
} else if self.workers > 0 {
ivm.normalize_parallel(self.workers)
} else {
ivm.normalize();
}
let out = ivm.follow(Port::new_wire(node.2));
if self.no_perf {
ivm.stats.clear_perf();
}
RunResult {
stats: (!self.no_stats).then_some(ivm.stats),
flags: ivm.flags,
no_io: out.tag() != Tag::ExtVal || unsafe { out.as_ext_val() }.bits() != host.new_io().bits(),
vicious: ivm.stats.mem_free < ivm.stats.mem_alloc,
}
}
}
pub struct RunResult {
pub stats: Option<Stats>,
pub flags: Flags,
pub no_io: bool,
pub vicious: bool,
}
impl RunResult {
pub fn check(&self, debug_hint: bool) {
if self.no_io {
eprintln!("\nError: the net did not return its `IO` handle");
if debug_hint {
eprintln!(" hint: try running the program in `--debug` mode to see error messages");
}
}
if self.vicious {
eprintln!("\nError: the net created a vicious circle");
}
if self.flags.ext_copy {
eprintln!("\nError: a linear extrinsic was copied");
}
if self.flags.ext_erase {
eprintln!("\nError: a linear extrinsic was erased");
}
if self.flags.ext_generic {
eprintln!("\nError: an extrinsic function encountered an unspecified error");
}
if let Some(stats) = &self.stats {
eprintln!("{}", stats);
}
if !self.success() {
exit(1);
}
}
pub fn success(&self) -> bool {
!self.no_io && !self.vicious && self.flags.success()
}
}
fn parse_size(size: &str) -> anyhow::Result<usize> {
if let Some(size) = size.strip_suffix("K") {
Ok(size.parse::<usize>()? << 10)
} else if let Some(size) = size.strip_suffix("M") {
Ok(size.parse::<usize>()? << 20)
} else if let Some(size) = size.strip_suffix("G") {
Ok(size.parse::<usize>()? << 30)
} else {
Ok(size.parse::<usize>()?)
}
}
================================================
FILE: cli/src/ivy_cli.rs
================================================
use std::{fs, io, path::PathBuf};
use anyhow::Result;
use clap::{Args, CommandFactory};
use clap_complete::generate;
use rustyline::DefaultEditor;
use ivm::{IVM, ext::Extrinsics, heap::Heap};
use ivy::{host::Host, parser::Parser, repl::Repl};
use crate::{Optimizations, RunArgs};
#[derive(Debug, clap::Parser)]
#[command(name = "ivy", version, about = "Ivy's CLI", propagate_version = true)]
pub enum IvyCommand {
#[command(about = "Run an Ivy program")]
Run(IvyRunCommand),
#[command(about = "Optimize an Ivy program")]
Optimize(IvyOptimizeCommand),
Repl(IvyReplCommand),
#[command(about = "Generate shell completion scripts")]
Completion(IvyCompletionCommand),
}
impl IvyCommand {
pub fn execute() -> Result<()> {
match <Self as clap::Parser>::parse() {
IvyCommand::Run(run) => run.execute(),
IvyCommand::Optimize(optimize) => optimize.execute(),
IvyCommand::Repl(repl) => repl.execute(),
IvyCommand::Completion(completion) => completion.execute(),
}
}
}
#[derive(Debug, Args)]
pub struct IvyRunCommand {
#[arg()]
src: PathBuf,
#[command(flatten)]
run_args: RunArgs,
}
impl IvyRunCommand {
pub fn execute(self) -> Result<()> {
let src_contents = fs::read_to_string(self.src.clone())?;
let nets = Parser::parse(&src_contents).unwrap();
self.run_args.check(&nets, false);
Ok(())
}
}
#[derive(Debug, Args)]
pub struct IvyOptimizeCommand {
#[arg(index = 1, default_value = "main.iv")]
src: String,
#[arg(name = "out", long, short = 'o')]
maybe_out: String,
#[command(flatten)]
optimizations: Optimizations,
}
impl IvyOptimizeCommand {
pub fn execute(&self) -> Result<()> {
unimplemented!()
}
}
#[derive(Debug, Args)]
pub struct IvyReplCommand {
#[arg()]
src: Option<PathBuf>,
#[command(flatten)]
run_args: RunArgs,
}
impl IvyReplCommand {
pub fn execute(self) -> Result<()> {
let src = self.src.map(fs::read_to_string).unwrap_or(Ok(String::new()))?;
let nets = Parser::parse(&src).unwrap();
let mut host = &mut Host::default();
let heap = Heap::new();
let mut extrinsics = Extrinsics::default();
host.register_default_extrinsics(&mut extrinsics);
host.register_runtime_extrinsics(&mut extrinsics, &self.run_args.args, io::stdin, io::stdout);
host.insert_nets(&nets);
let mut ivm = IVM::new(&heap, &extrinsics);
let mut repl = Repl::new(host, &mut ivm);
let mut rl = DefaultEditor::new()?;
loop {
print!("\n{repl}");
match rl.readline("> ") {
Ok(line) => {
_ = rl.add_history_entry(&line);
if let Err(err) = repl.exec(&line) {
println!("{err:?}");
}
}
Err(_) => break,
}
}
Ok(())
}
}
#[derive(Debug, Args)]
pub struct IvyCompletionCommand {
pub shell: clap_complete::Shell,
}
impl IvyCompletionCommand {
pub fn execute(self) -> Result<()> {
let shell = self.shell;
let mut cmd = IvyCommand::command();
let cmd_name = cmd.get_name().to_string();
generate(shell, &mut cmd, cmd_name, &mut io::stdout());
Ok(())
}
}
================================================
FILE: cli/src/lib.rs
================================================
mod common;
mod ivy_cli;
#[cfg(feature = "vine")]
mod vine_cli;
pub use common::*;
pub use ivy_cli::*;
#[cfg(feature = "vine")]
pub use vine_cli::*;
================================================
FILE: cli/src/vine_cli.rs
================================================
use std::{
collections::HashMap,
env,
ffi::OsStr,
fmt, fs,
io::{self, IsTerminal, Read, Write, stderr, stdin, stdout},
path::{Path, PathBuf},
process::exit,
sync::mpsc,
time::{Duration, Instant},
};
use anyhow::Result;
use clap::{
Args, CommandFactory, Parser,
builder::{TypedValueParser, ValueParserFactory},
error::ErrorKind,
};
use ivm::{IVM, ext::Extrinsics, heap::Heap};
use ivy::{ast::Nets, host::Host};
use notify::{RecommendedWatcher, RecursiveMode, Watcher};
use rustyline::DefaultEditor;
use vine::{
compiler::Compiler,
components::loader::{FileId, Loader, RealFS},
structures::{ast::Ident, resolutions::FragmentId},
tools::{doc::document, fmt::Formatter, repl::Repl},
};
use vine_lsp::lsp;
use vine_util::idx::IdxVec;
use super::{Optimizations, RunArgs};
#[derive(Debug, Parser)]
#[command(name = "vine", version, about = "Vine's CLI", propagate_version = true)]
pub enum VineCommand {
/// Build and run a Vine program
Run(VineRunCommand),
/// Compile a Vine program to Ivy
Build(VineBuildCommand),
Check(VineCheckCommand),
/// Run tests in a Vine program
Test(VineTestCommand),
Fmt(VineFmtCommand),
Repl(VineReplCommand),
Lsp(VineLspCommand),
/// Generate shell completion scripts
Completion(VineCompletionCommand),
#[command(hide = true)]
Doc(VineDocCommand),
}
impl VineCommand {
pub fn execute() -> Result<()> {
match Self::parse() {
VineCommand::Run(run) => run.execute(),
VineCommand::Build(build) => build.execute(),
VineCommand::Check(check) => check.execute(),
VineCommand::Test(test) => test.execute(),
VineCommand::Repl(repl) => repl.execute(),
VineCommand::Fmt(fmt) => fmt.execute(),
VineCommand::Lsp(lsp) => lsp.execute(),
VineCommand::Completion(completion) => completion.execute(),
VineCommand::Doc(doc) => doc.execute(),
}
}
}
#[derive(Debug, Args)]
pub struct LibArgs {
#[arg(long = "lib")]
libs: Vec<Source>,
#[arg(long)]
no_root: bool,
}
impl LibArgs {
fn initialize(mut self, compiler: &mut Compiler) -> IdxVec<FileId, PathBuf> {
if !self.no_root {
self.libs.push(root_source())
}
let mut file_paths = IdxVec::new();
let mut loader = Loader::new(compiler, RealFS, Some(&mut file_paths));
for lib in self.libs {
loader.load_mod(lib.name, lib.path);
}
file_paths
}
}
#[derive(Debug, Args)]
pub struct CheckArgs {
entrypoints: Vec<String>,
#[command(flatten)]
libs: LibArgs,
}
#[derive(Debug, Args)]
pub struct CompileArgs {
main: Source,
#[command(flatten)]
libs: LibArgs,
#[arg(long)]
debug: bool,
#[arg(long, num_args = 2, value_names = ["KEY", "VALUE"])]
config: Vec<String>,
}
impl CompileArgs {
fn initialize(self) -> Compiler {
let mut compiler = Compiler::new(self.debug, build_config(self.config));
self.libs.initialize(&mut compiler);
let mut loader = Loader::new(&mut compiler, RealFS, None);
loader.load_main_mod(self.main.name, self.main.path);
compiler
}
fn compile(self) -> (Nets, Compiler) {
let mut compiler = self.initialize();
let result = compiler.compile(());
eprint_diags(&compiler);
match result {
Ok(nets) => (nets, compiler),
Err(_) => {
exit(1);
}
}
}
}
fn root_source() -> Source {
let mut path = env::current_exe().unwrap();
path.pop();
let compile_time_root_path = option_env!("VINE_ROOT_PATH");
let runtime_root_path = env::var("VINE_ROOT_PATH").ok();
match runtime_root_path.as_deref().or(compile_time_root_path) {
Some(root_path) => {
path.push(root_path);
}
None => {
path.push(env!("CARGO_MANIFEST_DIR"));
path.pop();
path.push("root");
}
}
Source { name: Ident("root".into()), path }
}
#[derive(Debug, Args)]
pub struct VineRunCommand {
#[command(flatten)]
compile: CompileArgs,
#[command(flatten)]
optimizations: Optimizations,
#[command(flatten)]
run_args: RunArgs,
}
impl VineRunCommand {
pub fn execute(self) -> Result<()> {
let debug = self.compile.debug;
let (mut nets, _) = self.compile.compile();
self.optimizations.apply(&mut nets, &[]);
self.run_args.check(&nets, !debug);
Ok(())
}
}
#[derive(Debug, Args)]
pub struct VineTestCommand {
#[command(flatten)]
compile: CompileArgs,
#[command(flatten)]
optimizations: Optimizations,
#[command(flatten)]
run_args: RunArgs,
/// By default, stdout is captured when running test entrypoints. It is only
/// printed to stderr when an error occurs. Setting `no_capture` always prints
/// stdout to stderr after the test runs.
#[arg(short, long)]
no_capture: bool,
/// The test patterns to run. Test paths containing any of the provided
/// strings as substrings are run. If none are provided, all tests are run.
#[arg(long = "test")]
tests: Vec<String>,
}
impl VineTestCommand {
pub fn execute(mut self) -> Result<()> {
self.compile.debug = true;
let (mut nets, mut compiler) = self.compile.compile();
let tests = Self::matching_tests(&self.tests, &compiler);
eprintln!("running {} test(s)\n", tests.len());
let entrypoints: Vec<_> = tests.iter().map(|(_, id)| compiler.entrypoint_name(*id)).collect();
self.optimizations.apply(&mut nets, &entrypoints);
let Colors { reset, grey, bold, red, green, .. } = colors(&stderr());
let mut failed = false;
for (path, test_id) in tests {
compiler.insert_main_net(&mut nets, test_id);
eprint!("{grey}test{reset} {bold}{path}{reset} {grey}...{reset} ");
let (result, output) = self.run_args.output(&nets);
if result.success() {
eprintln!("{green}ok{reset}");
} else {
failed = true;
eprintln!("{red}FAILED{reset}");
}
if self.no_capture || !result.success() {
io::stderr().write_all(&output)?;
eprintln!();
}
}
if failed {
exit(1);
}
Ok(())
}
fn matching_tests(tests: &[String], compiler: &Compiler) -> Vec<(String, FragmentId)> {
compiler
.chart
.tests
.iter()
.filter_map(|&test_id| {
let def_id = compiler.chart.concrete_fns[test_id].def;
let path = &compiler.chart.defs[def_id].path;
(tests.is_empty() || tests.iter().any(|test| path.contains(test)))
.then(|| (path.to_owned(), compiler.resolutions.fns[test_id]))
})
.collect()
}
}
#[derive(Debug, Args)]
pub struct VineBuildCommand {
#[command(flatten)]
compile: CompileArgs,
#[command(flatten)]
optimizations: Optimizations,
#[arg(long)]
out: Option<PathBuf>,
}
impl VineBuildCommand {
pub fn execute(self) -> Result<()> {
let (mut nets, _) = self.compile.compile();
self.optimizations.apply(&mut nets, &[]);
if let Some(out) = self.out {
fs::write(out, nets.to_string())?;
} else {
println!("{nets}");
}
Ok(())
}
}
#[derive(Debug, Args)]
pub struct VineCheckCommand {
#[command(flatten)]
check: CheckArgs,
#[arg(long)]
watch: Vec<PathBuf>,
#[arg(long, default_value = "50")]
debounce: u64,
}
impl VineCheckCommand {
pub fn execute(self) -> Result<()> {
let mut compiler = Compiler::default();
self.check.libs.initialize(&mut compiler);
if compiler.check(()).is_err() {
eprint_diags(&compiler);
exit(1);
}
let checkpoint = compiler.checkpoint();
let Colors { reset, red, yellow, green, grey, .. } = colors(&stderr());
let mut check = move || {
let start = Instant::now();
compiler.revert(&checkpoint);
let mut loader = Loader::new(&mut compiler, RealFS, None);
for glob in &self.check.entrypoints {
for entry in glob::glob(glob).unwrap() {
let path = entry.unwrap();
if let Some(name) = RealFS::detect_name(&path) {
loader.load_mod(name, path);
}
}
}
_ = compiler.check(());
eprint_diags(&compiler);
let color = if !compiler.diags.errors.is_empty() {
red
} else if !compiler.diags.warnings.is_empty() {
yellow
} else {
green
};
eprintln!("{color}finished{reset} {grey}in{reset} {:?}", start.elapsed());
};
let clear = || {
eprint!("\x1b[H\x1b[3J\x1b[2J");
};
if self.watch.is_empty() {
check();
} else {
let (send, recv) = mpsc::channel();
let mut watcher = RecommendedWatcher::new(send, Default::default())?;
for path in self.watch {
watcher.watch(&path, RecursiveMode::Recursive)?;
}
let debounce = Duration::from_millis(self.debounce);
loop {
clear();
check();
_ = recv.recv();
while recv.recv_timeout(debounce).is_ok() {}
}
}
Ok(())
}
}
#[derive(Debug, Args)]
pub struct VineReplCommand {
#[command(flatten)]
libs: LibArgs,
#[arg(long)]
echo: bool,
#[arg(long)]
no_debug: bool,
args: Vec<String>,
#[arg(long, num_args = 2)]
config: Vec<String>,
}
impl VineReplCommand {
pub fn execute(self) -> Result<()> {
let host = &mut Host::default();
let heap = Heap::new();
let mut extrinsics = Extrinsics::default();
host.register_default_extrinsics(&mut extrinsics);
host.register_runtime_extrinsics(&mut extrinsics, &self.args, io::stdin, io::stdout);
let mut ivm = IVM::new(&heap, &extrinsics);
let mut compiler = Compiler::new(!self.no_debug, build_config(self.config));
self.libs.initialize(&mut compiler);
let mut repl = match Repl::new(host, &mut ivm, &mut compiler) {
Ok(repl) => repl,
Err(_) => {
eprint_diags(&compiler);
exit(1);
}
};
let mut rl = DefaultEditor::new()?;
loop {
println!();
if repl.options.show_scope {
repl.print_scope();
}
match rl.readline("> ") {
Ok(line) => {
if self.echo {
println!("> {line}");
}
_ = rl.add_history_entry(&line);
let checkpoint = repl.compiler.checkpoint();
if repl.exec(&line).is_err() {
repl.compiler.diags.warnings.clear();
print_diags(repl.compiler);
repl.compiler.revert(&checkpoint);
}
}
Err(_) => break,
}
}
Ok(())
}
}
#[derive(Debug, Args)]
pub struct VineFmtCommand {
files: Option<Vec<PathBuf>>,
}
impl VineFmtCommand {
pub fn execute(self) -> Result<()> {
let mut success = true;
if let Some(files) = self.files {
for path in files {
let src = fs::read_to_string(&path)?;
if let Some(out) = Self::fmt(path.display(), &src) {
fs::write(&path, out)?;
} else {
success = false;
}
}
} else {
let mut src = String::new();
stdin().read_to_string(&mut src)?;
if let Some(out) = Self::fmt("input", &src) {
print!("{out}");
} else {
success = false;
}
}
if !success {
exit(1);
}
Ok(())
}
fn fmt(path: impl fmt::Display, src: &str) -> Option<String> {
match Formatter::fmt(src) {
Ok(out) => Some(out),
Err(diag) => {
eprintln!("error formatting {path}:\n{diag}");
None
}
}
}
}
#[derive(Debug, Args)]
pub struct VineLspCommand {
#[command(flatten)]
check: CheckArgs,
}
impl VineLspCommand {
pub fn execute(self) -> Result<()> {
let mut compiler = Compiler::default();
let file_paths = self.check.libs.initialize(&mut compiler);
lsp(compiler, file_paths, self.check.entrypoints);
Ok(())
}
}
#[derive(Debug, Args)]
pub struct VineCompletionCommand {
pub shell: clap_complete::Shell,
}
impl VineCompletionCommand {
pub fn execute(self) -> Result<()> {
let shell = self.shell;
let mut cmd = VineCommand::command();
let cmd_name = cmd.get_name().to_string();
clap_complete::generate(shell, &mut cmd, cmd_name, &mut io::stdout());
Ok(())
}
}
#[derive(Debug, Args)]
pub struct VineDocCommand {
#[command(flatten)]
compile: CompileArgs,
output: PathBuf,
}
impl VineDocCommand {
pub fn execute(self) -> Result<()> {
let mut compiler = self.compile.initialize();
let result = compiler.compile(());
if document(&compiler, &self.output).is_err() {
eprint_diags(&compiler);
if result.is_ok() {
eprintln!("could not build docs");
}
exit(1);
}
Ok(())
}
}
fn eprint_diags(compiler: &Compiler) {
_print_diags(stderr(), compiler).unwrap();
}
fn print_diags(compiler: &Compiler) {
_print_diags(stdout(), compiler).unwrap();
}
fn _print_diags(mut w: impl io::Write + IsTerminal, compiler: &Compiler) -> io::Result<()> {
let Colors { reset, bold, underline, grey, red, yellow, .. } = colors(&w);
let errors = compiler.diags.errors.iter().map(|x| (red, "error", x));
let warnings = compiler.diags.warnings.iter().map(|x| (yellow, "warning", x));
for (color, severity, diag) in errors.chain(warnings) {
let Some(span) = diag.span() else { continue };
writeln!(w, "{color}{severity}{grey}:{reset} {bold}{diag}{reset}")?;
if let Some(span_str) = compiler.show_span(span) {
let file = &compiler.files[span.file];
let start = file.get_pos(span.start);
let end = file.get_pos(span.end);
let line_width = (end.line + 1).ilog10() as usize + 1;
writeln!(w, " {:>line_width$}{grey} @ {span_str}", "")?;
for line in start.line..=end.line {
let line_start = file.line_starts[line];
let line_end = file.line_starts.get(line + 1).copied().unwrap_or(file.src.len());
let line_str = &file.src[line_start..line_end];
let line_str =
line_str.strip_suffix("\r\n").or(line_str.strip_suffix("\n")).unwrap_or(line_str);
let start = if line == start.line { start.col } else { 0 };
let end = if line == end.line { end.col } else { line_str.len() };
writeln!(
w,
" {grey}{:>line_width$} |{reset} {}{color}{underline}{}{reset}{}",
line + 1,
&line_str[..start],
&line_str[start..end],
&line_str[end..],
)?;
}
}
writeln!(w,)?;
}
Ok(())
}
struct Colors {
reset: &'static str,
bold: &'static str,
underline: &'static str,
grey: &'static str,
red: &'static str,
yellow: &'static str,
green: &'static str,
}
fn colors(t: &impl IsTerminal) -> Colors {
if t.is_terminal() {
Colors {
reset: "\x1b[0m",
bold: "\x1b[1m",
underline: "\x1b[4m",
grey: "\x1b[2;39m",
red: "\x1b[91m",
yellow: "\x1b[33m",
green: "\x1b[32m",
}
} else {
Colors { reset: "", bold: "", underline: "", grey: "", red: "", yellow: "", green: "" }
}
}
#[derive(Clone, Debug)]
struct Source {
name: Ident,
path: PathBuf,
}
impl ValueParserFactory for Source {
type Parser = ParseSource;
fn value_parser() -> Self::Parser {
ParseSource
}
}
#[derive(Clone)]
struct ParseSource;
impl TypedValueParser for ParseSource {
type Value = Source;
fn parse_ref(
&self,
cmd: &clap::Command,
_: Option<&clap::Arg>,
value: &OsStr,
) -> Result<Self::Value, clap::Error> {
let bytes = value.as_encoded_bytes();
if let Some(index) = bytes.iter().position(|&x| x == b'=') {
let name = unsafe { OsStr::from_encoded_bytes_unchecked(&bytes[0..index]) };
let path = unsafe { OsStr::from_encoded_bytes_unchecked(&bytes[index + 1..]) };
if let Some(name) = name.to_str().and_then(Ident::new) {
Ok(Source { name, path: path.to_owned().into() })
} else {
Err(
clap::Error::raw(
ErrorKind::ValueValidation,
format!("invalid source name `{}`", name.display()),
)
.with_cmd(cmd),
)
}
} else {
let path: &Path = value.as_ref();
if let Some(name) = RealFS::detect_name(path) {
Ok(Source { name, path: path.to_owned() })
} else {
Err(
clap::Error::raw(
ErrorKind::ValueValidation,
format!("could not detect name for source with path `{}`", path.display()),
)
.with_cmd(cmd),
)
}
}
}
}
fn build_config(args: Vec<String>) -> HashMap<String, String> {
let mut args = args.into_iter();
let mut config = HashMap::new();
while args.len() != 0 {
config.insert(args.next().unwrap(), args.next().unwrap());
}
config
}
================================================
FILE: cspell.json
================================================
{
"$schema": "https://raw.githubusercontent.com/streetsidesoftware/cspell/main/cspell.schema.json",
"version": "0.2",
"words": [
"antinodes",
"brainfuck",
"centimanes",
"cmps",
"codepoint",
"combinators",
"condvar",
"cottus",
"divmod",
"eisel",
"elementwise",
"elif",
"extrinsics",
"frameless",
"freelist",
"furiosity",
"gyges",
"hexdigit",
"hfsq",
"horiz",
"ilog",
"impls",
"indexmap",
"itertools",
"lemire",
"miri",
"msun",
"muls",
"nats",
"nilary",
"nohash",
"nonoverlapping",
"nums",
"pathfind",
"peekable",
"polyformic",
"primenesses",
"readback",
"rels",
"Remez",
"repr",
"rfold",
"rotr",
"rustyline",
"scrutinee",
"specializer",
"subimpls",
"subpattern",
"tarjan's",
"tripterygium",
"underflows",
"uninit",
"unpark",
"unshifted",
"untuple",
"vecs",
"visitee",
"whnf",
"wilfordii",
"woah"
],
"dictionaries": [
"rust"
],
"files": [
"**/*.rs",
"**/*.md",
"**/*.vi",
"**/*.iv"
],
"ignorePaths": [
"tests/snaps",
"tests/programs/aoc_2024"
],
"ignoreRegExpList": [
"HexValues"
],
"useGitignore": true
}
================================================
FILE: docs/.gitignore
================================================
/deps
/root
*.pdf
*.html
================================================
FILE: docs/compiler/architecture.typ
================================================
#import "/lib.typ": *
= Architecture
The *cli* is the entrypoint to the compiler,
and collects all of the compilation options.
Most notably, it creates a list of _entrypoints_, paths to top-level modules
(the main module, the standard library, and any third-party libraries).
The *loader* then takes this list of entrypoints and queries the file system for their contents.
It invokes the _parser_ (which in turn invokes the _lexer_) to parse the file into an _AST_.
The loader then finds any files included in this AST, and recursively loads them.
Once this process is complete, the loader returns an AST node representing the entire compilation unit.
The *charter* then takes the AST and uses it to build the _chart_,
a directory of all of the _definitions_ in the program.
Definitions can have different kinds of _bindings_;
each definition can be bound to a value, pattern, type, trait, and/or implementation.
A definition can also have _members_;
e.g. a module will have a member for every item within it.
The chart also contains AST nodes for various kinds of items,
including constants, functions, traits, etc.
The *resolver* then passes over the chart,
resolving the AST nodes into _Typed Intermediate Representation_.
TIR is fully typed, so the resolver performs type inference and type checking.
TIR also refers to items by their ids, rather than paths,
so the resolver finds the referent of every path and reports any errors.
The *finder* is used by the resolver, as well as later stages,
to find methods and implementations when they are not explicitly specified.
It does this by iterating over all candidates and recursively finding implementation arguments for each.
The *distiller* then distills TIR into _Vine Intermediate Representation_.
VIR is much simpler than the AST or TIR;
compound expressions are distilled into sequential, atomic steps,
and high-level control-flow constructs are distilled into a @sfg[_Stacked Flow Graph_].
The distiller is also responsible for checking the forms of expressions and patterns,
inserting coercions,
and reporting resulting errors.
The *normalizer* then transforms the VIR to remove all of the _divergence_ from the SFG.
The *analyzer* then performs various analyses on the VIR,
including reachability analysis and dataflow analysis
(determining which locals are used by which _stages_, and how).
The *specializer* computes the set of _specializations_,
instantiations of a given _fragment_
(an item that emits code; i.e. a constant or function)
with a given set of implementation arguments.
The *emitter* then converts each specialization of the VIR
into a collection of _Ivy nets_, one for each stage.
================================================
FILE: docs/compiler/compiler.typ
================================================
#import "/lib.typ": *
= The Vine Compiler
An introduction to the internals of the Vine compiler. Here be dragons!
#let children = (
"architecture.typ",
"sfg.typ",
)
================================================
FILE: docs/compiler/sfg.typ
================================================
#import "/lib.typ": *
= Stacked Flow Graphs <sfg>
Many compilers use Control Flow Graphs (CFGs) to represent the control flow of a function.
The Vine compiler uses Stacked Flow Graphs (SFGs), an extension of CFGs,
a representation that allows for greater parallelization (among other benefits).
== Layers, Stages, and Steps
An SFG consists of a forest of _layers_.
Each layer is itself analogous to a CFG,
and consists of several _stages_
(analogous to basic blocks in a CFG).
Flow begins in the initial stage of the initial layer.
Flow can transfer between layers.
Once flow exits a layer, flow returns to the previous layer.
This is analogous to a call stack (hence the "stacked" flow graph).
Each stage contains a series of _steps_.
Flow visits each step in a stage sequentially.
A step can:
- _invoke_ a variable
- _transfer_ to another layer
- _diverge_ to an ancestor layer
- perform a primitive operation, such as constructing a tuple, or calling a function
After the last step of a stage,
if the stage has a _terminator_,
flow transfers to another stage in the same layer.
Otherwise, flow exits the layer.
== Interfaces and Transfers
Every stage has an _interface_.
Within a layer, multiple stages may have the same interface.
Every interface has one or more stages;
interfaces with exactly one stage are _unconditional_.
A transfers specifies a _target_ interface.
If there are multiple stages with that interface,
the transfer must supply a _payload_ which will determine which stage is transferred to.
The interface specifies the type of this payload, and how it is used.
For example, a boolean interface has two stages.
One stage is associated with a payload of #vi[`true`]; the other with #vi[`false`].
== Forestry and Divergence
Recall that layers are structured in a forest;
the forest has one or more root layers,
and every non-root layer has a single parent layer.
When transferring to another layer (i.e. in a transfer step),
the target must be in either a root layer, or a child of the current layer.
A step can _diverge_, causing flow to immediately exit several layers.
A diverge step specifies a target ancestor layer, and optionally a stage in that layer.
Flow exits layers until it reaches the target ancestor layer.
If a stage is specified, flow transfers to that stage;
otherwise, the target layer is exited as well.
(Divergence is used to implement features like #vi[`return`], #vi[`break`], and #vi[`continue`].
In the 'call stack' analogy, divergence is analogous to throwing an exception
that is caught by a function higher up on the stack.)
In Vine, SFGs are _normalized_ before being emitted.
Normalization removes all divergence by splitting stages at points where flow may diverge.
================================================
FILE: docs/docs.nix
================================================
{
typix,
hyptyp,
typsitter,
flake-utils,
pkgs,
system,
grammars,
cli,
}:
let
self.packages.typsitter-langs = pkgs.callPackage typsitter.lib.typsitterMkDerivation {
typsitterGrammars = {
inherit (typsitter.lib.typsitterDefaultGrammars pkgs)
bash
json
toml
;
vine = grammars.packages.tree-sitter-vine;
ivy = grammars.packages.tree-sitter-ivy;
};
};
typixLib = typix.lib.${system};
hyptypLib = hyptyp.lib.${system} typixLib;
docCmd = out: "${cli.packages.vine-no-root}/bin/vine doc --debug --no-root root ${out}";
rootDocs = pkgs.stdenvNoCC.mkDerivation {
name = "root-docs";
src = pkgs.lib.fileset.toSource {
root = ../.;
fileset = ../root;
};
buildPhase = docCmd "$out";
};
commonArgs = {
typstSource = "docs/main.typ";
typstOpts = {
features = [ "html" ];
};
fontPaths = [
"${pkgs.atkinson-hyperlegible}/share/fonts/opentype"
"${pkgs.atkinson-hyperlegible-mono}/share/fonts/opentype"
];
virtualPaths = [
{
dest = "docs/deps/typsitter/typsitter.typ";
src = typsitter.lib.src;
}
{
dest = "docs/deps/typsitter-langs/";
src = self.packages.typsitter-langs;
}
{
dest = "docs/deps/hyptyp";
src = hyptypLib.hyptyp-typst;
}
];
};
watchArgs = commonArgs // { };
buildArgs = commonArgs // {
src = pkgs.lib.fileset.toSource {
root = ../.;
fileset = ./.;
};
virtualPaths = commonArgs.virtualPaths ++ [
{
dest = "docs/root";
src = "${rootDocs}/root";
}
];
};
self.packages.docs = hyptypLib.buildHyptypProject buildArgs;
self.apps.docs = flake-utils.lib.mkApp {
drv =
let
typstWatcher = hyptypLib.watchHyptypProject watchArgs;
in
pkgs.writeShellScriptBin "watch-docs" ''
${docCmd "docs"}
${pkgs.watchexec}/bin/watchexec -qw root "${docCmd "docs"}" &
${typstWatcher}/bin/${typstWatcher.name}
'';
};
self.packages.docs-pdf = typixLib.buildTypstProject buildArgs;
self.apps.docs-pdf = flake-utils.lib.mkApp {
drv = hyptypLib.watchHyptypProject watchArgs;
};
in
self
================================================
FILE: docs/docs.typ
================================================
#import "lib.typ": *
= The Vine Programming Language
Vine is an experimental new programming language based on interaction nets
(#link("https://en.wikipedia.org/wiki/Interaction_nets")[Wikipedia];;
#link("https://t6.fyi/guides/inets")[Illustrated Guide]).
Vine is a multi-paradigm language,
featuring seamless interop between functional and imperative patterns.
See
#link("https://github.com/VineLang/vine/tree/main/vine/examples/")[`vine/examples/`]
for examples of Vine.
```bash
cargo run -r --bin vine run vine/examples/$NAME.vi
```
If you're curious to learn more, join the
#link("https://discord.gg/bgUPV8KjDv")[Vine Discord server].
#let children = (
"starting/starting.typ",
"features/features.typ",
"tooling/tooling.typ",
"compiler/compiler.typ",
"ivy_ivm/ivy_ivm.typ",
)
#todos
================================================
FILE: docs/features/conditions.typ
================================================
#import "/lib.typ": *
= Conditions <conditions>
Conditions are expressions which evaluate to booleans (the #ty[`Bool`] type).
Conditions include:
- the usual:
- boolean literals (#expr[`true`], #expr[`false`])
- short-circuiting logical operators (#op[`and`], #op[`or`], #op[`!`])
- non-short-circuiting ("bitwise") operators (#op[`&`], #op[`|`], #op[`^`])
- comparison operators (#op[`==`], #op[`!=`], #op[`<`], #op[`<=`], #op[`>`], #op[`>=`])
- comparison chains
- the #op[`is`] operator
- the implication operator (#op[`impl`])
== Comparison Chains
In Vine, you can chain comparison operators.
For example, #expr[`a < b < c`] is equivalent to #expr[`(a < b) & (b < c)`].
More generally, #expr[`a() < b() < c()`] is equivalent to
```vi
do {
let x = a();
let y = b();
let z = c();
(x < y) & (y < z)
}
```
Note that comparison chains do not short-circuit;
all of the subexpressions are evaluated exactly once.
All of the comparison operators can be chained.
As a contrived example, these are equivalent:
```vi
1 == 1 < 2 <= 3 > 0 != 5 // true
(1 == 1) & (1 < 2) & (2 <= 3) & (3 > 0) & (0 != 5) // true
```
== The `is` Operator <is>
The #op[`is`] operator checks if an expression matches some pattern, and returns a boolean.
```vi
let option = Some(1);
option is Some(_); // true
option is None(); // false
```
Any variables bound by the patterns are in scope in subsequent *true-paths*
including #op[`and`] chains, then-blocks of an #vi[`if`], and the body of a #vi[`while`].
```vi
let option = Some(1);
option is Some(value) and value > 0; // true
if option is Some(value) {
value; // 1
} else {
// `value` is not bound in this scope
}
```
A true-path is broken by negation (#op[`!`]) and disjunction (#op[`or`]).
```vi
// invalid:
!(option is Some(value)) and value > 0
// invalid:
option is Some(value) or value > 0
```
== Implication
In logic, the statement "P implies Q" is true if, whenever P is true, Q is also true.
This is equivalent to "P is false, or Q is true".
Vine has an implication operator, #op[`impl`], with the same semantics.
```vi
true impl true // true
true impl false // false
false impl true // true
false impl false // true
```
The implies operator also continues the true-path;
variables bound in the left-hand side are in scope in the right-hand side:
```vi
let x = Some(1);
x is Some(value) impl value > 0 // true
x is Some(value) impl value == 0 // false
let y = None;
y is Some(value) impl value > 0 // true
y is Some(value) impl value == 0 // true
```
A common pattern in other languages
is to write `value == null || validate(value)`
to validate a nullable value.
In Vine, this is written with the implication operator:
```vi
value is Some(value) impl validate(value)
```
================================================
FILE: docs/features/control_flow/blocks.typ
================================================
#import "/lib.typ": *
= Blocks
Control flow is structured with _blocks_,
delimited with curly braces #vi[`{}`],
which can contain statements,
and may optionally end with an expression.
Blocks which end in an expression
evaluate to the value of that expression.
For example, the body of a function is a block,
and the return value of the function is the value
that the block evalautes to.
```vi
fn add(a: N32, b: N32) -> N32 {
a + b
}
add(1, 2) // 3
```
=== `do`
The #vi[`do`] expression allows embedding a block inside an expression.
```vi
let sum = do {
let a = 1;
let b = 2;
a + b
};
sum // 3
```
================================================
FILE: docs/features/control_flow/conditionals.typ
================================================
#import "/lib.typ": *
= Conditionals
== `if`
An #vi[`if`] branches on a @conditions[condition]
and executes its block when the condition is #vi[`true`].
```vi
fn maybe_greet(&io: &IO, condition: Bool) {
if condition {
io.println("hello");
}
}
maybe_greet(&io, true) // prints `hello`
maybe_greet(&io, false) // does nothing
```
An #vi[`if`] may be followed by an #vi[`else`]
to execute when the condition is #vi[`false`].
```vi
fn pleasantry(&io: &IO, condition: Bool) {
if condition {
io.println("hello");
} else {
io.println("goodbye");
}
}
pleasantry(&io, true) // prints `hello`
pleasantry(&io, false) // prints `goodbye`
```
An #vi[`if`]/#vi[`else`] can be used as an expression,
and it will evaluate to the value of the executed block.
```vi
fn pleasantry(&io: &IO, condition: Bool) {
let message = if condition { "hello" } else { "goodbye" };
io.println(message);
}
pleasantry(&io, true) // prints `hello`
pleasantry(&io, false) // prints `goodbye`
```
Note that Vine does not have an #vi[`else if`] syntax;
#vi[`when`] can be used instead.
== `when`
The #vi[`when`] expression checks multiple conditions,
and evaluates the block corresponding to the first #vi[`true`] condition.
```vi
fn count(number: N32) -> String {
when {
number == 0 { "zero" }
number == 1 { "one" }
number <= 5 { "several" }
_ { "many" }
}
}
count(0) // "zero"
count(1) // "one"
count(3) // "several"
count(46) // "many"
```
== `match`
The #vi[`match`] expression checks a value against multiple @patterns[patterns]
and evaluates the block corresponding to the first pattern that matches.
Pattern matching is often used with @enums[enums].
```vi
enum* Weekday {
Monday(),
Tuesday(),
Wednesday(),
Thursday(),
Friday(),
}
fn mood(day: Weekday) -> String {
match day {
Weekday::Monday() { ":(" }
Weekday::Friday() { ":)" }
_ { ":|" }
}
}
mood(Weekday::Friday()) // ":)"
mood(Weekday::Wednesday()) // ":|"
```
================================================
FILE: docs/features/control_flow/control_flow.typ
================================================
#import "/lib.typ": *
= Control Flow <control-flow>
#let children = (
"blocks.typ",
"conditionals.typ",
"loops.typ",
)
================================================
FILE: docs/features/control_flow/loops.typ
================================================
#import "/lib.typ": *
= Loops
== `while`
The #vi[`while`] loop repeatedly executes its block
as long as its @conditions[condition] is #vi[`true`].
```vi
let i = 0;
while i < 6 {
io.println("{i}");
i += 1;
}
```
```
0
1
2
3
4
5
```
== `for`
The #vi[`for`] loop iterates over the values of an iterator.
Ranges (written with #op[`..`]) are one type of iterator.
```vi
for i in 0..6 {
io.println("{i}");
}
```
```
0
1
2
3
4
5
```
Many collections, such as @list[lists], can also be iterated over using their #fn[`.iter()`] method.
```vi
let messages = ["hello", "how are you?", "goodbye"];
for message in messages.iter() {
io.println(message);
}
```
```
hello
how are you?
goodbye
```
== `break` & `continue`
Loops can have their execution stopped early with #vi[`break`]:
```vi
for i in 0..6 {
io.println("{i}");
if i == 3 {
break;
}
}
```
```
0
1
2
3
```
#vi[`continue`] causes execution to skip to the next iteration:
```vi
for i in 0..6 {
// skip even numbers
if i % 2 == 0 {
continue;
}
io.println("{i}");
}
```
```
1
3
5
```
== `loop`
#vi[`loop`] creates a loop without specifying a condition to repeat it.
By default, it will execute only once;
to repeat the loop, #vi[`continue`] must be used.
```vi
let i = 0;
loop {
io.println("{i}");
i += 1;
if i < 6 {
continue;
}
}
```
```
0
1
2
3
4
5
```
================================================
FILE: docs/features/features.typ
================================================
#import "/lib.typ": *
= Vine Language Features
#let children = (
"usual.typ",
"root.typ",
"modules.typ",
"variables.typ",
"control_flow/control_flow.typ",
"types/types.typ",
"patterns.typ",
"conditions.typ",
"methods.typ",
"traits/traits.typ",
"io.typ",
"values_spaces_places.typ",
"references.typ",
"inverse.typ",
)
================================================
FILE: docs/features/inverse.typ
================================================
#import "/lib.typ": *
= The Inverse <inverse>
*Note*:
This page is *bad* and _should feel bad_.
It is left here for posterity.
The inverse operator is a _niche, low-level_ feature,
and is not explained well here.
#t.hr()
Vine's concept of the _inverse_ is not something seen in other programming languages,
as it is a concept that is only possible due to the unique properties of interaction nets.
The _inverse type_ #ty[`~N32`] represents an _expectation_ of an #ty[`N32`].
Such an expectation must be _fulfilled_ with an #ty[`N32`].
The type #ty[`~~N32`] is equivalent to the type #ty[`N32`].
#footnote[
Any value can be considered to be an expectation of an expectation of itself.
Consider the value #vi[`5`].
It expects to be used, at some point.
Let's call the thing that will use it `u`.
`u` is expecting an #ty[`N32`].
(That expectation will eventually be fulfilled with #vi[`5`].)
Since `u` is expecting an #ty[`N32`], `u` is an #ty[`~N32`].
Since #vi[`5`] is expecting `u`, and `u` is an #ty[`~N32`], #vi[`5`] is an #ty[`~~N32`]
(in addition to being an #ty[`N32`]).
Thus, the types #ty[`N32`] and #ty[`~~N32`] are equivalent.
]
The _inverse operator_ can be applied to a value, a space, or a place.
- The inverse operator, when applied to a space `s` of type `T`,
evaluates to a value of type `~T`.
This value is the expectation of a `T` that will be put into the space `s`.
- The inverse operator, when applied to a value `v` of type `T`,
evaluates to a space of type `~T`.
Whatever expectation is put into the space will be fulfilled with the value `v`.
- The inverse operator, when applied to a place `p` of type `T`,
evaluates to a place `q` of type `~T`.
The value of `q` is the inverse of the space of `p`;
the space of `q` is the inverse of the value of `p`.
The _inverse pattern_ is essentially the reverse of the inverse operator,
and can be used to unwrap inverse types.
== Out Parameters
The inverse operator can be used to implement out parameters:
```vi
// `foo` takes an expectation of an `N32` as its parameter
fn foo(~n: ~N32) {
// and fulfills it with `123`
n = 123;
}
let x: N32;
let e = ~x; // e: ~N32
// `e` is now an expectation of an `N32` to put into `x`
foo(e); // we pass `e` to `foo`, which fulfills it with `123`
x // 123
```
(References can serve a similar role,
but references also carry with them a current value.)
== DIY Functions
The inverse operator can also be used to implement functions from scratch.
The following code using functions:
```vi
let add_one = fn(x: N32) { x + 1 };
let a = 1;
let b = add_one(a);
b // 2
```
Could be written without functions like so:
```vi
// `add_one` will be a tuple:
// - the first element will be an expectation of the input
// - the second element will be the output
let add_one: (~N32, N32) = do {
let x: N32;
(
~x, // create an expectation for the input, which will be put into `x`
x + 1, // calculate the output
)
};
let a = 1;
let b = do {
let (~i, o) = add_one; // destructure the tuple
i = a; // fulfill the input expectation with `a`
o // evaluate to the output
};
b // 2
```
Note that here, the order in which these computations can resolve
does not align with the imperative order of execution;
the fulfillment on line 14 must be resolved before `x + 1` on line 8 can be resolved.
This value is in a sense flowing "backwards";
counter to the usual forward flow.
== Backwards Flow
This effect can be generalized;
if you invert all uses of a variable,
the variable will flow "backwards":
```vi
// Normal, forward flow:
let x: String;
x = "a";
io.println("0: " ++ x);
io.println("1: " ++ x);
x = "b";
io.println("2: " ++ x);
io.println("3: " ++ x);
x = "c";
```
```
0: a
1: a
2: b
3: b
```
```vi
// Inverted, backward flow:
let ~x: String;
~x = "a";
io.println("0: " ++ ~x);
io.println("1: " ++ ~x);
~x = "b";
io.println("2: " ++ ~x);
io.println("3: " ++ ~x);
~x = "c";
```
```
0: b
1: b
2: c
3: c
```
Normally, writing to a variable affects accesses on later lines.
For an inverted variable,
writing to a variable affects accesses on _earlier_ lines.
This gets extra peculiar when you initialize the variable:
```vi
// Normal, forward flow:
let x = "a";
io.println("0: " ++ x);
io.println("1: " ++ x);
x = "b";
io.println("2: " ++ x);
io.println("3: " ++ x);
x = "c";
io.println("4: " ++ x);
io.println("5: " ++ x);
```
```
0: a
1: a
2: b
3: b
4: c
5: c
```
```vi
// Inverted, backward flow:
let ~x = "a";
io.println("0: " ++ ~x);
io.println("1: " ++ ~x);
~x = "b";
io.println("2: " ++ ~x);
io.println("3: " ++ ~x);
~x = "c";
io.println("4: " ++ ~x);
io.println("5: " ++ ~x);
```
```
0: b
1: b
2: c
3: c
4: a
5: a
```
The initialization of a normal variable affects
accesses on lines before any reassignment of the variable.
The initialization of an inverted variable affects
accesses on lines _after_ any reassignment of the variable.
== Time Travel
At this point, a natural question is: when is this useful?
It turns out that there are many situations where the inverse operator is useful,
and allows writing code that could not be expressed without it.
Consider the following function:
```vi
fn sub_min(&list: &List[N32]) {
let min_acc = None[N32];
let it = list.iter();
while it.next() is Some(&val) {
if min_acc is Some(m) impl val < m {
min_acc = Some(val);
}
}
let min = min_acc.unwrap();
let it = list.iter();
while it.next() is Some(&val) {
val -= min
}
}
```
This function calculates the minimum of a list of numbers,
and subtracts every number in the list by that minimum.
For example:
```vi
let x = [4, 3, 7, 9];
sub_min(&x);
x // [1, 0, 4, 6]
```
This function currently iterates over the list twice;
once to calculate the minimum, and once to do the subtraction.
At a first glance, it looks like there is no way to merge these two loops,
because you need to calculate the minimum of all the numbers
before you can subtract from any of them.
The only way you could merge these loops
is if you could somehow know what the minimum value was
before the loop even started.
As it turns out, this _is_ possible, using the inverse operator.
Since an inverted variable flows "backwards in time",
we can use one to send the minimum values from the end of the loop
back to all of the previous iterations of the loop.
```vi
fn sub_min(&list: &List[N32]) {
// our accumulator will still flow forwards, as usual
let min_acc = None[N32];
// but we'll have an inverted variable to store the final minimum value
let ~min: N32;
let it = list.iter();
while it.next() is Some(&val) {
// as we iterate over the list, we update `min_acc` as usual
if min_acc is Some(m) impl val < m {
min_acc = Some(val);
}
// but we simultaneously subtract the final minimum from the value
val -= ~min;
}
// now that we know the real minimum, we set the inverted variable,
// propagating this value back to all of the loop iterations
~min = min_acc.unwrap();
}
```
This is mind-bending to think about,
but extremely useful once you get the hang of it!
================================================
FILE: docs/features/io.typ
================================================
#import "/lib.typ": *
= IO <io>
All IO in Vine is done by calling functions on an IO handle,
passed in to #fn[`main`] at the start of the program.
For example, here is a basic `cat` program:
```vi
pub fn main(&io: &IO) {
while io.read_line() is Some(line) {
io.println(line);
}
}
```
Any function that needs to do IO must take a reference to this handle.
```vi
pub fn main(&io: &IO) {
if io.prompt("What is your name? ") is Some(name) {
greet(&io, name);
}
}
fn greet(&io: &IO, name: String) {
io.println("Hello, {name}!");
}
```
Any function that does not get passed a reference to an IO handle is *pure*
(i.e. does not interact with the outside world).
IO calls are asynchronous and do not block the execution of the rest of the program.
Every IO function takes the IO handle by reference,
and the IO handle is updated after every low-level IO operation
(like printing or reading a byte).
This ensures that the IO is executed in the expected order,
despite being asynchronous.
================================================
FILE: docs/features/methods.typ
================================================
#import "/lib.typ": *
= Methods
Any function can be marked as a _method_ by writing a `.` before the name in the definition:
```vi
fn .sum(list: List[N32]) -> N32 {
let sum = 0;
while list.pop_front() is Some(value) {
sum += value;
}
sum
}
```
Methods must take at least one argument, called the _receiver_.
Methods can still be called like normal functions,
but they can also be called using method syntax:
```vi
[1, 2, 3].sum() // 6
```
A method call can refer to any _method candidate_ with the appropriate receiver types.
Method candidates include:
- any method that is in scope
- any method defined in the module of the receiver type
- any method defined by a candidate @traits[trait]
This means that if you define a custom type,
and declare methods in its module,
anything using that type can call those methods,
without needing to explicitly import them:
```vi
enum* Shape {
Circle(F32),
Rect({ width: F32, height: F32 }),
}
mod Shape {
pub fn .perimeter(shape: Shape) -> F32 {
match shape {
Shape::Circle(radius) {
6.28 * radius
}
Shape::Rect({ width, height }) {
2.0 * (width + height)
}
}
}
}
let shape = Shape::Circle(1.0);
shape.perimeter() // 6.28
```
The first parameter of a methods can also be a @references[reference],
allowing the method to mutate the value it is called upon.
```vi
mod Shape {
pub fn .scale(&shape: &Shape, factor: F32) {
match &shape {
&Shape::Circle(radius) {
radius *= factor;
}
&Shape::Rect({ width, height }) {
width *= factor;
height *= factor;
}
}
}
}
let shape = Shape::Rect({ width: 4.0, height: 6.0 });
shape.perimeter() // 20.0
shape.scale(2.3);
shape.perimeter() // 46.0
```
================================================
FILE: docs/features/modules.typ
================================================
#import "/lib.typ": *
= Modules
Vine programs are comrpised of _modules_.
Every Vine file is a module.
Modules consist of a collection of _items_.
```vi
// main.vi
// function item named `main`
pub fn main(&io: &IO) {
io.println("Hello, world!");
}
// constant item named `answer`
const answer: N32 = 42;
```
Every item has a _visibility_, which determines where they can be accessed.
By default, items are private,
and can only be accessed within the module they were defined in.
Items can be made public with the `pub` keyword;
public items can be accessed anywhere.
== Submodules
Modules can have _submodules_.
```vi
// main.vi
mod messages {
pub const greeting: String = "Hello, world!";
pub const farewell: String = "Goodbye, world!";
}
pub fn main(&io: &IO) {
io.println(messages::greeting);
io.println(messages::farewell);
}
```
A submodule can be included from a separate file by specifying its path:
```vi
// main.vi
mod messages = "./messages.vi";
pub fn main(&io: &IO) {
io.println(messages::greeting);
io.println(messages::farewell);
}
```
```vi
// messages.vi
pub const greeting: String = "Hello, world!";
pub const farewell: String = "Goodbye, world!";
```
It is idiomatic for modules which have children
to have a path `<name>/<name>.vi`,
and for their children to be at path `<name>/<child>.vi`
(or `<name>/<child>/<child>.vi` if it also has children).
When this convention is followed,
submodule paths can be omitted,
and will be found automatically.
```vi
// main/main.vi
mod messages; // automatically refers to `main/messages.vi`
use messages::{greeting, farewell};
pub fn main(&io: &IO) {
io.println(greeting);
io.println(farewell);
}
```
```vi
// main/messages.vi
pub const greeting: String = "Hello, world!";
pub const farewell: String = "Goodbye, world!";
```
== Imports
Items from other modules can be imported with a `use` item:
```vi
// main.vi
mod messages = "./messages.vi";
use messages::{greeting, farewell};
pub fn main(&io: &IO) {
io.println(greeting);
io.println(farewell);
}
```
================================================
FILE: docs/features/patterns.typ
================================================
#import "/lib.typ": *
= Patterns <patterns>
_Patterns_ appear in:
- #vi[`let`] bindings (#vi[`let pattern = ...`])
- #vi[`fn`] parameters (#vi[`fn foo(pattern: ...) { ... }`])
- #vi[`match`] arms (#vi[`match foo { pattern { ... } }`])
- @is[#op[`is`] expressions] (#vi[`foo is pattern`])
Patterns are used to declare variables, unwrap data, and match values.
== Complete Patterns
Variables are declared using _variable patterns_.
```vi
let x = 1; // here, `x` is a variable pattern
```
Variable patterns are often subpatterns of other patterns.
_Composite patterns_ unwrap @composite[composite types]:
```vi
// tuple pattern
let tuple = (1, 2);
let (x, y) = tuple; // here, `(x, y)` is a tuple pattern
// and `x` and `y` are variable subpatterns
x // 1
y // 2
```
```vi
// object pattern
let object = { a: 1, b: 2.0 };
let { a, b: float } = object;
a // 1
float // 2.0
```
_Struct_ patterns unwrap @structs[structs]:
```vi
struct* Foo(N32);
let foo = Foo(123);
// struct pattern
let Foo(x) = foo;
x // 123
```
```vi
struct* Point((N32, N32));
let p = Point((1, 2));
// struct pattern with tuple subpattern
let Point((x, y)) = p;
x // 123
y // "abc"
// the inner set of parentheses can also be omitted:
let Point(x, y) = p;
x // 123
y // "abc"
```
```vi
struct* Place({ latitude: F32, longitude: F32 });
let magnetic_north_pole = Place({ latitude: 86.494, longitude: 162.867 });
// struct pattern with object subpattern
let Place({ latitude, longitude }) = magnetic_north_pole;
latitude // 86.494
longitude // 162.867
```
The `_` pattern discards the matched value.
```vi
let tuple = (1, 2);
let (x, _) = tuple; // discard the second field
x // 1
```
These are all _complete patterns_, because they match all values of their type.
Only complete patterns can be used in `let` bindings and `fn` parameters.
Other kinds of complete patterns include:
- @references[reference/dereference patterns]
- @inverse[inverse patterns]
== Incomplete Patterns
_Enum patterns_ match values of an @enums[enum type].
They are _incomplete patterns_, because they do not match all values of their type;
they only match one variant of the enum.
Any pattern with incomplete subpatterns is also incomplete.
Incomplete patterns can be used in `match` expressions to perform pattern matching.
For example:
```vi
fn display(score: Option[N32]) -> String {
match score {
Some(value) { "score: {value}" }
None() { "no score" }
}
}
display(Some(123)) // "score: 123"
display(None()) // "no score"
```
Incomplete patterns can also be used with the @is[`is` operator].
================================================
FILE: docs/features/references.typ
================================================
#import "/lib.typ": *
= References <references>
A _reference_ is a value that represents a place.
References can be created using the #vi[`&`] reference operator.
```vi
let x = 1; // x: N32
let r = &x; // r: &N32
```
`r` is now a reference to the place that `x` evaluated to.
It is of type #ty[`&N32`], the type representing references to #ty[`N32`]s.
References can be unwrapped using the #ty[`&`] reference pattern.
```vi
let x = 1;
let r = &x;
let &y = r; // unwrap the reference `r` into a place, and name it `y`
y = 2; // write the value `2` into the place
x // 2
```
References can be passed to function calls to allow mutation of local variables:
```vi
fn increment(&n: &N32) {
n += 1;
}
let x = 0;
increment(&x);
x // 1
```
Under the hood, methods that mutate their receiver use references:
```vi
let x = [1, 2, 3];
x.push_back(4); // equivalent to: `List::push_back(&x, 4)` (note the reference!)
x // [1, 2, 3, 4]
```
References are also useful when a function only needs to access part of a data structure:
```vi
// Inefficient
fn is_empty(list: List[N32]) -> N32 {
list.len() != 0
}
let x = [1, 2, 3, 4];
let e = is_empty(x); // inefficient; clones the whole list
x // [1, 2, 3, 4]
e // false
```
```vi
// Efficient
fn is_empty(&list: &List[N32]) -> N32 {
list.len() != 0
}
let x = [1, 2, 3, 4];
let e = is_empty(&x); // efficient; no clones necessary
x // [1, 2, 3, 4]
e // false
```
(This is why #vi[`List::len`] takes its receiver by reference,
despite not needing to mutate it.)
== Dereference Operator
The place contained in a reference can also be accessed with the #vi[`*`] dereference operator:
```vi
let x = 1;
let r = &x;
*r = 2;
x // 2
```
This can be useful when a function returns a reference:
```vi
let x = [1, 2, 3];
*x.get(2) = 4;
x // [1, 2, 4]
```
The #op[`*`] operator can also be written as a postfix operator using #op[`.*`]:
```vi
let x = [1, 2, 3];
x.get(2).* = 4;
x // [1, 2, 4]
```
== Dereference Pattern
The #op[`*`] dereference _pattern_ takes a value pattern of type #ty[`&T`],
and yields a place pattern of type #ty[`T`].
This can be used, for example, to "split" a reference to a struct into references to its fields.
```vi
struct Pair(N32, N32);
fn increment(&n: &N32) {
n += 1;
}
fn increment_pair(r: &Pair) {
let &Pair(*x, *y) = r; // x: &N32, y: &N32
increment(x);
increment(y);
}
let pair = Pair(0, 0);
increment_pair(&pair);
pair // Pair(1, 1)
```
================================================
FILE: docs/features/root.typ
================================================
#import "/lib.typ": *
= The Root Library
@root[`#root`] is Vine's standard library.
It provides:
- types fundamental to Vine,
including @root-numeric-N32[`N32`],
@root-IO[`IO`],
@root-data-List[`List`],
and @root-unicode-String[`String`]
- @root-ops[operator traits] which define the behavior
of Vine's operators, including
@root-ops-arithmetic-Add[`+`],
@root-ops-bitwise-BitAnd[`&`],
and @root-ops-Cast[`as`].
- the @root-prelude[prelude],
which defines items that are in scope
without needing to be explicitly imported
- a number of useful types and utilities, such as
@root-data-Array[`Array`],
@root-data-Map[`Map`],
@root-debug[`debug`],
and @root-rng[`rng`]
=== @root[API Docs for `#root`]
================================================
FILE: docs/features/traits/fork_drop.typ
================================================
#import "/lib.typ": *
= Fork and Drop <flex>
Every type in Vine has a _flexibility_,
which is the combination of whether its values can be _forked_
and whether its values can be _dropped_.
Forking a value gives two copies of the value; dropping a value destroys it.
Behind the scenes, any time a value is used multiple times, it is first forked,
and any time a value is not used, it is dropped.
```vi
let used_multiple_times = 123;
(used_multiple_times, used_multiple_times)
// equivalent to:
let used_multiple_times = 123;
(used_multiple_times.fork(), used_multiple_times)
```
```vi
let used_zero_times = 456;
// equivalent to:
let used_zero_times = 456;
used_zero_times.drop();
```
There are several places in Vine where one can specify the flexibility of a type,
including in type parameters, struct/enum definitions, and closure expressions.
- By default, the type is neither forkable nor droppable; its values must be used exactly once.
- With an annotation of #vi[`?`], the type will be droppable; its values may be used zero or one times.
- With an annotation of #vi[`+`], the type will be forkable; its values may be used one or more times.
- With an annotation of #vi[`*`], the type will be forkable and droppable; its values may be used zero or more times.
(This syntax parallels regex quantifiers.)
== The `Fork` and `Drop` traits
The behavior of forking/dropping values of a type is controlled by the `Fork` and `Drop` traits:
```vi
trait Fork[T] {
fn .fork(&self: &T) -> T;
}
trait Drop[T] {
fn .drop(self: T);
}
```
A type #ty[`T`] is forkable if there is an implementation of #vi[`Fork[T]`],
and droppable if there is an implementation of #vi[`Drop[T]`].
Most types implement both `Fork` and `Drop`.
A notable exception is #ty[`IO`], which can't be forked or dropped.
This means that at any point in the execution of a Vine program,
there is exactly one IO handle,
so all IO operations are ordered.
When defining a struct or enum, the flexibility can be annotated
after the #vi[`struct`]/#vi[`enum`] keyword,
to automatically implement `Fork` and/or `Drop` for the type
whenever its type parameters all implement `Fork`/`Drop`.
```vi
pub struct* Named[T](String, T);
// equivalent to:
pub struct Named[T](String, T);
pub mod Named {
pub impl fork[T; Fork[T]]: Fork[Named[T]] {
fn fork(&Named[T](name, value)) -> Named[T] {
Named(name.fork(), value.fork())
}
}
pub impl drop[T; Drop[T]]: Drop[Named[T]] {
fn drop(Named[T](name, value)) {
name.drop();
value.drop();
}
}
}
```
When writing a generic function, the flexibility of a type parameter can be annotated,
which automatically adds `Fork`/`Drop` implementation parameters.
```vi
fn lots_of[T*](value: T, length: N32) -> List[T] {
let list = [];
for _ in 0..length {
list.push_back(value);
}
list
}
// equivalent to:
fn lots_of[T; Fork[T], Drop[T]](value: T, length: N32) -> List[T] {
...
}
```
When writing a closure, its flexibility can be annotated after the #vi[`fn`] keyword.
The flexibility of a closure corresponds to the number of times it can be called.
```vi
let called_exactly_once = fn (...) { ... };
let called_at_most_once = fn? (...) { ... };
let called_at_least_once = fn+ (...) { ... };
let called_any_number_of_times = fn* (...) { ... };
```
================================================
FILE: docs/features/traits/intro.typ
================================================
#import "/lib.typ": *
= Using Traits
A _trait_ defines functionality that can be shared between types.
For example, one could define
an `Equal` trait#footnote[
Note that the standard library defines an
@comparison-traits[`Eq` trait]
similar to the `Equal` trait we've written,
and this is what underlies the #op[`==`] operator.
]
to represent equality.
```vi
trait Equal[T] {
fn .equal(x: T, y: T) -> Bool;
}
```
The `Equal` trait is generic on a type #ty[`T`],
and has a single method, #fn[`equal`],
which tests for equality between two values of type #ty[`T`].
Traits only define the signature of their methods,
so to actually call these methods, the trait has to be _implemented_.
```vi
struct* Color({ r: N32, g: N32, b: N32 });
const red: Color = Color({ r: 255, g: 0, b: 0 });
const green: Color = Color({ r: 0, g: 255, b: 0 });
const blue: Color = Color({ r: 0, g: 0, b: 255 });
impl equal_color: Equal[Color] {
fn equal(x: Color, y: Color) -> Bool {
x.r == y.r and x.g == y.g and x.b == y.b
}
}
```
Now, we've defined an implementation named `equal_color` of the trait `Equal` for the type #ty[`Color`],
so we can now call the #fn[`equal`] method on #ty[`Color`]s:
```vi
red.equal(blue) // false
red.equal(red) // true
```
If we wanted to use this method on other types, we could create more implementations.
```vi
impl equal_bool: Equal[Bool] {
fn equal(x: Bool, y: Bool) -> Bool {
x and y or !x and !y
}
}
```
(Most of the time, the names of implementations don't matter,
but they are used to disambiguate if multiple implementations could apply.)
== Implementation Parameters
The advantage of using traits instead of just defining individual functions for types is that,
with traits, one can abstract over any type that has an implementation of a certain trait.
For example, we could write a `not_equal` function:
```vi
fn not_equal[T; Equal[T]](a: T, b: T) -> Bool {
!a.equal(b)
}
```
The #fn[`not_equal`] function takes one type parameter, #ty[`T`],
and one _implementation parameter_, of the trait #vi[`Equal[T]`].
(The semicolon inside the generic parameters separates the type parameters from the implementation parameters.)
Since `a` and `b` are of type #ty[`T`],
and there is an implementation of #vi[`Equal[T]`],
`equal` can be called on `a` and `b`.
We can then call this function on any types that we've implemented `Equal` for.
```vi
not_equal(red, blue) // true
not_equal(true, true) // false
```
Without traits, we would have to manually implement this function
for every type we created an #fn[`equal`] method for.
Implementations themselves can also be generic and take implementation parameters.
This allows us to implement #vi[`Equal[List[T]]`] for any #ty[`T`] where #vi[`Equal[T]`] is implemented:
```vi
impl equal_list[T; Equal[T]]: Equal[List[T]] {
fn equal(x: List[T], y: List[T]) -> Bool {
if x.len() != y.len() {
return false;
}
while x.pop_front() is Some(a) and y.pop_front() is Some(b) {
if not_equal(a, b) {
return false;
}
}
true
}
}
```
The signature of `equal_list` says that for any type #ty[`T`],
if there is an implementation of #vi[`Equal[T]`],
then `equal_list` implements #vi[`Equal[List[T]]`].
We can thus now check equality for lists of colors or lists of booleans:
```vi
[red, green, blue].equal([red, blue, green]) // false
[true, false].equal([true, false]) // true
```
We can even check equality for lists of lists of colors!
```vi
[[red, blue], [green, red]].equal([[red, blue], [green, red]]) // true
[[], [red]].equal([[red], []]) // false
```
================================================
FILE: docs/features/traits/standard.typ
================================================
#import "/lib.typ": *
= Standard Traits
The standard library defines several traits, many of which control the behavior of built-in operators.
Implementations of the `Concat` trait control the behavior of the #op[`++`] operator.
Implementations of the `Cast` trait control the behavior of the #op[`as`] operator,
which can be used for explicit type casting (#expr[`123 as String`]).
The `Cast` trait is also used in string interpolation to cast interpolated values into #ty[`String`]s.
== Arithmetic Operators
Implementations of
the `Add`, `Sub`, `Mul`, `Div`, `Rem`, and `Neg` traits (from #vi[`#root::ops::arithmetic`])
control the behavior of
the #op[`+`], #op[`-`], #op[`*`], #op[`/`], #op[`%`], and unary #op[`-`] operators.
The standard library defines implementations of these traits for all numeric types.
One can opt-in to element-wise arithmetic on pairs (#expr[`(1, 2) + (3, 4) == (4, 6)`])
by importing the implementations from #vi[`#root::ops::elementwise`].
== Bitwise Operators
Implementations of
the `And`, `Or`, `Xor`, `Not`, `Shl`, and `Shr` traits (from #vi[`#root::ops::bitwise`])
control the behavior of
the #op[`&`], #op[`|`], #op[`^`], #op[`!`], #op[`<<`], and #op[`>>`] operators.
The standard library defines implementations of these traits for all integer types,
and implementations of the first four for booleans.
(The logical operators #op[`and`], #op[`or`], and #op[`impl`] cannot be overloaded.)
== Comparison Operators <comparison-traits>
Implementations of the `Eq` trait control the behavior of the #op[`==`] and #op[`!=`] operators.
Implementations of the `Lt` and `Le` traits control the behavior of the #op[`<`] and #op[`<=`] operators.
(The behavior of #op[`>`] and #op[`>=`] is implicitly derived from these.)
In most cases, rather than implementing `Lt` and `Le` directly, one should implement the `Ord` trait,
which represents a total order and is used by things like #ty[`Map`].
(There are standard implementations of `Lt` and `Le` for any type that `Ord` is implemented for.)
== `Show`
The `Show` trait defines a way to represent the structure of a value for printing,
which is useful for debugging.
Most types should implement the `Show` trait.
The #fn[`show`] method provided by the `Show` trait returns an instance of the `Show` enum,
which can then be cast to a string to print.
For example:
```vi
[1, 2, 3, 4].show() as String // "[1, 2, 3, 4]"
let value = (true, Some(23 * 2), [(1, "one"), (2, "two"), (3, "three")] as Map)
io.println("{value.show()}")
// (true, Some(46), Map({ 1: "one", 2: "two", 3: "three" }))
```
Things that are too long to fit on one line will get broken into several lines:
```vi
let value = "
a very long list of strings
so long that all of the strings
could not possibly all fit
onto a single line
".split_trim("\n");
io.println("{value.show()}")
// [
// "a very long list of strings",
// "so long that all of the strings",
// "could not possibly all fit",
// "onto a single line",
// ]
```
================================================
FILE: docs/features/traits/traits.typ
================================================
#import "/lib.typ": *
= Traits <traits>
A _trait_ defines functionality that can be shared between types.
#let children = (
"intro.typ",
"standard.typ",
"fork_drop.typ",
)
================================================
FILE: docs/features/types/composite.typ
================================================
#import "/lib.typ": *
= Composite Types <composite>
A composite type is a fixed-sized, heterogenous collection of values.
There are two kinds of composite types: _tuples_ and _objects_.
```vi
// tuple
let a = (1, 'a', 4.6); // a: (N32, Char, F32)
// object
let b = { p: false, q: "xyz" }; // b: { p: Bool, r: String }
```
The values of a tuple are accessed by their index.
```vi
let a = (1, 'a', 4.6);
a.0 // 1
a.1 // 'a'
a.2 // 4.6
a.2 *= 10.0;
a.2 // 46.0
```
The values of an object are accessed by their key.
```vi
let b = { p: false, q: "xyz" };
b.p // false
b.q // "xyz"
b.p = !b.p;
b.p // true
```
================================================
FILE: docs/features/types/enums.typ
================================================
#import "/lib.typ": *
= Enums <enums>
An enum is a type with a fixed set of _variants_.
An enum value is one of those variants.
```vi
enum* Weekday {
Monday(),
Tuesday(),
Wednesday(),
Thursday(),
Friday(),
}
let day = Weekday::Friday(); // day: Weekday
day is Weekday::Monday() // false
day is Weekday::Friday() // true
let mood = match day {
Weekday::Monday() { ":(" }
Weekday::Friday() { ":)" }
_ { ":|" }
};
mood // ":)"
```
(The `*` specifies that the struct can be freely copied and deleted.
Most of this time, this is what you want; see @flex[flexibility] for more detail.)
Like structs, enum variants wrap content:
```vi
enum* Shape {
Point(),
Circle(F32),
Rect({ width: F32, height: F32 }),
}
let x = Shape::Point(); // x: Shape
let y = Shape::Circle(1.0); // y: Shape
let z = Shape::Rect({ width: 4.0, height: 6.0 }); // z: Shape
```
Pattern matching can be used to branch on the variant of the enum and access its content.
```vi
fn perimeter(shape: Shape) -> F32 {
match shape {
Shape::Point() {
0.0
}
Shape::Circle(radius) {
6.28 * radius
}
Shape::Rect({ width, height }) {
2.0 * (width + height)
}
}
}
perimeter(Shape::Point) // 0.0
perimeter(Shape::Circle(1.0)) // 6.28
perimeter(Shape::Rect({ width: 4.0, height: 6.0 })) // 20.0
```
Pattern matching is discussed further in the @patterns[Patterns] section.
== Standard Enums
The standard library defines the enum types #ty[`Option[T]`] and #ty[`Result[T, E]`]:
```vi
enum* Option[T] {
Some(T),
None(),
}
enum* Result[T, E] {
Ok(T),
Err(E),
}
```
================================================
FILE: docs/features/types/primitives.typ
================================================
#import "/lib.typ": *
= Primitive Types <primitive-types>
(Note: there is no implicit casting between numeric types.
Values can be converted to another primitive type using the #op[`as`] operator
(#expr[`45 as F32 + 1.0`]).)
== `N32` <n32>
The type #ty[`N32`] describes
natural numbers#footnote[
Natural numbers are non-negative integers.
In other programming languages,
they are often referred to as "unsigned integers".
Seeing as positive integers do have a sign (namely, a positive sign),
the only truly unsigned integer is zero.
],
represented with 32 bits of precision.
#ty[`N32`] values can be written as literals
in decimal (#expr[`46`]), hex (#expr[`0x2e`]), or binary (#expr[`0b101110`]).
Digits can be separated with underscores (#expr[`1_000_000`]).
#ty[`N32`]s support the usual arithmetic and bitwise operators
(#expr[`4 * 11 + 2`], #expr[`5 << 3 | 6`]).
_See also @root-numeric-N32[`#root::numeric::N32`]._
== `I32`
The type #ty[`I32`] describes integers, represented with 32 bits of precision.
#ty[`I32`] values can be written as literals in
decimal (#expr[`+46`], #expr[`-46`]),
hex (#expr[`+0x2e`], #expr[`-0x2e`]),
or binary (#expr[`+0b101110`], #expr[`-0b101110`]).
The sign is required.
Digits can be separated with underscores (#expr[`+1_000_000`], #expr[`-1_000_000`]).
#ty[`I32`]s support the usual arithmetic and bitwise operators
(#expr[`+4 * +12 + -2`], #expr[`+5 << +3 | +6`]).
_See also @root-numeric-I32[`#root::numeric::I32`]._
== `F32` <f32>
The type #ty[`F32`] describes 32-bit floating-point numbers (following IEEE 754).
#ty[`F32`] values can be written as literals (#expr[`4.6e1`]).
The decimal point is required.
#ty[`F32`]s support the usual arithmetic operators (#expr[`3.6 * 12.3 + 1.72`]).
_See also @root-numeric-F32[`#root::numeric::F32`]._
== `Char`
The type #ty[`Char`] describes Unicode scalar values.
#ty[`Char`]s are primarily used within #ty[`String`]s.
#ty[`Char`] values can be written as literals using single quotes (#expr[`'.'`]).
#ty[`Char`]s support adding an #ty[`N32`], resulting in another #ty[`Char`] (#expr[`'a' + 4`]),
as well as subtracting another #ty[`Char`], resulting in an #ty[`N32`] (#expr[`'G' - 'A'`]).
_See also @root-unicode-Char[`#root::unicode::Char`]._
== `Bool`
The type #ty[`Bool`] describes booleans.
The two #ty[`Bool`] values can be written as literals (#expr[`true`], #expr[`false`]).
`Bool`s support the usual short-circuiting logical operators (#op[`and`], #op[`or`], #op[`!`])
and non-short-circuiting ("bitwise") operators (#op[`&`], #op[`|`], #op[`^`]).
Expressions that evaluate to booleans are called @conditions[conditions].
_See also @root-logical-Bool[`#root::logical::Bool`]._
== `IO`
#ty[`IO`] is a special primitive type used to interact with the outside world.
Values of this type cannot be explicitly constructed;
instead, an #ty[`IO`] handle is passed in to #fn[`main`] at the start of the program.
See the section on @io[IO] for more detail.
_See also @root-IO[`#root::IO`]._
================================================
FILE: docs/features/types/standard.typ
================================================
#import "/lib.typ": *
= Standard Types <standard-types>
The standard library defines various commonly-used types.
(In the following sections, the time complexity of operations is described in
#link("https://en.wikipedia.org/wiki/Big_O_notation")[Big O notation].)
== `String` <string>
The type #ty[`String`] describes Unicode strings,
represented as a list of Unicode scalar values.
Strings can be written as literals using double quotes (#expr[`"Hello, world!"`]).
Expressions can be interpolated into string literals using braces
(#expr[`"{10} + {36} = {10 + 36}"`]).
Strings can be concatenated with the #op[`++`] operator (`O(1)`).
_See also @root-unicode-String[`#root::unicode::String`]._
== `List` <list>
The generic type #ty[`List[T]`] describes lists of values of type #ty[`T`].
Lists are optimized for fast concatenation and in-order iteration.
Accessing the first value in a list is `O(1)`,
but accessing an arbitrary value is `O(n)`.
An array is a better choice if frequently accessing elements by index.
Lists can be written as literals using square brackets (#expr[`[1, 2, 3]`]).
Lists can be concatenated with the #op[`++`] operator (`O(1)`).
Lists can be used as a queue by
using #fn[`.push_back`] to enqueue
and #fn[`.pop_front`] to dequeue (both `O(1)`).
Lists can be used as a stack by
using #fn[`.push_front`] to push
and #fn[`.pop_front`] to pop (both `O(1)`).
_See also @root-data-List[`#root::data::List`]._
== `Array`
The generic type #ty[`Array[T]`] describes arrays of values of type #ty[`T`].
Arrays are optimized for fast random access.
Accessing an arbitrary value in the array is `O(log(n))`.
Elements can be added and removed from either the front or the back with
#fn[`.push_front`] / #fn[`.pop_front`] / #fn[`.push_back`] / #fn[`.pop_back`] (`O(log(n))`).
`Array`s can be converted to and from lists with
#expr[`array as List`] and #expr[`list as Array`] (`O(n)`).
_See also @root-data-Array[`#root::data::Array`]._
== `Map`
The generic type #ty[`Map[K, V]`] describes mappings from keys of type #ty[`K`] to values of type #ty[`V`].
Maps are sorted by their key,
and can be efficiently iterated over using #fn[`.iter`] and #fn[`.into_iter`].
Inserting, accessing, and removing a value by key can be done with
#fn[`.insert`] / #fn[`.get`] / #fn[`.remove`] (`O(log(n))`).
The minimum / maximum key-value pair can be removed with
#fn[`.remove_min`] / #fn[`.remove_max`] (`O(log(n))`).
_See also @root-data-Map[`#root::data::Map`]._
== `Set`
The generic type #ty[`Set[T]`] describes sets of elements of type #ty[`T`].
Sets are sorted by their key,
and can be efficiently iterated over using #fn[`.iter`] and #fn[`.into_iter`].
Inserting, checking for, and removing a value can be done with
#fn[`.insert`] / #fn[`.has`] / #fn[`.remove`] (`O(log(n))`).
The minimum / maximum value pair can be removed with
#fn[`.remove_min`] / #fn[`.remove_max`] (`O(log(n))`).
_See also @root-data-Set[`#root::data::Set`]._
================================================
FILE: docs/features/types/structs.typ
================================================
#import "/lib.typ": *
= Structs <structs>
A _struct_ creates a new type that wraps some _content_.
```vi
// define a struct named `Id` with content type `N32`
struct* Id(N32);
```
(The `*` specifies that the struct can be freely copied and deleted.
Most of this time, this is what you want; see @flex[flexibility] for more detail.)
Structs can be constructed by specifying their content:
```vi
let id = Id(46); // id: Id
```
A struct type is distinct from its content type:
```vi
let id: Id = 46; // error; expected type `Id`, found type `N32`
let num: N32 = Id(46); // error; expected type `N32`, found type `Id`
```
To access the content of a struct, one can use the unwrap operator, #op[`!`]:
```vi
let id = Id(46);
let num = id!; // num: N32
num // 46
```
Structs are also _nominal_;
a struct type is distinct from any other struct type,
even one with the same content:
```vi
struct* Foo(String);
struct* Bar(String);
let foo: Foo = Bar("foo"); // error: expected type `Foo`, found type `Bar`
```
It's often useful to have struct types which wrap multiple fields;
this can be accomplished by having the content be a composite type:
```vi
struct* Point((N32, N32));
let p = Point((1, 2));
// for tuples, the inner set of parentheses can be omitted:
let p = Point(1, 2);
p! // (1, 2)
p!.0 // 1
p!.1 // 2
// the `!` can be omitted when accessing a field:
p.0 // 1
p.1 // 2
```
```vi
struct* Place({
latitude: F32,
longitude: F32,
});
let magnetic_north_pole = Place({
latitude: 86.494,
longitude: 162.867,
});
magnetic_north_pole! // { latitude: 86.494, longitude: 162.867 }
magnetic_north_pole!.latitude // 86.494
magnetic_north_pole!.longitude // 162.867
// the `!` can be omitted when accessing a field:
magnetic_north_pole.latitude // 86.494
magnetic_north_pole.longitude // 162.867
```
Struct types can also be generic.
```vi
struct* Pair[T]((T, T));
let u = Pair(1, 2); // u: Pair[N32]
let v = Pair(true, false); // v: Pair[Bool]
struct* Box[T]({ value: T })
let x = Box({ value: 46 }); // x: Box[N32]
let y = Box({ value: "abc" }); // y: Box[String]
```
By default, the content of a struct is private to the module the struct was defined in:
```vi
mod points {
pub struct* Point((N32, N32));
pub const origin: Point = Point(0, 0);
}
use points::{Point, origin};
Point(1, 2) // error; content of `Point` is private
origin.0 // error; content of `Point` is private
```
The content can be made public by giving it a visibility of `pub`:
```vi
mod points {
pub struct* Point(pub (N32, N32));
// ^-- visibility of the content
pub const origin: Point = Point(0, 0);
}
use points::{Point, origin};
Point(1, 2) // ok
origin.0 // ok
```
================================================
FILE: docs/features/types/types.typ
================================================
#import "/lib.typ": *
= Types
Vine is statically typed.
Every expression has a type, like #ty[`Bool`] or #ty[`List[N32]`].
Type parameters are written in square brackets.
Types fall in to several categories:
- @primitive-types[primitive types] are fundamental types defined by the compiler
- @standard-types[standard types] are commonly-used types defined by the standard library
- @structs[structs] and @enums[enums] are user-defined types
#let children = (
"primitives.typ",
"standard.typ",
"composite.typ",
"structs.typ",
"enums.typ",
)
================================================
FILE: docs/features/usual.typ
================================================
#import "/lib.typ": *
= The Usual <usual>
Vine has the usual complement of standard programming language features, including:
- @n32[integers]: #expr[`1 + 2 * 3`]
- @f32[floats]: #expr[`1.0 + 2.0 * 3.0`]
- @conditions[booleans] (including short-circuiting):
#expr[`true and !(false or 1 == 2)`]
- @list[lists]: #expr[`[1, 2, 3] ++ [4, 5, 6]`]
- @string[strings]: #expr[`"12 + 34 = {12 + 34}"`]
- @composite[tuples]: #expr[`(1, 1.0, "abc")`], #expr[`(1, 2).0`]
- @variables[variables]: #vi[`let x = 5; x += 1`]
- @control-flow[control flow]:
- #vi[`if condition { ... } else { ... }`]
- #vi[`while condition { ... }`]
- #vi[`return value`]
- #vi[`break`], #vi[`continue`]
(Try some of these snippets in the `vine repl`!)
Many of Vine's features are influenced by Rust,
and it has a similar expression-oriented syntax, type system, and module system.
================================================
FILE: docs/features/values_spaces_places.typ
================================================
#import "/lib.typ": *
= Values, Spaces, and Places
The result of an expression in Vine has one of three _forms_:
a value, a space, or a place.
- a _value_ represents some piece of data
- a _space_ represents somewhere that data can be put
- a _place_ is the combination of a value and a space.
We'll use the following code example to explore these concepts further.
```vi
let x = 1 + 2;
x + 1;
x = 5;
x *= 2;
```
On line 1, the expression #expr[`1 + 2`] results in the value #expr[`3`].
The variable #expr[`x`] is then declared with an initial value of #expr[`3`].
On line 2, the expression #expr[`x`] results in its value #expr[`3`],
so the expression #expr[`x + 1`] results in the value #expr[`4`].
This expression is unused so its result is simply discarded.
On line 3, we have an assignment statement.
This expects a space on the left-hand side,
and a value on the right-hand side,
and will put the value into the space.
In this particular case, the expression #expr[`x`] on the left-hand side results in a space --
whatever value is put into this space will become the new value of #expr[`x`].
Then, the assignment operator puts the value #expr[`5`] into the space.
The value of #expr[`x`] is now #expr[`5`].
On line 4, the #op[`*=`] operator expects a place on the left-hand side,
and a value on the right-hand side.
Thus, #expr[`x`] results in its place,
which is the combination of the value #expr[`5`]
and a space to put a new value for #expr[`x`].
The #op[`*=`] operator uses the value to calculate #expr[`5 * 2`],
and puts the value #expr[`10`] into #expr[`x`]'s space.
Thus, the value of #expr[`x`] is now #expr[`10`].
== Expression Resolution
=== Expression Positions
Every expression is located in either a value position, a space position, or a place position.
The form of the expression's position determines the form of the result of the expression.
We saw above that the expression #expr[`x`] could result in a value, a space, or a place;
this is determined by the form of its position.
- On line 2, in #expr[`x + 1`], #expr[`x`] is in a value position, so it results in a value.
- On line 3, in #expr[`x = 5`], #expr[`x`] is in a space position, so it results in a space.
- On line 4, in #expr[`x *= 2`], #expr[`x`] is in a place position, so it results in a place.
=== Expression Forms
Independent of its position, every expression has a form --
it is either a value expression, a space expression, or a place expression.
For example, variable expressions, like #expr[`x`], are place expressions.
The form of an expression determines the form of what the expression *evaluates to*.
If this form does not match the form of the expression's position,
it is _coerced_ to become the result.
- On line 2, in #expr[`x + 1`], #expr[`x`] evaluates to a place.
It is in a value position, so it is coerced to a value.
- On line 3, in #expr[`x = 5`], #expr[`x`] evaluates to a place.
It is in a space position, so it is coerced to a space.
- On line 4, in #expr[`x *= 2`], #expr[`x`] evaluates to a place.
It is in a place position, so it is not coerced.
=== Coercion
There are three rules for coercion:
- If `Fork[T]` is implemented,
when a place of type `T` is coerced to a value,
the value is `Fork::fork(&place)`.
- If `Drop[T]` is implemented,
when a place of type `T` is coerced to a space,
the resulting space is the place's space;
the place's value is dropped.
- If `Drop[T]` is implemented,
when a value of type `T` is coerced to a place,
the resulting place is a combination of the value
and a space that drops the updated value.
// In code:
// ```vi
// fn place_to_value[T; Fork[T]](&place: &T) -> T {
// Fork::fork(&place)
// }
//
// fn place_to_space[T; Drop[T]](&place: &T) -> ~T {
// let &(value; space) = &place;
// Drop::drop(value)
// ~space
// }
//
// fn value_to_place[T; Drop[T]](value: T) -> &T {
// &(value; |> t { Drop::drop(t) })
// }
// ```
These rules result in the behavior described in the first section.
================================================
FILE: docs/features/variables.typ
================================================
#import "/lib.typ": *
= Variables <variables>
The primary way to declare new variables is with the #vi[`let`] statement.
```vi
let x = 4; // declare the variable `x` with an initial value of `4`
x // 4
x = 6; // assign a new value, `6`, to `x`
x // 6
```
You can also declare a new variable with no initial value.
```vi
let x;
// `x` has no value!
x = 5; // assign `5` to `x`
x // 5
```
(Note that, in more advanced uses of the #vi[`let`] statement,
declaring a variable with an initializer is not always equivalent
to declaring it no initializer and then assigning to it.)
Using a variable with no value is an error.
```vi
let x;
x // error!
```
All variables have a type, which is inferred by default.
```vi
let x = "abc"; // x: String
x = 5; // error!
```
The type of a variable can also be explicitly specified with a type annotation:
```vi
let x: String = "abc";
let y: String = 5; // error!
```
== Shadowing
Declaring a variable with the same name as a variable already in scope
_shadows_ the previous variable,
making it inaccessible for the duration of the scope.
```vi
let x = 1;
x // 1
let x = "abc";
x // "abc"
```
This is different from reassigning the variable in a number of ways;
for one, the new variable can have a different type (like in the above example).
Variables shadowed within a block will no longer be shadowed after the end of the block.
```vi
let x = 1;
x // 1
if x > 0 {
let x = "abc";
x // "abc"
}
x // 1
```
================================================
FILE: docs/img.typ
================================================
#import "/lib.typ": hyptyp
#import hyptyp: t
#import t: link, meta
#let resources = for img in (
"/logo.svg",
"/logo.png",
"/favicon.ico",
"/apple-touch-icon-57x57.png",
"/apple-touch-icon-114x114.png",
"/apple-touch-icon-72x72.png",
"/apple-touch-icon-144x144.png",
"/apple-touch-icon-60x60.png",
"/apple-touch-icon-120x120.png",
"/apple-touch-icon-76x76.png",
"/apple-touch-icon-152x152.png",
"/favicon-196x196.png",
"/favicon-96x96.png",
"/favicon-32x32.png",
"/favicon-16x16.png",
"/favicon-128.png",
"/mstile-144x144.png",
"/mstile-70x70.png",
"/mstile-150x150.png",
"/mstile-310x150.png",
"/mstile-310x310.png",
) {
hyptyp.resource(img, read("img" + img, encoding: none))
}
#let icons = {
link(rel: "apple-touch-icon-precomposed", sizes: "57x57", href: "/apple-touch-icon-57x57.png")
link(rel: "apple-touch-icon-precomposed", sizes: "114x114", href: "/apple-touch-icon-114x114.png")
link(rel: "apple-touch-icon-precomposed", sizes: "72x72", href: "/apple-touch-icon-72x72.png")
link(rel: "apple-touch-icon-precomposed", sizes: "144x144", href: "/apple-touch-icon-144x144.png")
link(rel: "apple-touch-icon-precomposed", sizes: "60x60", href: "/apple-touch-icon-60x60.png")
link(rel: "apple-touch-icon-precomposed", sizes: "120x120", href: "/apple-touch-icon-120x120.png")
link(rel: "apple-touch-icon-precomposed", sizes: "76x76", href: "/apple-touch-icon-76x76.png")
link(rel: "apple-touch-icon-precomposed", sizes: "152x152", href: "/apple-touch-icon-152x152.png")
link(rel: "icon", type: "image/png", href: "/favicon-196x196.png", sizes: "196x196")
link(rel: "icon", type: "image/png", href: "/favicon-96x96.png", sizes: "96x96")
link(rel: "icon", type: "image/png", href: "/favicon-32x32.png", sizes: "32x32")
link(rel: "icon", type: "image/png", href: "/favicon-16x16.png", sizes: "16x16")
link(rel: "icon", type: "image/png", href: "/favicon-128.png", sizes: "128x128")
meta(name: "application-name", content: "Vine")
meta(name: "msapplication-TileColor", content: "#151820")
meta(name: "msapplication-TileImage", content: "/mstile-144x144.png")
meta(name: "msapplication-square70x70logo", content: "/mstile-70x70.png")
meta(name: "msapplication-square150x150logo", content: "/mstile-150x150.png")
meta(name: "msapplication-wide310x150logo", content: "/mstile-310x150.png")
meta(name: "msapplication-square310x310logo", content: "/mstile-310x310.png")
}
================================================
FILE: docs/ivy_ivm/extrinsics.typ
================================================
#import "/lib.typ": *
= Extrinsics <extrinsics>
Extrinsics are how programs running in the IVM interact with the outside world.
An extrinsic value is a nilary agent that represents an external entity.
They are opaque to the interaction net,
and can only be manipulated and queried via extrinsic functions and extrinsic branches.
An extrinsic function is an agent that represents an external operation.
They operate solely on extrinsic values,
and return only extrinsic values.
Extrinsic functions may have side effects.
Extrinsic functions are the only way for the interaction net to manipulate extrinsic values.
An extrinsic branch is a ternary agent that represents a boolean query on an external entity.
They query a single extrinsic value, and select one of two branches.
Extrinsic branches are the only way for the interaction net to inspect extrinsic values.
Currently, there is a fixed set of extrinsics built-in to IVM.
In the future, this will be extensible (#issue(54)).
== Extrinsic Value Types
=== `N32`
An `N32` extrinsic value represents a 32-bit natural number.
They can be written as integer literals in Ivy programs.
Vine's `N32`, `I32`, `Char`, and `Bool` types
are all represented by `N32` extrinsic values.
=== `F32`
An `F32` extrinsic value represents a 32-bit floating-point number.
They can be written as float literals in Ivy programs.
=== `IO` <extrinsic-io>
An `IO` extrinsic value represents an IO handle,
and can be used to perform IO.
`IO` values cannot be written in Ivy programs.
When an Ivy program is run,
the `::main` net is connected to an `IO` value.
This is the only way to obtain an `IO` value.
== Extrinsic Functions
=== General Arithmetic
The `@add`/`@sub`/`@mul`/`@div`/`@rem` extrinsic functions
perform arithmetic on `N32` or `F32` values.
They input two values and output one.
If both inputs are `N32`s, the output will be an `N32`;
otherwise, the output is an `F32`.
=== Comparisons
The `@eq`/`@ne`/`@lt`/`@le` extrinsic functions
take two `N32` or two `F32` values
and return an `N32` value representing the result of the comparison
(`1` for true, and `0` for false).
=== Specialized Arithmetic
The `@n32_shl`/`@n32_shr`/`@n32_rotl`/`@n32_rotr`/`@n32_and`/`@n32_or`/`@n32_xor`
extrinsic functions take two `N32` values,
perform a bitwise operation,
and output an `N32` value.
The `@n32_add_high`/`@n32_mul_high` extrinsic functions
return the 32 most-significant bits of the 64-bit result of an operation on two `N32` values.
=== IO
The `@io_print_char` extrinsic functions takes an `IO` value
and an `N32` value representing a Unicode scalar value,
prints the character to stdout,
and returns an `IO` value.
The `@io_print_byte` extrinsic function
takes an `IO` value and an `N32` value,
prints the least-significant byte to stdout,
and returns an `IO` value.
The `@io_flush` extrinsic function
takes an `IO` value and an `N32` value,
flushes stdout,
discards the `N32`,
and returns an `IO` value.
The `@io_read_byte` extrinsic function
takes an `IO` value and an `N32` value,
reads a byte from stdin,
and returns that byte as an `N32`,
or the `N32` parameter if no byte could be read.
The `@seq` extrinsic function takes two extrinsic values and returns the first.
It is useful for sequentializing side effects from other extrinsic functions.
================================================
FILE: docs/ivy_ivm/interaction_system.typ
================================================
#import "/lib.typ": *
= Ivy's Interaction System <interaction-system>
Ivy's interaction system is based on the symmetric interaction combinators,
with various extensions.
== Agent Types
=== Combinators
Ivy has a (theoretically) unlimited number of binary combinator agent types,
each identified with a _label_.
Two combinators of the same label annihilate,
whilst two combinators of different labels commute.
Ivy also has an eraser agent, which is a nilary combinator.
=== Globals
Ivy programs are structured as a collection of named _global nets_.
Each global net corresponds to a nilary _global agent_.
A global agent expands into the corresponding global net when necessary during interaction.
=== Extrinsics
_Extrinsic agents_ represent entities and operations external to the interaction net.
- _extrinsic values_ are nilary agents that represent external entities
- _extrinsic functions_ are binary agents that represent external operations
- _extrinsic branches_ are ternary agents that represent a boolean query on an external entity
Extrinsics are discussed in more detail on the @extrinsics[corresponding page].
== Interaction Rules
Ivy has 7 categories of interaction rules:
- Annihilate
- Commute
- Copy
- Erase
- Expand
- Call
- Branch
For combinator agents, the Annihilate, Commute, Copy, and Erase rules
behave equivalently to the standard rules for symmetric interaction combinators.
=== Annihilate
When two non-nilary agents of the same type interact, they annihilate.
The wires previously connected to their auxiliary ports are linked together.
=== Commute
When two non-nilary agents of different types interact, they commute,
analogously to interaction combinators.
=== Copy
When a nilary agent and a non-nilary agent of certain types interact,
the nilary agent is copied to each of the non-nilary agent's auxiliary wires.
This happens when:
- the nilary agent is an eraser
- the nilary agent is an extrinsic value,
and the non-nilary agent is a combinator
- the nilary agent is a global agent,
and the non-nilary agent is a combinator
of a label that does not appear in the global net
(or any global net transitively referenced)
=== Erase
When two nilary agents interact, they are erased,
unless one is an extrinsic value and the other is a global agent.
=== Expand <expand>
When a global agent interacts with another agent, it is expanded
(unless the Copy or Erase rules above apply).
The global agent is simply replaced with the corresponding global net
(and the other agent is untouched).
=== Call <call>
When an extrinsic value interacts with an extrinsic function,
the associated operation is performed on the associated entity,
and some extrinsic value is returned.
=== Branch
When an extrinsic value interacts with an extrinsic branch,
the associated query is performed on the associated entity.
Based on the boolean result,
one of the first two auxiliary wires is linked to the third,
and the other is connected to an eraser.
================================================
FILE: docs/ivy_ivm/ivm.typ
================================================
#import "/lib.typ": *
= IVM Overview <ivm>
IVM is a performant interaction combinator runtime.
It is used to run Ivy programs
(and thus also Vine programs, since they compile to Ivy).
To run an Ivy program on the IVM,
each named global net is translated into a list of instructions for assembling the net
(e.g. create a node, then link these two ports).
These instructions are used to perform @expand[Expand] interactions.
The IVM then boots, creating a single active pair
between a global agent for the `::main` net, and an @extrinsic-io[`IO` extrinsic value].
The IVM then enters its main loop to perform interactions.
The first interaction will always be
an Expand interaction between the `::main` agent and the `IO` value.
The IVM follows the instructions for assembling the `::main` net.
This creates more active pairs, which are continually reduced.
@call[Call] interactions may have side effects,
allowing the net to interact with the outside world.
Once all interactions are performed,
the net will be in normal form.
Since the starting net had no free ports,
if no vicious circles are formed,
the final net will empty.
== Parallel Evaluation
The IVM can also be run in a parallel mode.
In parallel mode, after boot, the IVM spawns the configured number of *worker* threads.
The main thread then assumes the role of the *dispatch* thread.
The worker threads are responsible for performing interactions,
whilst the dispatch thread distributes active pairs among the workers.
Each worker has two buffers of active pairs:
one that it is currently reducing,
and one that is shared with the dispatch thread.
This shared buffer is used to
pass work from the dispatch to the worker (if the worker is idle)
or from the worker to the dispatch (if the worker is overloaded).
================================================
FILE: docs/ivy_ivm/ivy.typ
================================================
#import "/lib.typ": *
= Ivy Overview <ivy>
An Ivy program consists of a series of named global nets.
The name of a global net must start with `::`,
and may contain arbitrary identifier characters or additional `::`s (e.g. `::foo::bar`).
Ivy nets are specified with a syntax based on the
#link("https://en.wikipedia.org/wiki/Interaction_nets#Interaction_calculus")[interaction calculus];;
each net has a root tree, attached to its singular free port;
any number of pairs of trees;
and a wiring specified by pairs of variables.
```iv
// definition of the net `::main` (which is the entrypoint of the program)
::main {
fn(io _) // <-- the root tree, a combinator with label `fn`
// ^ ^-- eraser node
// '----- a variable, representing one half of a wire
io = @io_print_char(::char::i @io_print_char(::char::v _))
// ^-- pair ^^^^^^^^^ ^^^^^^^^^
// global net reference extrinsic function node
}
// more global net definitions; here serving the role of constants
::char::i { 105 }
::char::v { 118 }
::char::nl { 10 }
// ^^-- external value node
```
Ivy programs run on the @ivm[IVM].
================================================
FILE: docs/ivy_ivm/ivy_ivm.typ
================================================
#import "/lib.typ": *
= Ivy and the IVM
Vine compiles to @ivy[Ivy], a low-level interaction-combinator programming language.
Ivy code runs on the @ivm[IVM], a performant interaction combinator runtime.
#let children = (
"ivy.typ",
"interaction_system.typ",
"ivm.typ",
"extrinsics.typ",
"statistics.typ",
)
================================================
FILE: docs/ivy_ivm/statistics.typ
================================================
#import "/lib.typ": *
= Statistics <statistics>
The IVM collects various statistics during execution.
The Vine and Ivy CLIs display these statistics after running a program.
Let's take a look at a sample stat block, section by section.
=== Interactions
```iv
Interactions
Total 11_106_946
Annihilate 4_319_083
Commute 33_750
Copy 2_378_685
Erase 315_132
Expand 556_910
Call 3_227_767
Branch 275_619
```
`Total` shows the total number of interactions performed in the execution of the program.
This measures how much "work" was done,
in a deterministic and universal way;
the same program will always have the exact same interaction count,
no matter what machine it is run on.
The other numbers break down the @interaction-system[various types of interactions].
=== Memory
```iv
Memory
Heap 784 B
Allocated 242_850_688 B
Freed 242_850_688 B
```
`Heap` shows the greatest size of the runtime's heap over the course of the program, measured in bytes.
In this case, it never needed to use more than a kilobyte of heap space throughout the entire program.
`Allocated` shows the total number of bytes allocated through the program,
and `Freed` shows the total number of bytes freed.
These numbers should always match;
if they differ, that indicates that there was a vicious circle in the interaction net.
In this case, `Allocated` and `Freed` are much greater than `Heap`;
this shows that the evaluator was reusing its memory buffer very effectively.
(This is very common for the IVM.)
These numbers are deterministic when the program is executed sequentially,
but can vary when executed in parallel
(since the OS's thread scheduling is non-deterministic).
=== Performance
```vi
Performance
Time 175 ms
Speed 63_375_794 IPS
```
`Time` is the amount of time elapsed over the execution of the program.
`Speed` is the speed of the execution,
measured in IPS (interactions per second),
and equal to `Interactions / Time`.
== Parallel Statistics
Some statistics only apply to parallel execution.
=== Workload
```vi
Workload
Workers 16
Active 16
Minimum 312_096
Average 694_184
Maximum 855_071
Moved 111
```
`Workers` is the number of worker threads available to the IVM.
`Active` is the number of worker threads that were used.
`Minimum`, `Average`, and `Maximum` describe the statistics of
the number of interactions performed by each active worker.
`Moved` is the number of active pairs that were moved between workers.
=== Performance
```vi
Performance
Time 19 ms
Speed 569_167_395 IPS
Working 230 ms
Rate 48_201_985 IPS
```
`Time` and `Speed` are the same as in sequential execution.
`Working` is the total of the amounts of time each worker was active.
`Rate` is the average speed of an individual worker,
and equal to `Interactions / Working`.
================================================
FILE: docs/lib.typ
================================================
#import "deps/hyptyp/hyptyp.typ"
#import "deps/typsitter/typsitter.typ"
#import hyptyp: t
#let theme(theme, fg, fgl, bg) = {
let comment = color.mix(space: rgb, (fg, 50%), (bg, 50%))
let keyword = color.mix(space: oklab, (theme, 80%), (fg, 20%));
let vague = fgl;
let special = color.mix(space: oklab, (theme, 50%), (fg, 40%), (white, 10%))
let string = color.mix(space: oklab, (theme, 60%), (fg, 30%), (blue, 10%))
(
"fg": fg,
"bg": bg,
"string": string,
"comment": comment,
"keyword": keyword,
"operator": keyword,
"constant": special,
"variable.builtin": special,
"type": special,
"function": special,
"punctuation": vague,
"namespace": vague,
)
}
#let theme-bright = rgb("#46c676")
#let theme-dim = rgb("#169646")
#let white = rgb("#d6dde0")
#let dawn = rgb("#bdc3c7")
#let dusk = rgb("#252830")
#let black = rgb("#151820")
#let dawn-white = color.mix(space: rgb, (dawn, 50%), (white, 50%))
#let dusk-black = color.mix(space: rgb, (dusk, 50%), (black, 50%))
#let dawn-grey = color.mix(space: rgb, (dawn, 75%), (black, 25%))
#let dusk-grey = color.mix(space: rgb, (dusk, 75%), (white, 25%))
#let dark-theme = theme(theme-bright, dawn, dawn-grey, dusk-black);
#let light-theme = theme(theme-dim, dusk, dusk-grey, dawn-white);
#let pdf-theme = theme(theme-dim, dusk, dusk-grey, dawn-white);
#let issue = number => link("https://github.com/VineLang/vine/issues/" + str(number))[\##number]
#let vi_ = (prefix, suffix, raw) => {
set box(outset: (y: 2pt), inset: (x: 2pt), radius: 2pt)
set text(font: "Atkinson Hyperlegible Mono")
typsitter.render(
pdf-theme,
block: false, lang: "vine",
html_support: true,
prefix: prefix, suffix: suffix,
raw.text,
)
}
#let vi = vi_.with("", "")
#let expr = vi_.with("const x =", ";")
#let ty = vi_.with("type x = ", ";")
#let pat = vi_.with("fn x(", ") {}")
#let fn = vi_.with("fn ", "() {}")
#let op = vi_.with("1 ", " 1")
#let vstr = vi_.with("\"", "\"")
#let src = (file, line: none) => {
let url = "https://github.com/VineLang/vine/tree/main/" + file
let label = file
if line != none {
url += "#L" + str(line)
label += ":" + str(line)
}
t.a(class: "src", href: url)[#raw(label)]
}
#let todo-counter = counter("todo")
#let todo = (desc) => [
#context {
let id = "todo-" + str(todo-counter.get().at(0))
[#t.span(class: "todo", id: id)[\[TODO: #desc\]] #metadata((id: id, desc: desc)) <todo>]
}
#todo-counter.step()
]
#let todos = context {
let todos = query(<todo>)
if todos != () {
[=== TODO]
list(
..for todo in todos {
([
#link(hyptyp.slug.at(todo.location()) + "#" + todo.value.id)[#todo.value.desc]
(#raw(hyptyp.slug.at(todo.location())))
],)
}
)
}
}
================================================
FILE: docs/main.typ
================================================
#import "/lib.typ": *
#import hyptyp: t
#import "img.typ"
#include "deps/typsitter-langs/langs.typ"
#show: typsitter.register(pdf-theme, html_support: true)
#show raw: set block(inset: 10pt, radius: 2pt, width: 100%, breakable: false)
#show: it => context if target() == "paged" {
set page(numbering: "1")
show raw.where(block: false): box.with(outset: (y: 2pt), inset: (x: 2pt), radius: 2pt, fill: dawn-white)
it
} else {
it
}
#set text(font: "Atkinson Hyperlegible", size: 11pt)
#show raw: set text(font: "Atkinson Hyperlegible Mono", size: 11pt)
#show ref: it => {
let el = it.element
if target() != "html" and el != none {
show: underline.with(stroke: theme-dim)
show: link.with(el.location())
it.supplement
" (page "
numbering(
"1",
..counter(page).at(el.location())
)
")"
} else {
it
}
}
#hyptyp.resource("/theme.css", read("theme.css"))
#hyptyp.resource("/root.css", read("root.css"))
#hyptyp.resource("/typsitter.css", {
typsitter.theme-css(dark-theme)
"@media (prefers-color-scheme: light) {\n"
typsitter.theme-css(light-theme)
"\n}"
})
#hyptyp.resource("/index.html", slug: "/", read("landing.html"))
#img.resources
#let site = root-docs => hyptyp.show-site(
root: if root-docs { "root/root.typ" } else { "docs.typ" },
root-slug: if root-docs { "/root/" } else { "/docs/" },
path-to-slug: site => path => if root-docs { "" } else { "/docs" } + (hyptyp.defaults.path-to-slug)(site)(path),
sidebar-header: site => _ => {
if root-docs {
t.a(class: "logo", href: "/docs/")[#t.img(class: "logo", src: "/logo.svg")]
t.p[#t.a( href: "/docs/features/root")[« About the Root Library]]
} else {
t.a(class: "logo", href: "/")[#t.img(class: "logo", src: "/logo.svg")]
}
},
head-extra: site => _ => {
t.link(rel: "stylesheet", href: "/typsitter.css")
t.link(rel: "stylesheet", href: "/theme.css")
if root-docs {
t.link(rel: "stylesheet", href: "/root.css")
}
img.icons
}
)([])
#context if target() == "html" {
t.html([
#for root-docs in (false, true) {
site(root-docs)
}
])
} else {
site(false)
}
================================================
FILE: docs/root.css
================================================
#sidebar, .children {
li::before {
content: "·";
font-weight: 900;
font-family: "Atkinson Hyperlegible Mono";
}
li:not(:has(.current)) ol {
display: none;
}
& ol {
margin: 0;
}
}
h3 {
margin-bottom: 0;
}
h3 + h1 {
margin-top: 0;
}
h2 {
border-top: 2px solid color-mix(in srgb, var(--fg-grey) 33%, transparent);
padding-top: .5em;
}
h2 a[href^="#"] {
text-decoration: none;
}
:is(h1, h2, h3) {
display: flex;
justify-content: space-between;
code {
&::before, &::after {
content: "" !important;
}
}
}
#prev-next {
display: none;
}
.children {
display: none;
}
.src {
align-self: center;
font-size: .8rem;
text-decoration: none;
text-align: right;
color: var(--fg-grey);
padding: .45rem;
padding-right: 0;
}
================================================
FILE: docs/starting/hello_world.typ
================================================
#import "/lib.typ": *
= `Hello, world!` <hello-world>
Let's run our first Vine program!
```vi
// hello_world.vi
pub fn main(&io: &IO) {
io.println("Hello, world!");
}
```
We can run this with:
```bash
vine run hello_world.vi
```
You should see something like the following:
```iv
Hello, world!
Interactions
Total 341
Annihilate 180
Commute 0
Copy 23
Erase 47
Expand 36
Call 41
Branch 14
Memory
Heap 640 B
Allocated 7_216 B
Freed 7_216 B
Performance
Time 0 ms
Speed 10_740_157 IPS
```
At the top, notice that it successfully printed `Hello, world!`.
At the bottom, you'll also see several @statistics[_statistics_] printed out.
You don't need to worry about them for now.
If you want to disable them, you can use `--no-stats`.
Let's break down what just happened.
#let p0 = vi_.with("", "() {}")
#let p1 = vi_.with("", " fn main() {}")
#let p2 = vi_.with("fn main", "{}")
#let p3 = vi_.with("fn main()", "")
#let p4 = vi_.with("", "()")
#let p5 = vi_.with("io.println", "")
- #p0[`fn main`]: declares a function, named #fn[`main`]
- #p1[`pub`]: makes it public
- #p2[`(&io: &IO)`]: it takes a single parameter:
- #ty[`&IO`]: of type #ty[`&IO`]
- #pat[`&io`]: to be dereferenced and bound to the variable #pat[`io`]
- #p3[`{ ... }`]: in the function body
- #p4[`io.println`]: uses the #fn[`println`] method on #ty[`IO`]
- #p5[`("Hello, world!")`]: calls it with the string #vstr[`Hello, world!`]
We'll go into this in more detail in future chapters.
Every Vine program must contain a #vi[`pub fn main(&io: &IO) { ... }`]
("a public function `main` that takes a reference to IO").
================================================
FILE: docs/starting/installation.typ
================================================
#import "/lib.typ": *
= Installation <installation>
Make sure you have #link("https://www.rust-lang.org/tools/install")[Rust] installed.
```bash
cargo install --git https://github.com/VineLang/vine --locked
```
You can head over to the @hello-world[next page] to write your first Vine program.
If you want to install even more things first, check out the section on @editor[editor configuration].
================================================
FILE: docs/starting/starting.typ
================================================
#import "/lib.typ": *
= Getting Started
Let's get started!
Once you've @installation[installed Vine],
we'll take a look at a basic @hello-world[Hello, world!] program.
#let children = (
"installation.typ",
"hello_world.typ",
)
================================================
FILE: docs/theme.css
================================================
:root {
--theme: light-dark(#169646, #46c676);
--white: #d6dde0;
--dawn: #bdc3c7;
--dusk: #252830;
--black: #151820;
}
@media(prefers-color-scheme: light) {
img.logo {
filter: url("data:image/svg+xml;charset=utf-8;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxmaWx0ZXIgaWQ9IngiPjxmZUNvbG9yTWF0cml4IGluPSJTb3VyY2VHcmFwaGljIiB0eXBlPSJtYXRyaXgiIGNvbG9yLWludGVycG9sYXRpb24tZmlsdGVycz0ic1JHQiIgdmFsdWVzPSIwIDAgMCAwIC4wODcgMCAwIDAgMCAuNTg5IDAgMCAwIDAgLjI3NSAwIDAgMCAxIDAiIC8+PC9maWx0ZXI+PC9zdmc+#x");
}
}
#sidebar a.logo {
display: flex;
justify-content: center;
height: 8rem;
margin-top: -.666rem;
}
code.ts {
background: none;
}
.todo {
color: red;
font-style: italic;
&:target {
font-weight: bold;
}
}
#sidebar {
scrollbar-gutter: stable;
}
================================================
FILE: docs/tooling/cli.typ
================================================
#import "/lib.typ": *
= Using the CLI
== Building <building>
You can build a Vine program with `vine build`,
which outputs an @ivy[Ivy] file.
`vine build` takes a path to the main Vine program to run.
You can supply additional library paths with `--lib <path>`.
You can enable @debug[debug mode] with `--debug`.
== Running
You can build and run a Vine program with `vine run`.
All of the @building[build options] apply.
Passing `--workers <n>` or `-w <n>` will
execute the program in parallel on `n` threads.
Passing `--breadth-first` will run the program in breadth-first mode,
where at each step, every possible interaction is performed in parallel.
This allowing measuring the
the number of parallel steps needed,
which corresponds to the
#link("https://en.wikipedia.org/wiki/Analysis_of_parallel_algorithms#Definitions")[_depth_]
of the computation.
This gives an upper bound on the speedup that could be seen from a parallel machine.
The flags `--depth` and `-d` can thus be used as aliases.
By default, the runtime is limited to 4 GB of memory.
You can configure the size of the runtime's heap with `--heap`.
If your program runs out of memory,
consider specifying a larger heap size such as `--heap 16G`.
== REPL
Vine's CLI also features a @repl[REPL].
================================================
FILE: docs/tooling/debug.typ
================================================
#import "/lib.typ": *
= Debug Mode <debug>
Vine programs can be run in debug mode by passing the `--debug` flag.
In debug mode, any function can log to the console by calling #expr[`debug::log`].
```vi
// add.vi
pub fn main(&io: &IO) {
io.println("12 + 34 = {add(12, 34)}");
}
fn add(x: N32, y: N32) -> N32 {
debug::log("adding {x} and {y}");
let result = x + y;
debug::log("calculated {result}");
result
}
```
```
$ vine run add.vi --debug
[add.vi:8:3] adding 12 and 34
[add.vi:10:3] calculated 46
12 + 34 = 46
```
When not running in debug mode, #expr[`debug::log`] is a no-op:
```
$ vine run add.vi
12 + 34 = 46
```
Errors can be reported with #expr[`debug::error`], which will print the error message along with a backtrace:
```vi
// divide.vi
pub fn main(&io: &IO) {
io.println("1 / 0 = {divide(1, 0)}")
}
fn divide(x: N32, y: N32) -> N32 {
if y == 0 {
return debug::error("attempted to divide by zero");
}
x / y
}
```
```
$ vine run divide.vi --debug
ERROR: attempted to divide by zero
@ #divide::divide (divide.vi:9:12)
@ #divide::main (divide.vi:4:24)
Error: the net did not return its `IO` handle
```
When not running in debug mode, only the runtime's error will be printed:
```
$ vine run divide.vi
Error: the net did not return its `IO` handle
```
================================================
FILE: docs/tooling/editor.typ
================================================
#import "/lib.typ": *
= Editor Configuration <editor>
== VSCode
Install the #link("https://marketplace.visualstudio.com/items?itemName=VineLang.vine")[Vine extension] from the VSCode Marketplace.
For VSCode forks, check the latest version on the marketplace and download
```
https://marketplace.visualstudio.com/_apis/public/gallery/publishers/vinelang/vsextensions/vine/<VERSION>/vspackage
```
You can then install this with "Extensions: Install from VSIX".
=== LSP Configuration
```json
// .vscode/settings.json
{
// list all of your top-level Vine programs (globs are supported)
"vine.entrypoints": ["src/main.vi"]
}
```
Make sure you reload the window after changing this file.
== Helix
```toml
# ~/.config/helix/languages.toml
[[language]]
name = "vine"
scope = "source.vine"
file-types = ["vi"]
language-servers = ["vine"]
formatter = { command = "vine", args = ["fmt"] }
grammar = "vine"
auto-format = true
comment-tokens = ["//"]
[[grammar]]
name = "vine"
source.path = "/absolute/path/to/vine-repo/lsp/tree-sitter-vine/"
```
To build the tree sitter grammar,
make sure you have #link("https://nodejs.org/en/download/package-manager")[Node.js] installed,
and run
```bash
cd lsp/tree-sitter-vine
npm i
npx tree-sitter generate
hx --grammar build
mkdir -p ~/.config/helix/runtime/queries
ln -s /absolute/path/to/vine-repo/lsp/tree-sitter-vine/queries ~/.config/helix/runtime/queries/vine
```
=== LSP Configuration
```toml
# your-project/.helix/languages.toml
[language-server.vine]
command = "vine"
# list all of your top-level Vine programs (globs are supported)
args = ["lsp", "--", "src/main.vi"]
```
================================================
FILE: docs/tooling/repl.typ
================================================
#import "/lib.typ": *
= The REPL <repl>
Vine has a
#link("https://en.wikipedia.org/wiki/Read-eval-print_loop")[REPL],
launched with `vine repl`.
When you launch the REPL, it should look like this:
```vi
$ vine repl
let io: IO = <IO>;
>
```
At the bottom is the prompt (`>`)
where you can enter Vine code.
Above that is a listing of all of the variables in scope,
with their types and values.
The session starts with a variable `io` of type `IO`
containing an IO handle.
Entering an expression will evaluate it,
print the result,
and display another prompt.
```vi
$ vine repl
let io: IO = <IO>;
> 12 + 34
46
let io: IO = <IO>;
>
```
You can also enter statements:
```vi
$ vine repl
let io: IO = <IO>;
> let x = 12;
let io: IO = <IO>;
let x: N32 = 12;
> x += 34;
let io: IO = <IO>;
let x: N32 = 46;
>
```
And you can use the IO handle:
```vi
$ vine repl
let io: IO = <IO>;
> io.println("Hello, world!");
Hello, world!
let io: IO = <IO>;
> let response = io.prompt("enter a response: ");
enter a response: Hello, REPL!
let io: IO = <IO>;
let response: Option[String] = Some("Hello, REPL!");
>
```
The REPL also supports a few commands; you can type `/help` to see a list of commands.
You can use `/clear` to unbind local variables, ending their scope.
```vi
$ vine repl
let io: IO = <IO>;
> let x = 46;
let io: IO = <IO>;
let x: N32 = 46;
> /clear x
let io: IO = <IO>;
>
```
You can pass `--lib <path>` to load libraries (for example, a Vine program you want to troubleshoot):
```vi
$ vine repl --lib vine/examples/fib_repl.vi
let io: IO = <IO>;
> use #fib_repl::fib;
let io: IO = <IO>;
> fib(7)
13
```
================================================
FILE: docs/tooling/tooling.typ
================================================
#import "/lib.typ": *
= Tooling
#let children = (
"editor.typ",
"cli.typ",
"repl.typ",
"debug.typ",
)
================================================
FILE: dprint.json
================================================
{
"indentWidth": 2,
"lineWidth": 100,
"markdown": {
"textWrap": "always",
"lineWidth": 80,
"emphasisKind": "asterisks"
},
"exec": {
"commands": [{
"command": "target/release/vine fmt",
"exts": ["vi"]
}, {
"command": "rustfmt",
"exts": ["rs"]
}]
},
"excludes": ["tests/fail/*", "tests/repl/*", "tests/fmt/*", "tests/snaps/*"],
"plugins": [
"https://plugins.dprint.dev/g-plane/pretty_yaml-v0.5.0.wasm@eae6b4db51bb656ec28b0cbf3875d30352688fd3c6131dd2646b6f680fff833a",
"https://plugins.dprint.dev/json-0.19.3.wasm@e89b5f3b5d73712f1b1ca017bce9cdf67de30a7d0dba47807809e0d262b01fb9",
"https://plugins.dprint.dev/markdown-0.17.8.wasm@3c810df549d80bc7682697734bb33a4041d0350b63ed6c17020bdec0fb138eab",
"https://plugins.dprint.dev/toml-0.6.2.wasm@a0451faef6244604ec8bfe046bfc293aff62527d09320cfaf53370f118c03bcd",
"https://plugins.dprint.dev/typescript-0.95.8.wasm@bba0e941684fc8446984a9a55ce4c4e8d5bfd3c6330435a0cd64c9e092cb0231",
"https://plugins.dprint.dev/exec-0.5.0.json@8d9972eee71fa1590e04873540421f3eda7674d0f1aae3d7c788615e7b7413d0"
]
}
================================================
FILE: flake.nix
================================================
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
rust-overlay = {
url = "github:oxalica/rust-overlay";
inputs.nixpkgs.follows = "nixpkgs";
};
crane.url = "github:ipetkov/crane";
typix = {
url = "github:loqusion/typix";
inputs.nixpkgs.follows = "nixpkgs";
};
typsitter = {
url = "github:TendrilsCompute/typsitter";
inputs.nixpkgs.follows = "nixpkgs";
};
hyptyp = {
url = "github:TendrilsCompute/hyptyp";
inputs.nixpkgs.follows = "nixpkgs";
};
treefmt-nix = {
url = "github:numtide/treefmt-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs =
{
nixpkgs,
flake-utils,
rust-overlay,
crane,
typix,
typsitter,
hyptyp,
treefmt-nix,
...
}:
flake-utils.lib.eachDefaultSystem (
system:
let
pkgs = import nixpkgs {
inherit system;
overlays = [ rust-overlay.overlays.default ];
};
rustToolchain = pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml;
craneLib = (crane.mkLib pkgs).overrideToolchain (_: rustToolchain);
self.cli = import ./cli/cli.nix {
inherit pkgs craneLib;
};
self.tests = import ./tests/tests.nix {
inherit
pkgs
flake-utils
rustToolchain
craneLib
;
inherit (self) cli;
};
self.grammars = import ./lsp/grammars.nix {
inherit pkgs;
};
self.docs = import ./docs/docs.nix {
inherit
system
pkgs
flake-utils
hyptyp
typix
typsitter
;
inherit (self) grammars cli;
};
self.style = import ./style.nix {
inherit pkgs treefmt-nix;
inherit (self) cli;
};
in
builtins.foldl' pkgs.lib.attrsets.recursiveUpdate {
packages.default = self.cli.packages.vine;
devShells.default = craneLib.devShell {
name = "vine-dev";
packages = [
pkgs.cargo-expand
pkgs.nushell
pkgs.nodejs_24
pkgs.tree-sitter
];
};
} (builtins.attrValues self)
);
}
================================================
FILE: ivm/Cargo.toml
================================================
[package]
name = "ivm"
version = "0.0.0"
edition = "2024"
[dependencies]
[lints.clippy]
absolute_paths = "warn"
================================================
FILE: ivm/src/addr.rs
================================================
use core::{
fmt::{self, Debug},
ptr,
};
use crate::{
global::Global,
word::{AtomicWord, Word},
};
/// The address of a port, a pointer of only-externally-known interpretation.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
pub struct Addr(pub *const ());
unsafe impl Send for Addr {}
unsafe impl Sync for Addr {}
impl Addr {
pub const NULL: Addr = Addr(ptr::null());
/// Casts this address to an `&'ivm AtomicWord`.
///
/// ## Safety
/// This address must be a pointer into the heap of the `IVM<'ivm>`.
#[inline(always)]
pub(crate) unsafe fn as_word<'ivm>(self) -> &'ivm AtomicWord {
unsafe { &*self.0.cast() }
}
/// Casts this address to an `&'ivm Global<'ivm>`.
///
/// ## Safety
/// This address must be the address of a `Port<'ivm>` with `Tag::Global`.
#[inline(always)]
pub unsafe fn as_global<'ivm>(self) -> &'ivm Global<'ivm> {
unsafe { &*self.0.cast() }
}
const HALF_BIT: u64 = 0b1000;
#[inline(always)]
fn map_addr(self, f: impl FnOnce(u64) -> u64) -> Self {
Addr(Word::from_ptr(self.0).map_bits(f).ptr())
}
/// Returns the address of the other word in a two-word allocation.
#[inline(always)]
pub fn other_half(self) -> Self {
self.map_addr(|x| x ^ Self::HALF_BIT)
}
/// Returns the address of the left word in a two-word allocation.
#[inline(always)]
pub fn left_half(self) -> Self {
self.map_addr(|x| x & !Self::HALF_BIT)
}
}
impl Debug for Addr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:012?}", self.0)
}
}
================================================
FILE: ivm/src/allocator.rs
================================================
use crate::{
addr::Addr,
heap::{Heap, Node},
ivm::IVM,
port::{Port, Tag},
wire::Wire,
word::Word,
};
pub(crate) struct Allocator<'ivm> {
/// The heap memory backing this allocator.
pub(crate) heap: &'ivm Heap,
/// The head pointer of this allocator's freelist.
pub(crate) head: Addr,
/// The next unallocated index in the `heap`.
pub(crate) next: usize,
}
impl<'ivm> Allocator<'ivm> {
pub(crate) fn new(heap: &'ivm Heap) -> Self {
Allocator { heap, head: Addr::NULL, next: 0 }
}
pub(crate) fn shrink(&mut self) {
self.heap = self.heap.slice(self.next..);
self.next = 0;
}
pub(crate) fn fork(&mut self, index: usize, count: usize) -> Self {
self.shrink();
let length = self.heap.0.len();
let fork_point = length - length / (count + index + 1);
let fork = self.heap.slice(fork_point..);
self.heap = self.heap.slice(..fork_point);
Self::new(fork)
}
}
impl<'ivm, 'ext> IVM<'ivm, 'ext> {
/// Allocates a new binary node with a given `tag` and `label`.
///
/// ## Safety
/// `tag` must be the tag of a binary node, and `label` must comply with its
/// requirements.
#[inline(always)]
pub unsafe fn new_node(&mut self, tag: Tag, label: u16) -> (Port<'ivm>, Wire<'ivm>, Wire<'ivm>) {
unsafe {
let addr = self.alloc_node();
(Port::new(tag, label, addr), Wire::from_addr(addr), Wire::from_addr(addr.other_half()))
}
}
/// Allocates a new wire, returning both of its ends.
pub fn new_wire(&mut self) -> (Wire<'ivm>, Wire<'ivm>) {
unsafe {
let addr = self.alloc_node();
self.free_wire(Wire::from_addr(addr.other_half()));
(Wire::from_addr(addr), Wire::from_addr(addr))
}
}
/// Allocates two new wires, returning both of their ends.
pub fn new_wires(&mut self) -> ((Wire<'ivm>, Wire<'ivm>), (Wire<'ivm>, Wire<'ivm>)) {
unsafe {
let addr = self.alloc_node();
(
(Wire::from_addr(addr), Wire::from_addr(addr)),
(Wire::from_addr(addr.other_half()), Wire::from_addr(addr.other_half())),
)
}
}
/// Frees the memory backing a wire.
#[inline]
pub(crate) fn free_wire(&mut self, wire: Wire<'ivm>) {
self.stats.mem_free += 1;
unsafe {
let free = Word::from_bits(!0b111);
let addr = wire.addr();
addr.as_word().store(free);
if addr.other_half().as_word().load() == free {
let addr = addr.left_half();
if addr.as_word().compare_exchange(free, Word::from_ptr(self.alloc.head.0)).is_ok() {
self.alloc.head = addr;
}
}
}
}
/// Allocates a two-word region of memory within the heap.
#[inline]
fn alloc_node(&mut self) -> Addr {
self.stats.mem_alloc += 2;
let addr = if self.alloc.head != Addr::NULL {
let addr = self.alloc.head;
let next = unsafe { Addr(addr.as_word().load().ptr()) };
self.alloc.head = next;
addr
} else {
self.stats.mem_heap += 2;
let index = self.alloc.next;
self.alloc.next += 1;
if let Some(node) = self.alloc.heap.0.get(index) {
Addr(node as *const Node as *const ())
} else {
self.alloc = self.alloc_pool.pop().expect("OOM");
return self.alloc_node();
}
};
unsafe { addr.as_word().store(Word::from_bits(0)) }
unsafe { addr.other_half().as_word().store(Word::from_bits(0)) }
addr
}
}
================================================
FILE: ivm/src/ext.rs
================================================
//! External values and functions, whose semantics live outside interaction
//! combinators.
#![allow(nonstandard_style)]
use core::{
fmt::{self, Debug},
marker::PhantomData,
ops::{Deref, DerefMut},
};
use crate::{ivm::IVM, port::Tag, wire::Wire, word::Word};
macro_rules! trait_alias {
($($(#[$attr:meta])* $vis:vis trait $name:ident = ($($trait:tt)*);)*) => {$(
$(#[$attr])*
$vis trait $name<'ivm>: $($trait)* {}
impl<'ivm, T> $name<'ivm> for T where T: $($trait)* {}
)*};
}
trait_alias! {
/// A trait alias for `ExtVal -> (ExtVal, ExtVal)` extrinsic functions.
pub trait ExtSplitFn = (
for<'a, 'ext> Fn(&'a mut IVM<'ivm, 'ext>, ExtVal<'ivm>, Wire<'ivm>, Wire<'ivm>) + Send + Sync + 'ivm
);
/// A trait alias for `(ExtVal, ExtVal) -> ExtVal` extrinsic functions.
pub trait ExtMergeFn = (
for<'a, 'ext> Fn(&'a mut IVM<'ivm, 'ext>, ExtVal<'ivm>, ExtVal<'ivm>, Wire<'ivm>) + Send + Sync + 'ivm
);
}
pub struct Extrinsics<'ivm> {
ext_split_fns: Vec<Box<dyn ExtSplitFn<'ivm>>>,
ext_merge_fns: Vec<Box<dyn ExtMergeFn<'ivm>>>,
/// Number of registered extrinsic types.
ext_tys: u16,
/// An always-present extrinsic type of n32 numbers.
n32_ext_ty: ExtTy<'ivm, u32>,
phantom: PhantomData<fn(&'ivm ()) -> &'ivm ()>,
}
impl Default for Extrinsics<'_> {
fn default() -> Self {
let n32_ext_ty = ExtTy::new_unchecked(ExtTyId::new(0, true));
Self {
ext_split_fns: Vec::new(),
ext_merge_fns: Vec::new(),
ext_tys: 1,
n32_ext_ty,
phantom: PhantomData,
}
}
}
impl<'ivm> Extrinsics<'ivm> {
pub const MAX_EXT_FN_COUNT: usize = 0x3FFF;
pub const MAX_EXT_TY_COUNT: usize = 0x7FFF;
pub fn new_split_ext_fn(&mut self, f: impl ExtSplitFn<'ivm>) -> ExtFn<'ivm> {
assert!(self.ext_split_fns.len() < Self::MAX_EXT_FN_COUNT);
let ext_fn = ExtFn::new_split(self.ext_split_fns.len());
let f = Box::new(f) as Box<dyn ExtSplitFn<'ivm>>;
self.ext_split_fns.push(f);
ext_fn
}
pub fn new_merge_ext_fn(&mut self, f: impl ExtMergeFn<'ivm>) -> ExtFn<'ivm> {
assert!(self.ext_merge_fns.len() < Self::MAX_EXT_FN_COUNT);
let ext_fn = ExtFn::new_merge(self.ext_merge_fns.len());
let f = Box::new(f) as Box<dyn ExtMergeFn<'ivm>>;
self.ext_merge_fns.push(f);
ext_fn
}
pub fn new_ext_ty<T: ExtTyCast<'ivm>>(&mut self) -> ExtTy<'ivm, T> {
assert!((self.ext_tys as usize) < Self::MAX_EXT_TY_COUNT);
self.ext_tys += 1;
ExtTy::new_unchecked(ExtTyId::new(self.ext_tys, T::COPY))
}
pub fn n32_ext_ty(&self) -> ExtTy<'ivm, u32> {
self.n32_ext_ty
}
pub fn ext_val_as_n32(&self, x: ExtVal<'ivm>) -> Option<u32> {
self.n32_ext_ty().unwrap_ext_val(x)
}
pub fn get_ext_split_fn(&self, ext_fn: ExtFn<'ivm>) -> &dyn ExtSplitFn<'ivm> {
self.ext_split_fns.get(ext_fn.index()).expect("unknown extrinsic function")
}
pub fn get_ext_merge_fn(&self, ext_fn: ExtFn<'ivm>) -> &dyn ExtMergeFn<'ivm> {
self.ext_merge_fns.get(ext_fn.index()).expect("unknown extrinsic function")
}
}
/// An external value with a 45-bit payload.
///
/// The 64-bit value is laid out as follows:
/// - top 16 bits are the extrinsic's type id [`ExtTyId`].
/// - the next 45 bits are the payload.
/// - the last 3 bits are `Tag::ExtVal as u16` for compatibility with [`Port`].
///
/// [`Port`]: crate::ivm::Port
#[derive(Clone, Copy)]
pub struct ExtVal<'ivm>(Word, PhantomData<fn(&'ivm ()) -> &'ivm ()>);
impl<'ivm> ExtVal<'ivm> {
const PAYLOAD_MASK: u64 = 0x0000_FFFF_FFFF_FFF8;
/// Creates an `ExtVal` from the raw bits.
///
/// ## Safety
/// The bits must be a valid representation of an `ExtVal`.
#[inline(always)]
pub unsafe fn from_bits(bits: Word) -> Self {
Self(bits, PhantomData)
}
/// Returns the raw bits of this value.
#[inline(always)]
pub fn bits(&self) -> Word {
self.0
}
/// Creates a new `ExtVal` with a given type and 45-bit payload.
///
/// The provided 45-bit payload can only occupy bits 48..3 (inclusive) of the
/// provided `u64` value. That is, the highest 16 bits and lowest 3 bits must
/// be set to zero.
#[inline(always)]
pub fn new(ty_id: ExtTyId<'ivm>, payload: Word) -> Self {
debug_assert!(
payload.bits() & !Self::PAYLOAD_MASK == 0,
"ExtVal::new with non-payload bits set"
);
unsafe {
Self::from_bits(payload.map_bits(|payload| {
((ty_id.bits() as u64) << 48) | (payload & Self::PAYLOAD_MASK) | (Tag::ExtVal as u64)
}))
}
}
/// Returns the type id of this value.
#[inline(always)]
pub fn ty_id(&self) -> ExtTyId<'ivm> {
ExtTyId::from_bits((self.0.bits() >> 48) as u16)
}
/// Returns the unshifted 45-bit payload of this value.
///
/// The payload is located between bits 48 and 3 in the returned `u64`.
/// The highest 16 bits and lowest 3 bits are guaranteed to be zero.
#[inline(always)]
fn payload(&self) -> Word {
self.0.map_bits(|bits| bits & Self::PAYLOAD_MASK)
}
/// Interprets this extrinsic value as a `T` without checking its [`ExtTyId`].
///
/// # Safety
///
/// This [`ExtVal`]'s payload must be valid to cast into a `T` using
/// [`ExtTyCast::from_payload`].
pub unsafe fn cast<T: ExtTyCast<'ivm>>(self) -> T {
unsafe { T::from_payload(self.payload()) }
}
}
impl<'ivm> Debug for ExtVal<'ivm> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "ExtVal({:?})", self.0.bits())
}
}
pub struct ExtTy<'ivm, T>(ExtTyId<'ivm>, PhantomData<fn(T) -> T>);
impl<'ivm, T> Clone for ExtTy<'ivm, T> {
fn clone(&self) -> Self {
*self
}
}
impl<'ivm, T> Copy for ExtTy<'ivm, T> {}
impl<'ivm, T> ExtTy<'ivm, T> {
pub fn new_unchecked(ty_id: ExtTyId<'ivm>) -> Self {
Self(ty_id, PhantomData)
}
#[inline(always)]
pub fn ty_id(self) -> ExtTyId<'ivm> {
self.0
}
/// Interprets this extrinsic value as a `T` through [`ExtTy<'ivm, T>`].
///
/// If `ext`'s [`ExtVal::ty_id`] does not match [`self::ty_id`], this returns
/// `None`.
#[inline(always)]
pub fn unwrap_ext_val(self, ext: ExtVal<'ivm>) -> Option<T>
where
T: ExtTyCast<'ivm>,
{
if ext.ty_id() == self.0 { Some(unsafe { T::from_payload(ext.payload()) }) } else { None }
}
/// Converts `value` into an [`ExtVal`] with `self` as the type id.
#[inline(always)]
pub fn wrap_ext_val(self, value: T) -> ExtVal<'ivm>
where
T: ExtTyCast<'ivm>,
{
ExtVal::new(self.ty_id(), T::into_payload(value))
}
}
/// A trait describing how to convert between an [`ExtVal`] and a `Self`.
///
/// Types which can be converted to/from a 45-bit payload, can implement
/// `ExtTyCast`.
pub trait ExtTyCast<'ivm> {
const COPY: bool;
/// Converts `Self` into an unshifted [`ExtVal`] 45-bit payload.
///
/// The returned value must not have bits outside of [`ExtVal::PAYLOAD_MASK`].
/// That is, the highest 16 bits and lowest 3 bits must be set to zero.
fn into_payload(self) -> Word;
/// Casts an [`ExtVal`]'s payload to a `Self`.
///
/// # Safety
///
/// `payload` must have been returned from [`into_payload`].
unsafe fn from_payload(payload: Word) -> Self;
}
impl<'ivm> ExtTyCast<'ivm> for u32 {
const COPY: bool = true;
#[inline(always)]
fn into_payload(self) -> Word {
Word::from_bits((self as u64) << 3)
}
#[inline(always)]
unsafe fn from_payload(payload: Word) -> u32 {
(payload.bits() >> 3) as u32
}
}
impl<'ivm> ExtTyCast<'ivm> for f32 {
const COPY: bool = true;
#[inline(always)]
fn into_payload(self) -> Word {
Word::from_bits((self.to_bits() as u64) << 3)
}
#[inline(always)]
unsafe fn from_payload(payload: Word) -> f32 {
f32::from_bits((payload.bits() >> 3) as u32)
}
}
/// Used for the `IO` extrinsic type.
impl<'ivm> ExtTyCast<'ivm> for () {
const COPY: bool = false;
#[inline(always)]
fn into_payload(self) -> Word {
Word::from_bits(0)
}
#[inline(always)]
unsafe fn from_payload(_payload: Word) {}
}
#[derive(Default)]
#[repr(align(8))]
pub struct Aligned<T>(T);
#[derive(Default)]
#[repr(transparent)]
pub struct Boxed<T>(Box<Aligned<T>>);
impl<T> From<T> for Boxed<T> {
fn from(value: T) -> Self {
Self(Box::new(Aligned(value)))
}
}
impl<T> Deref for Boxed<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0.0
}
}
impl<T> DerefMut for Boxed<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0.0
}
}
impl<T> Boxed<T> {
fn ptr(self) -> *mut Aligned<T> {
Box::into_raw(self.0)
}
pub fn into_inner(self) -> T {
(*self.0).0
}
fn into_aligned_ptr(value: T) -> *mut Aligned<T> {
Box::into_raw(Box::new(Aligned(value)))
}
unsafe fn from_aligned_ptr(ptr: *mut Aligned<T>) -> Self {
Self(unsafe { Box::from_raw(ptr) })
}
}
impl<'ivm> ExtTyCast<'ivm> for f64 {
const COPY: bool = false;
#[inline(always)]
fn into_payload(self) -> Word {
Word::from_ptr(Boxed::into_aligned_ptr(self).cast())
}
#[inline(always)]
unsafe fn from_payload(payload: Word) -> Self {
*unsafe { Boxed::from_aligned_ptr(payload.ptr().cast_mut().cast()) }
}
}
impl<'ivm, T> ExtTyCast<'ivm> for Boxed<T> {
const COPY: bool = false;
#[inline(always)]
fn into_payload(self) -> Word {
Word::from_ptr(self.ptr().cast())
}
#[inline(always)]
unsafe fn from_payload(payload: Word) -> Self {
unsafe { Boxed::from_aligned_ptr(payload.ptr().cast_mut().cast()) }
}
}
/// The type id of an external value.
///
/// The highest bit specifies whether it is copyable. If a non-copyable
/// [`ExtVal`] is copied or erased during reduction, an error flag will
/// be set on the [`IVM`].
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ExtTyId<'ivm>(u16, PhantomData<&'ivm mut &'ivm ()>);
impl<'ivm> ExtTyId<'ivm> {
const COPY_BIT: u16 = 0x8000;
#[inline(always)]
fn new(ty_id: u16, copy: bool) -> Self {
Self::from_bits(ty_id | if copy { Self::COPY_BIT } else { 0 })
}
#[inline(always)]
fn from_bits(bits: u16) -> Self {
Self(bits, PhantomData)
}
#[inline(always)]
fn bits(self) -> u16 {
self.0
}
#[inline(always)]
pub fn is_copy(self) -> bool {
self.0 & Self::COPY_BIT != 0
}
}
/// A type uniquely identifying an extrinsic function.
///
/// The highest bit denotes whether the function arguments are swapped.
/// The second-highest bit denotes whether this is a merge or split ext fn.
/// The lowest 14 bits denote an index into one of `ext_split_fns` or
/// `ext_merge_fns`.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ExtFn<'ivm>(u16, PhantomData<fn(&'ivm ()) -> &'ivm ()>);
impl<'ivm> ExtFn<'ivm> {
const SWAP_BIT: u16 = 0x8000;
const MERGE_BIT: u16 = 0x4000;
const ID_MASK: u16 = 0x3FFF;
#[inline(always)]
fn new_split(id: usize) -> Self {
Self(id as u16, PhantomData)
}
#[inline(always)]
fn new_merge(id: usize) -> Self {
Self(id as u16 | Self::MERGE_BIT, PhantomData)
}
#[inline(always)]
fn index(&self) -> usize {
(self.0 & Self::ID_MASK) as usize
}
#[inline(always)]
pub fn bits(&self) -> u16 {
self.0
}
#[inline(always)]
pub fn is_swapped(&self) -> bool {
self.0 & Self::SWAP_BIT != 0
}
#[inline(always)]
pub fn is_merge(&self) -> bool {
self.0 & Self::MERGE_BIT != 0
}
#[inline(always)]
pub fn swapped(&self) -> Self {
Self(self.0 ^ Self::SWAP_BIT, PhantomData)
}
}
impl<'ivm> Debug for ExtFn<'ivm> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "ExtFn({:?})", self.0)
}
}
#[derive(Debug, Clone, Copy)]
pub struct OpaqueExtFn {
pub label: u16,
pub swap: bool,
}
================================================
FILE: ivm/src/flags.rs
================================================
/// Error flags set during interactions.
#[derive(Clone, Copy, Default, PartialEq, Eq)]
pub struct Flags {
/// A non-copyable extrinsic was copied.
pub ext_copy: bool,
/// A non-copyable extrinsic was erased.
pub ext_erase: bool,
/// An extrinsic function encountered an unspecified error.
pub ext_generic: bool,
}
impl Flags {
pub fn success(self) -> bool {
self == Self::default()
}
}
================================================
FILE: ivm/src/global.rs
================================================
use crate::instruction::Instructions;
/// A global definition of a net.
#[derive(Debug, Default)]
pub struct Global<'ivm> {
/// The name of this global; to be used for debugging and readback only.
pub name: String,
/// The set of all labels used in this net (including indirectly).
pub labels: LabelSet,
/// The instructions for constructing this net.
pub instructions: Instructions<'ivm>,
/// An internal implementation detail used in ivy's serialization logic.
#[doc(hidden)]
pub flag: usize,
}
/// A set of labels used in a global.
///
/// Because of the representation used here, `self.has(u16::MAX)` will always
/// return false, even if `self.add(u16::MAX)` is called.
#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub struct LabelSet {
/// The least label greater than all labels in this set.
cap: u16,
/// A bitset, containing at least `cap` bits (equivalently, at least `ceil(cap
/// / 64)` entries).
bits: Vec<u64>,
}
impl LabelSet {
/// The empty set.
pub const NONE: Self = Self { cap: 0, bits: Vec::new() };
/// Inserts a label into this set.
#[inline]
pub fn add(&mut self, label: u16) {
if label == u16::MAX {
return;
}
self.cap = self.cap.max(label + 1);
let index = (label >> 6) as usize;
let bit = label & 63;
if index >= self.bits.len() {
self.bits.resize(index + 1, 0);
}
self.bits[index] |= 1 << bit;
}
/// Returns whether `label` is in this set.
#[inline(always)]
pub fn has(&self, label: u16) -> bool {
if label >= self.cap {
return false;
}
let index = (label >> 6) as usize;
let bit = label & 63;
unsafe { self.bits.get_unchecked(index) & 1 << bit != 0 }
}
/// Inserts all labels in `other` into this set.
#[inline]
pub fn union(&mut self, other: &LabelSet) {
self.cap = self.cap.max(other.cap);
for (a, b) in self.bits.iter_mut().zip(other.bits.iter()) {
*a |= b;
}
if other.bits.len() > self.bits.len() {
self.bits.extend_from_slice(&other.bits[self.bits.len()..])
}
}
}
================================================
FILE: ivm/src/heap.rs
================================================
use core::{alloc::Layout, mem::transmute, ptr, slice::SliceIndex};
use std::alloc::alloc;
use crate::word::AtomicWord;
/// The heap, the primary memory of an IVM.
#[repr(transparent)]
pub struct Heap(pub(crate) [Node]);
/// An aligned region of memory storing two atomic words.
#[repr(align(16), C)]
pub(crate) struct Node(pub AtomicWord, pub AtomicWord);
/// The maximum size of heap to attempt to allocate.
pub const HEAP_SIZE_BYTES: usize = if cfg!(miri) {
1 << 16
} else if cfg!(target_pointer_width = "64") {
1 << 32
} else {
1 << 30
};
impl Heap {
/// Allocates a new heap, as large as possible.
pub fn new() -> Box<Self> {
let mut bytes = HEAP_SIZE_BYTES;
while bytes != 0 {
if let Some(heap) = Self::with_size(bytes) {
return heap;
}
bytes /= 2;
}
panic!("heap allocation failed")
}
/// Attempts to allocate a new heap with a given size in bytes.
///
/// Returns `None` if the allocation fails.
pub fn with_size(bytes: usize) -> Option<Box<Self>> {
let nodes = bytes / 16;
if nodes == 0 {
return None;
}
unsafe {
let ptr = alloc(Layout::array::<Node>(nodes).unwrap()) as *mut Node;
if ptr.is_null() {
return None;
}
Some(Box::from_raw(ptr::slice_from_raw_parts_mut(ptr, nodes) as *mut Heap))
}
}
pub(crate) fn slice(&self, range: impl SliceIndex<[Node], Output = [Node]>) -> &Self {
unsafe { transmute::<&[Node], &Heap>(&self.0[range]) }
}
}
================================================
FILE: ivm/src/instruction.rs
================================================
use core::fmt::{self, Debug};
use crate::{
ext::OpaqueExtFn,
ivm::IVM,
port::{Port, Tag},
};
/// A list of instructions to create a net.
#[derive(Debug)]
pub struct Instructions<'ivm> {
/// The next unused register value; equivalently, the number of used
/// registers.
pub(crate) next_register: Register,
/// The actual list of instructions; see [`Instructions::push`] for the safety
/// requirements of these instructions.
pub(crate) instructions: Vec<Instruction<'ivm>>,
}
impl<'ivm> Default for Instructions<'ivm> {
fn default() -> Self {
Self { next_register: Register::new(1), instructions: Default::default() }
}
}
impl<'ivm> Instructions<'ivm> {
/// Returns a new, unused register.
#[inline(always)]
pub fn new_register(&mut self) -> Register {
let register = self.next_register;
self.next_register.byte_offset += REGISTER_SIZE;
register
}
/// Appends an instruction to the list.
///
/// ## Safety
/// All registers used in the instruction must either be `Register::ROOT` or
/// have been returned by `self.new_register()`.
#[inline(always)]
pub unsafe fn push(&mut self, instruction: Instruction<'ivm>) {
self.instructions.push(instruction);
}
#[inline(always)]
pub fn instructions(&self) -> &[Instruction<'ivm>] {
&self.instructions
}
}
/// An instruction to create a small sub-net.
///
/// It is not unsafe to construct invalid an invalid instruction, but it is
/// unsafe to add it to [`Instructions`] (which is assumed to consist only of
/// valid instructions).
#[derive(Debug)]
pub enum Instruction<'ivm> {
/// Create a nilary node.
///
/// ## Validity
/// Its port must truly be nilary (and thus safe to clone).
Nilary(Register, Port<'ivm>),
/// Create a binary node with a given tag and label.
///
/// ## Validity
/// For this instruction to be safely pushed to `Instructions`, its tag must
/// be that of a binary node, and its label must comply with the tag's
/// requirements.
Binary(Tag, u16, Register, Register, Register),
InertLink(Register, Register),
InertNode(OpaqueExtFn, Register, Register, Register),
}
/// A "register" of an [`Instruction`], used to identify pairs of ports to link.
///
/// Serves as an index into the `registers` field in an [`IVM`].
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Register {
/// The byte offset corresponding to the index; equivalent to `index *
/// REGISTER_SIZE`.
///
/// Stored as a `u32` to keep the size of an [`Instruction`] small.
pub(crate) byte_offset: u32,
}
/// The size of the data referenced by a register.
const REGISTER_SIZE: u32 = 8;
impl Register {
/// Register 0 is reserved for the root of a net.
pub const ROOT: Register = Register::new(0);
/// Creates a new register corresponding to the given index.
#[inline(always)]
const fn new(index: usize) -> Self {
Register { byte_offset: index as u32 * REGISTER_SIZE }
}
/// Returns the index of this register.
#[inline(always)]
pub fn index(&self) -> usize {
(self.byte_offset / REGISTER_SIZE) as usize
}
}
impl Debug for Register {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Register({})", self.index())
}
}
impl<'ivm, 'ext> IVM<'ivm, 'ext> {
/// Links the given `port` to the given `register`.
///
/// ## Safety
/// `register.index() < self.registers.len()`
#[inline]
unsafe fn link_register(&mut self, register: Register, port: Port<'ivm>) {
unsafe {
debug_assert!(register.index() < self.registers.len());
let register = &mut *(&mut *self.registers as *mut [_] as *mut Option<Port<'ivm>>)
.byte_offset(register.byte_offset as isize);
if let Some(got) = register.take() {
self.link(port, got);
} else {
*register = Some(port);
}
}
}
/// Execute [`Instructions`], linking the net's root to `port`.
pub fn execute(&mut self, instructions: &Instructions<'ivm>, port: Port<'ivm>) {
let needed_registers = instructions.next_register.index().max(1);
if needed_registers > self.registers.len() {
self.registers.resize_with(needed_registers, || None)
}
unsafe { self.link_register(Register::ROOT, port) };
for i in &instructions.instructions {
unsafe {
match *i {
Instruction::Nilary(r, ref p) => self.link_register(r, p.clone()),
Instruction::Binary(tag, label, p0, p1, p2) => {
let node = self.new_node(tag, label);
self.link_register(p0, node.0);
self.link_register(p1, Port::new_wire(node.1));
self.link_register(p2, Port::new_wire(node.2));
}
Instruction::InertLink(p0, p1) => {
let wires = self.new_wires();
self.link_register(p0, Port::new_wire(wires.0.0));
self.link_register(p1, Port::new_wire(wires.1.0));
self.inert_links.push((Port::new_wire(wires.0.1), Port::new_wire(wires.1.1)));
}
Instruction::InertNode(label, p0, p1, p2) => {
let wire_prim = self.new_wire();
let (wire_aux0, wire_aux1) = self.new_wires();
self.link_register(p0, Port::new_wire(wire_prim.0));
self.link_register(p1, Port::new_wire(wire_aux0.0));
self.link_register(p2, Port::new_wire(wire_aux1.0));
self.inert_nodes.push((
label,
Port::new_wire(wire_prim.1),
Port::new_wire(wire_aux0.1),
Port::new_wire(wire_aux1.1),
));
}
}
}
}
// Using registers an odd number of times will cause severe logic errors.
if cfg!(debug_assertions) {
for r in &self.registers {
assert!(r.is_none());
}
}
}
}
================================================
FILE: ivm/src/interact.rs
================================================
use crate::{
ivm::IVM,
port::{Port, PortRef, Tag},
wire::Wire,
};
macro_rules! sym {
($a: pat, $b: pat) => {
($a, $b) | ($b, $a)
};
($a: pat) => {
($a, $a)
};
}
impl<'ivm, 'ext> IVM<'ivm, 'ext> {
/// Link two ports.
pub fn link(&mut self, a: Port<'ivm>, b: Port<'ivm>) {
use Tag::*;
match (a.tag(), b.tag()) {
(Wire, _) => self.link_wire(unsafe { a.as_wire() }, b),
(_, Wire) => self.link_wire(unsafe { b.as_wire() }, a),
sym!(Global | Erase) => self.stats.erase += 1,
sym!(ExtVal | Erase) => {
if (a.tag() == ExtVal && !unsafe { a.as_ext_val() }.ty_id().is_copy())
|| (b.tag() == ExtVal && !unsafe { b.as_ext_val() }.ty_id().is_copy())
{
self.flags.ext_erase = true;
}
self.stats.erase += 1
}
sym!(Comb) | sym!(ExtFn) if a.label() == b.label() => self.active_fast.push((a, b)),
sym!(Global, _) | sym!(Comb | ExtFn | Branch) => self.active_slow.push((a, b)),
sym!(Erase, _) | sym!(ExtVal, _) => self.active_fast.push((a, b)),
}
}
/// Link a wire and a port.
pub fn link_wire(&mut self, a: Wire<'ivm>, b: Port<'ivm>) {
let b = self.follow(b);
if unsafe { Port::new_wire(a.clone()).bits() == b.bits() } {
self.free_wire(a);
return;
}
if let Some(s) = a.swap_target(Some(unsafe { b.clone() })) {
self.free_wire(a);
self.link(s, b);
}
}
/// Link two_wires.
#[inline(always)]
pub fn link_wire_wire(&mut self, a: Wire<'ivm>, b: Wire<'ivm>) {
self.link_wire(a, Port::new_wire(b));
}
/// Follows as many `Wire`s with active targets as currently possible.
#[inline]
pub fn follow(&mut self, mut p: Port<'ivm>) -> Port<'ivm> {
while p.tag() == Tag::Wire {
if let Some(q) = unsafe { p.clone().as_wire() }.load_target() {
self.free_wire(unsafe { p.as_wire() });
p = q;
} else {
break;
}
}
p
}
/// Non-destructively follows as many `Wire`s with active targets as currently
/// possible.
#[inline]
pub fn follow_ref<'a>(&self, p: &'a Port<'ivm>) -> PortRef<'a, 'ivm> {
let mut p = PortRef::from(p);
while p.tag() == Tag::Wire {
if let Some(q) = unsafe { p.clone().as_wire() }.load_target() {
p = PortRef::from_port(q);
} else {
break;
}
}
p
}
/// Execute an interaction between two principal ports.
pub(crate) fn interact(&mut self, a: Port<'ivm>, b: Port<'ivm>) {
use Tag::*;
match ((a.tag(), a), (b.tag(), b)) {
sym!((Wire, _), _) | sym!((Erase | ExtVal, _)) => unreachable!(),
sym!((Global, c), (Comb, d)) if !unsafe { c.as_global() }.labels.has(d.label()) => {
self.copy(c, d)
}
sym!((Global, c), (_, p)) => self.expand(c, p),
((Comb, a), (Comb, b)) | ((ExtFn, a), (ExtFn, b)) | ((Branch, a), (Branch, b))
if a.label() == b.label() =>
{
self.annihilate(a, b)
}
sym!((Erase, n), (_, b)) => self.copy(n, b),
sym!((ExtVal, n), (Comb, b)) => {
let x = unsafe { n.as_ext_val() };
if !x.ty_id().is_copy() {
self.flags.ext_copy = true;
self.copy(Port::ERASE, b);
} else {
self.copy(n, b);
}
}
((Comb | ExtFn | Branch, a), (Comb | ExtFn | Branch, b)) => self.commute(a, b),
sym!((ExtFn, f), (ExtVal, v)) => self.call(f, v),
sym!((Branch, b), (ExtVal, v)) => self.branch(b, v),
}
}
// Note that all of the following functions are technically unsafe -- they
// require the ports they are passed to have certain tags. They are not marked
// as `unsafe` to reduce noise, and as such must be kept private.
fn expand(&mut self, c: Port<'ivm>, p: Port<'ivm>) {
self.stats.expand += 1;
let global = unsafe { c.as_global() };
self.execute(&global.instructions, p);
}
fn annihilate(&mut self, a: Port<'ivm>, b: Port<'ivm>) {
self.stats.annihilate += 1;
let (a1, a2) = unsafe { a.aux() };
let (b1, b2) = unsafe { b.aux() };
self.link_wire_wire(a1, b1);
self.link_wire_wire(a2, b2);
}
fn copy(&mut self, n: Port<'ivm>, b: Port<'ivm>) {
self.stats.copy += 1;
let (x, y) = unsafe { b.aux() };
self.link_wire(x, unsafe { n.clone() });
self.link_wire(y, n);
}
fn commute(&mut self, a: Port<'ivm>, b: Port<'ivm>) {
self.stats.commute += 1;
let a_1 = unsafe { self.new_node(a.tag(), a.label()) };
let a_2 = unsafe { self.new_node(a.tag(), a.label()) };
let b_1 = unsafe { self.new_node(b.tag(), b.label()) };
let b_2 = unsafe { self.new_node(b.tag(), b.label()) };
let (a_0_1, a_0_2) = unsafe { a.aux() };
let (b_0_1, b_0_2) = unsafe { b.aux() };
self.link_wire_wire(a_1.1, b_1.1);
self.link_wire_wire(a_1.2, b_2.1);
self.link_wire_wire(a_2.1, b_1.2);
self.link_wire_wire(a_2.2, b_2.2);
self.link_wire(a_0_1, b_1.0);
self.link_wire(a_0_2, b_2.0);
self.link_wire(b_0_1, a_1.0);
self.link_wire(b_0_2, a_2.0);
}
fn call(&mut self, f: Port<'ivm>, lhs: Port<'ivm>) {
let ext_fn = unsafe { f.as_ext_fn() };
if ext_fn.is_merge() {
let (rhs_wire, out) = unsafe { f.aux() };
if let Some(rhs) = rhs_wire.load_target()
&& rhs.tag() == Tag::ExtVal
{
self.stats.call += 1;
self.free_wire(rhs_wire);
let func = self.extrinsics.get_ext_merge_fn(ext_fn);
let (arg0, arg1) = if ext_fn.is_swapped() {
unsafe { (rhs.as_ext_val(), lhs.as_ext_val()) }
} else {
unsafe { (lhs.as_ext_val(), rhs.as_ext_val()) }
};
(func)(self, arg0, arg1, out);
return;
}
let new_fn = unsafe { self.new_node(Tag::ExtFn, ext_fn.swapped().bits()) };
self.link_wire(rhs_wire, new_fn.0);
self.link_wire(new_fn.1, lhs);
self.link_wire_wire(new_fn.2, out);
} else {
self.stats.call += 1;
let func = self.extrinsics.get_ext_split_fn(ext_fn);
let (out0, out1) = unsafe { f.aux() };
let arg = unsafe { lhs.as_ext_val() };
(func)(self, arg, out0, out1);
}
}
fn branch(&mut self, b: Port<'ivm>, v: Port<'ivm>) {
self.stats.branch += 1;
let val = self.extrinsics.ext_val_as_n32(unsafe { v.as_ext_val() });
let (a, o) = unsafe { b.aux() };
let (b, z, p) = unsafe { self.new_node(Tag::Branch, 0) };
self.link_wire(a, b);
match val {
Some(val) => {
let (y, n) = if val == 0 { (z, p) } else { (p, z) };
self.link_wire(n, Port::ERASE);
self.link_wire_wire(o, y);
}
None => {
self.flags.ext_generic = true;
self.link_wire(z, Port::ERASE);
self.link_wire(p, Port::ERASE);
self.link_wire(o, Port::ERASE);
}
}
}
}
================================================
FILE: ivm/src/ivm.rs
================================================
use core::mem;
use std::time::Instant;
use crate::{
allocator::Allocator,
ext::{Extrinsics, OpaqueExtFn},
flags::Flags,
heap::Heap,
port::Port,
stats::Stats,
};
/// An Interaction Virtual Machine.
pub struct IVM<'ivm, 'ext> {
/// Execution statistics of this IVM.
pub stats: Stats,
/// Error flags set during interactions.
pub flags: Flags,
pub(crate) extrinsics: &'ext Extrinsics<'ivm>,
pub(crate) alloc: Allocator<'ivm>,
pub(crate) alloc_pool: Vec<Allocator<'ivm>>,
/// Active pairs that should be "fast" to process (generally, those which do
/// not allocate memory).
pub(crate) active_fast: Vec<(Port<'ivm>, Port<'ivm>)>,
/// Active pairs that may be "slow" to process (generally, those which may
/// allocate memory).
pub(crate) active_slow: Vec<(Port<'ivm>, Port<'ivm>)>,
pub inert_links: Vec<(Port<'ivm>, Port<'ivm>)>,
pub inert_nodes: Vec<(OpaqueExtFn, Port<'ivm>, Port<'ivm>, Port<'ivm>)>,
/// Used by [`IVM::execute`].
pub(crate) registers: Vec<Option<Port<'ivm>>>,
}
impl<'ivm, 'ext> IVM<'ivm, 'ext> {
/// Creates a new IVM with a given heap.
pub fn new(heap: &'ivm Heap, extrinsics: &'ext Extrinsics<'ivm>) -> Self {
Self::new_from_allocator(Allocator::new(heap), extrinsics)
}
pub(crate) fn new_from_allocator(
alloc: Allocator<'ivm>,
extrinsics: &'ext Extrinsics<'ivm>,
) -> Self {
Self {
alloc,
extrinsics,
alloc_pool: Vec::new(),
registers: Vec::new(),
active_fast: Vec::new(),
active_slow: Vec::new(),
inert_links: Vec::new(),
inert_nodes: Vec::new(),
stats: Stats::default(),
flags: Flags::default(),
}
}
/// Normalize all nets in this IVM.
pub fn normalize(&mut self) {
let start = Instant::now();
loop {
self.do_fast();
if let Some((a, b)) = self.active_slow.pop() {
self.interact(a, b)
} else {
break;
}
}
self.stats.time_clock += start.elapsed();
}
pub(crate) fn do_fast(&mut self) {
while let Some((a, b)) = self.active_fast.pop() {
self.interact(a, b)
}
}
/// Normalize all nets in breadth-first traversal.
///
/// This is useful to get the depth (longest critical path) of the computation
/// to understand the parallelism of the program.
pub fn normalize_breadth_first(&mut self) {
let start = Instant::now();
let mut work = vec![];
loop {
mem::swap(&mut work, &mut self.active_fast);
work.append(&mut self.active_slow);
if work.is_empty() {
break;
}
for (a, b) in work.drain(..) {
self.interact(a, b);
}
self.stats.depth += 1;
}
self.stats.time_clock += start.elapsed();
}
}
================================================
FILE: ivm/src/lib.rs
================================================
//! The Interaction Virtual Machine, an interaction combinator runtime.
//!
//! The [`IVM`] struct is the root of the API of this crate
#![cfg_attr(miri, feature(strict_provenance_lints))]
#![cfg_attr(miri, deny(fuzzy_provenance_casts, lossy_provenance_casts))]
#![warn(clippy::std_instead_of_core)]
mod ivm;
mod parallel;
pub use ivm::*;
pub mod addr;
pub mod ext;
pub mod flags;
pub mod global;
pub mod heap;
pub mod instruction;
pub mod port;
pub mod stats;
pub mod wire;
mod allocator;
mod interact;
mod word;
================================================
FILE: ivm/src/parallel.rs
================================================
use core::{mem, ptr};
use std::{
sync::{Condvar, Mutex, OnceLock},
thread::{self, Thread},
time::Instant,
};
use crate::{ivm::IVM, port::Port};
impl<'ivm, 'ext> IVM<'ivm, 'ext> {
pub fn normalize_parallel(&mut self, threads: usize) {
self.do_fast();
let shared = Vec::from_iter((0..threads).map(|_| Shared::default()));
let start = Instant::now();
thread::scope(|s| {
let workers = Vec::from_iter((0..threads).map(|i| {
let dispatch = thread::current();
let alloc = self.alloc_pool.pop().unwrap_or(self.alloc.fork(i, threads));
let shared = &shared[i];
let mut ivm = IVM::new_from_allocator(alloc, self.extrinsics);
if i == 0 {
ivm.active_slow = mem::take(&mut self.active_slow);
}
s.spawn(move || Worker { ivm, shared, dispatch }.execute());
WorkerHandle { shared }
}));
Dispatch { active: workers, idle: vec![] }.execute();
});
self.stats.time_clock += start.elapsed();
if self.stats.worker_min == 0 {
self.stats.worker_min = u64::MAX;
}
for mut shared in shared {
let ivm = shared.ivm_return.take().unwrap();
self.stats.workers_spawned += 1;
if ivm.stats.interactions() != 0 {
self.alloc_pool.push(ivm.alloc);
self.stats.workers_used += 1;
self.stats.worker_max = self.stats.worker_max.max(ivm.stats.interactions());
self.stats.worker_min = self.stats.worker_min.min(ivm.stats.interactions());
self.stats += ivm.stats;
}
}
}
}
#[derive(Default)]
struct Msg<'ivm> {
kind: MsgKind,
pairs: Pairs<'ivm>,
}
#[derive(Default)]
#[repr(align(256))]
struct Shared<'ivm, 'ext> {
ivm_return: OnceLock<IVM<'ivm, 'ext>>,
msg: Mutex<Msg<'ivm>>,
condvar: Condvar,
}
type Pairs<'ivm> = Vec<(Port<'ivm>, Port<'ivm>)>;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
enum MsgKind {
#[default]
None,
Dispatch,
WorkerShare,
WorkerIdle,
Exit,
}
struct Worker<'w, 'ivm, 'ext> {
ivm: IVM<'ivm, 'ext>,
shared: &'w Shared<'ivm, 'ext>,
dispatch: Thread,
}
const ERA_LENGTH: u32 = 512;
impl<'w, 'ivm, 'ext> Worker<'w, 'ivm, 'ext> {
fn execute(mut self) {
self.work();
self.shared.ivm_return.set(self.ivm).ok().unwrap();
}
fn work(&mut self) {
'work: loop {
let mut watermark = self.ivm.active_slow.len();
let start = Instant::now();
for _ in 0..ERA_LENGTH {
self.ivm.do_fast();
if let Some((a, b)) = self.ivm.active_slow.pop() {
watermark = watermark.min(self.ivm.active_slow.len());
self.ivm.interact(a, b);
} else {
self.ivm.stats.time_total += start.elapsed();
let mut msg = self.shared.msg.lock().unwrap();
while msg.pairs.is_empty() {
msg.kind = MsgKind::WorkerIdle;
self.dispatch.unpark();
msg = self.shared.condvar.wait(msg).unwrap();
if msg.kind == MsgKind::Exit {
return;
}
}
msg.kind = MsgKind::None;
mem::swap(&mut self.ivm.active_slow, &mut msg.pairs);
continue 'work;
}
}
self.ivm.stats.time_total += start.elapsed();
if watermark != 0 && watermark != self.ivm.active_slow.len() {
let mut msg = self.shared.msg.lock().unwrap();
if msg.kind == MsgKind::None {
debug_assert!(msg.pairs.is_empty());
let move_count = self.ivm.active_slow.len() - watermark;
self.ivm.stats.work_move += move_count as u64;
debug_assert!(move_count != 0);
msg.pairs.reserve(move_count);
unsafe {
ptr::copy_nonoverlapping(
self.ivm.active_slow.as_mut_ptr().add(watermark),
msg.pairs.as_mut_ptr(),
move_count,
);
self.ivm.active_slow.set_len(watermark);
msg.pairs.set_len(move_count);
}
debug_assert!(!msg.pairs.is_empty());
mem::swap(&mut msg.pairs, &mut self.ivm.active_slow);
msg.kind = MsgKind::WorkerShare;
self.dispatch.unpark();
}
}
}
}
}
struct WorkerHandle<'w, 'ivm, 'ext> {
shared: &'w Shared<'ivm, 'ext>,
}
struct Dispatch<'w, 'ivm, 'ext> {
active: Vec<WorkerHandle<'w, 'ivm, 'ext>>,
idle: Vec<WorkerHandle<'w, 'ivm, 'ext>>,
}
impl<'w, 'ivm, 'ext> Dispatch<'w, 'ivm, 'ext> {
fn execute(mut self) {
loop {
let mut i = 0;
let mut share_ready = false;
while i < self.active.len() {
let worker = &self.active[i];
let mut msg = worker.shared.msg.lock().unwrap();
if msg.kind == MsgKind::WorkerIdle {
debug_assert!(msg.pairs.is_empty());
drop(msg);
self.idle.push(self.active.remove(i));
continue;
} else if msg.kind == MsgKind::WorkerShare {
if self.idle.is_empty() {
share_ready = true;
} else {
debug_assert!(!msg.pairs.is_empty());
let waiting = self.idle.pop().unwrap();
let mut idle_msg = waiting.shared.msg.lock().unwrap();
debug_assert!(idle_msg.kind == MsgKind::WorkerIdle && idle_msg.pairs.is_empty());
idle_msg.kind = MsgKind::Dispatch;
mem::swap(&mut msg.pairs, &mut idle_msg.pairs);
waiting.shared.condvar.notify_one();
msg.kind = MsgKind::None;
self.active.insert(i + 1, waiting);
i += 1;
}
}
i += 1;
}
if self.active.is_empty() {
break;
}
if !self.idle.is_empty() && share_ready {
continue;
}
thread::park()
}
for thread in self.idle {
thread.shared.msg.lock().unwrap().kind = MsgKind::Exit;
thread.shared.condvar.notify_one();
}
}
}
================================================
FILE: ivm/src/port.rs
================================================
use crate::{
addr::Addr,
ext::{ExtFn, ExtVal},
global::Global,
wire::{Wire, WireRef},
word::{NonZeroWord, Word},
};
use core::{
fmt::{self, Debug},
marker::PhantomData,
mem::transmute,
ops::Deref,
ptr,
};
/// A port in the interaction net.
///
/// The interpretation of a port is determined by its *tag*, stored in the
/// bottom three bits, and accessible with [`Port::tag`].
///
/// All tags other than `ExtVal` divide the remaining bits of a port as follows:
/// - the top 16 bits are its *label*, accessible with [`Port::label`]
/// - the next 45 bits are the non-alignment bits of its *address*, a pointer
/// aligned to 8 bytes, accessible with [`Port::addr`]
/// - the bottom 3 bits are its tag, as always
///
/// The interpretation of these fields once again depends on the tag; see each
/// tag's documentation for details.
#[repr(transparent)]
pub struct Port<'ivm>(NonZeroWord, PhantomData<fn(&'ivm ()) -> &'ivm ()>);
/// The 3-bit tag of a [`Port`], determining its interpretation.
///
/// Bit pattern `0b000` is invalid and used by various systems to represent
/// non-port values.
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum Tag {
/// This port is a wrapper around a [`Wire`]. Its address is that of the wire,
/// and its label is zero.
Wire = 1,
/// This port is a reference to a global net. Its address is an
/// `&'ivm`[`Global`].
Global = 2,
/// This port is the principal port of an eraser node. Its address and label
/// are both zero.
Erase = 3,
/// This port is a wrapper around an [`ExtVal`]. Its address and label are
/// semantically irrelevant; `ExtVal` uses all the non-tag bits
/// indiscriminantly.
ExtVal = 4,
/// This port is the principal port of a binary combinator. Its address points
/// to a node in the heap, and its label is the label of the combinator.
Comb = 5,
/// This port is the principal port of a binary external function node. Its
/// address points to a node in the heap, and its label is the [`ExtFn`] of
/// this node.
ExtFn = 6,
/// This port is the principal port of a binary branch node. Its address
/// points to a node in the heap, and its label is zero.
///
/// Though branch nodes are semantically trinary, at runtime the trinary node
/// `?(a b c)` is represented with two binary nodes: `?(?(a b) c)`.
Branch = 7,
}
impl<'ivm> Port<'ivm> {
/// The principal port of an eraser node.
pub const ERASE: Self = unsafe { Port::from_bits(Word::from_bits(Tag::Erase as u64)) };
/// Constructs a port from its bit representation.
///
/// ## Safety
/// The bits of `word` must comply with the restrictions of a `Port`.
#[inline(always)]
pub(crate) const unsafe fn from_bits(word: Word) -> Self {
unsafe { Self(NonZeroWord::new_unchecked(word), PhantomData) }
}
pub(crate) fn bits(&self) -> Word {
self.0.get()
}
/// Constructs a port from its bit representation, if its tag is valid.
///
/// ## Safety
/// The bits of `word` must either comply with the restrictions of a `Port`,
/// or have an invalid tag.
#[inline(always)]
pub(crate) unsafe fn option_from_bits(word: Word) -> Option<Self> {
unsafe { if word.bits() & 0b111 == 0 { None } else { Some(Self::from_bits(word)) } }
}
/// Constructs a new port from its components.
///
/// ## Safety
/// `label` and `addr` must comply with the requirements of `tag`.
#[inline(always)]
pub unsafe fn new(tag: Tag, label: u16, addr: Addr) -> Self {
unsafe {
let port = Port::from_bits(
Word::from_ptr(addr.0).map_bits(|addr| label as (u64) << 48 | addr | tag as u64),
);
debug_assert_eq!(port.addr(), addr);
port
}
}
/// Accesses the tag of this port.
#[inline(always)]
pub fn tag(&self) -> Tag {
unsafe { transmute::<u8, Tag>((self.0.get().bits() & 0b111) as u8) }
}
/// Accesses the label of this port. The interpretation of this value depends
/// on the tag.
#[inline(always)]
pub fn label(&self) -> u16 {
(self.0.get().bits() >> 48) as u16
}
/// Accesses the address of this port. The interpretation of this value
/// depends on the tag.
#[inline(always)]
pub fn addr(&self) -> Addr {
Addr(self.0.get().map_bits(|x| x & 0x0000_FFFF_FFFF_FFF8).ptr())
}
/// Constructs a new [`Tag::Global`] port.
#[inline(always)]
pub fn new_global(global: &'ivm Global) -> Self {
unsafe { Self::new(Tag::Global, 0, Addr(global as *const Global as *const ())) }
}
/// Constructs a new [`Tag::Wire`] port.
#[inline(always)]
pub fn new_wire(wire: Wire<'ivm>) -> Self {
unsafe { Self::new(Tag::Wire, 0, wire.addr()) }
}
/// Constructs a new [`Tag::ExtVal`] port.
#[inline(always)]
pub fn new_ext_val(val: ExtVal) -> Self {
unsafe { Self::from_bits(val.bits()) }
}
/// Unsafely clones a port by copying its bits.
///
/// ## Safety
/// At most one clone may be linked.
///
/// This can't currently cause UB (just severe logic errors), but may in the
/// future.
#[inline(always)]
pub unsafe fn clone(&self) -> Self {
unsafe { ptr::read(self) }
}
/// Get the label of this port, interpreted as an [`ExtFn`].
///
/// ## Safety
/// This port must be [`Tag::ExtFn`].
#[inline(always)]
pub unsafe fn as_ext_fn(&self) -> ExtFn<'ivm> {
unsafe {
debug_assert_eq!(self.tag(), Tag::ExtFn);
transmute::<u16, ExtFn>(self.label())
}
}
/// Get the address of this port, interpreted as an [`Wire`].
///
/// ## Safety
/// This port must be [`Tag::Wire`].
#[inline(
gitextract_yoww9v3l/
├── .gitattributes
├── .github/
│ └── workflows/
│ ├── change-base.yml
│ ├── checks.yml
│ ├── docs.yml
│ ├── integration.yml
│ └── issues.yml
├── .gitignore
├── .vscode/
│ └── settings.json
├── Cargo.toml
├── LICENSE-APACHE
├── LICENSE-MIT
├── README.md
├── cli/
│ ├── Cargo.toml
│ ├── cli.nix
│ └── src/
│ ├── bin/
│ │ ├── ivy.rs
│ │ └── vine.rs
│ ├── common.rs
│ ├── ivy_cli.rs
│ ├── lib.rs
│ └── vine_cli.rs
├── cspell.json
├── docs/
│ ├── .gitignore
│ ├── compiler/
│ │ ├── architecture.typ
│ │ ├── compiler.typ
│ │ └── sfg.typ
│ ├── docs.nix
│ ├── docs.typ
│ ├── features/
│ │ ├── conditions.typ
│ │ ├── control_flow/
│ │ │ ├── blocks.typ
│ │ │ ├── conditionals.typ
│ │ │ ├── control_flow.typ
│ │ │ └── loops.typ
│ │ ├── features.typ
│ │ ├── inverse.typ
│ │ ├── io.typ
│ │ ├── methods.typ
│ │ ├── modules.typ
│ │ ├── patterns.typ
│ │ ├── references.typ
│ │ ├── root.typ
│ │ ├── traits/
│ │ │ ├── fork_drop.typ
│ │ │ ├── intro.typ
│ │ │ ├── standard.typ
│ │ │ └── traits.typ
│ │ ├── types/
│ │ │ ├── composite.typ
│ │ │ ├── enums.typ
│ │ │ ├── primitives.typ
│ │ │ ├── standard.typ
│ │ │ ├── structs.typ
│ │ │ └── types.typ
│ │ ├── usual.typ
│ │ ├── values_spaces_places.typ
│ │ └── variables.typ
│ ├── img.typ
│ ├── ivy_ivm/
│ │ ├── extrinsics.typ
│ │ ├── interaction_system.typ
│ │ ├── ivm.typ
│ │ ├── ivy.typ
│ │ ├── ivy_ivm.typ
│ │ └── statistics.typ
│ ├── lib.typ
│ ├── main.typ
│ ├── root.css
│ ├── starting/
│ │ ├── hello_world.typ
│ │ ├── installation.typ
│ │ └── starting.typ
│ ├── theme.css
│ └── tooling/
│ ├── cli.typ
│ ├── debug.typ
│ ├── editor.typ
│ ├── repl.typ
│ └── tooling.typ
├── dprint.json
├── flake.nix
├── ivm/
│ ├── Cargo.toml
│ └── src/
│ ├── addr.rs
│ ├── allocator.rs
│ ├── ext.rs
│ ├── flags.rs
│ ├── global.rs
│ ├── heap.rs
│ ├── instruction.rs
│ ├── interact.rs
│ ├── ivm.rs
│ ├── lib.rs
│ ├── parallel.rs
│ ├── port.rs
│ ├── stats.rs
│ ├── wire.rs
│ └── word.rs
├── ivy/
│ ├── Cargo.toml
│ ├── examples/
│ │ ├── cat.iv
│ │ ├── fib_repl.iv
│ │ ├── fizzbuzz.iv
│ │ └── hihi.iv
│ └── src/
│ ├── ast.rs
│ ├── host/
│ │ ├── ext.rs
│ │ ├── readback.rs
│ │ └── serialize.rs
│ ├── host.rs
│ ├── lexer.rs
│ ├── lib.rs
│ ├── optimize/
│ │ ├── eta_reduce.rs
│ │ ├── inline_globals.rs
│ │ ├── inline_vars.rs
│ │ ├── pre_reduce.rs
│ │ └── prune.rs
│ ├── optimize.rs
│ ├── parser.rs
│ └── repl.rs
├── lsp/
│ ├── Cargo.toml
│ ├── client/
│ │ ├── .gitignore
│ │ ├── .vscodeignore
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── extension.ts
│ │ │ ├── ivy-config.json
│ │ │ ├── ivy-grammar.json
│ │ │ ├── vine-config.json
│ │ │ └── vine-grammar.json
│ │ └── tsconfig.json
│ ├── grammars.nix
│ ├── src/
│ │ └── lib.rs
│ ├── tree-sitter-ivy/
│ │ ├── .gitignore
│ │ ├── grammar.js
│ │ ├── package.json
│ │ ├── queries/
│ │ │ ├── highlights.scm
│ │ │ └── textobjects.scm
│ │ ├── test.nu
│ │ └── tree-sitter.json
│ └── tree-sitter-vine/
│ ├── .gitignore
│ ├── grammar.js
│ ├── package.json
│ ├── queries/
│ │ ├── highlights.scm
│ │ ├── injections.scm
│ │ └── textobjects.scm
│ ├── test.nu
│ └── tree-sitter.json
├── root/
│ ├── Ext.vi
│ ├── IO/
│ │ ├── File.vi
│ │ └── IO.vi
│ ├── data/
│ │ ├── Array.vi
│ │ ├── Heap.vi
│ │ ├── Iterator.vi
│ │ ├── List.vi
│ │ ├── Map.vi
│ │ ├── Set.vi
│ │ └── data.vi
│ ├── debug/
│ │ ├── Show.vi
│ │ └── debug.vi
│ ├── derive.vi
│ ├── logical/
│ │ ├── Bool.vi
│ │ ├── Default.vi
│ │ ├── Nullable.vi
│ │ ├── Option.vi
│ │ ├── Result.vi
│ │ └── logical.vi
│ ├── numeric/
│ │ ├── F32/
│ │ │ └── F32.vi
│ │ ├── F64/
│ │ │ ├── F64.vi
│ │ │ ├── common.vi
│ │ │ ├── exp.vi
│ │ │ └── ln.vi
│ │ ├── Float/
│ │ │ ├── Float.vi
│ │ │ ├── parse.vi
│ │ │ └── to_string.vi
│ │ ├── I32.vi
│ │ ├── Int.vi
│ │ ├── N32.vi
│ │ ├── N64.vi
│ │ ├── Nat/
│ │ │ ├── Nat.vi
│ │ │ └── div_rem.vi
│ │ └── numeric.vi
│ ├── ops/
│ │ ├── Index.vi
│ │ ├── Range.vi
│ │ ├── arithmetic.vi
│ │ ├── bitwise.vi
│ │ ├── comparison.vi
│ │ ├── elementwise.vi
│ │ ├── flex.vi
│ │ └── ops.vi
│ ├── prelude.vi
│ ├── rng/
│ │ ├── Pcg32.vi
│ │ └── rng.vi
│ ├── root.vi
│ ├── unicode/
│ │ ├── Char.vi
│ │ ├── String.vi
│ │ └── unicode.vi
│ └── util.vi
├── rust-toolchain.toml
├── rustfmt.toml
├── style.nix
├── tests/
│ ├── aoc_2024/
│ │ ├── README.md
│ │ ├── day_01.vi
│ │ ├── day_02.vi
│ │ ├── day_03.vi
│ │ ├── day_04.vi
│ │ ├── day_05.vi
│ │ ├── day_06.vi
│ │ ├── day_07.vi
│ │ ├── day_08.vi
│ │ ├── day_09.vi
│ │ ├── day_10.vi
│ │ ├── day_11.vi
│ │ ├── day_12.vi
│ │ ├── day_13.vi
│ │ ├── day_14.vi
│ │ ├── day_15.vi
│ │ ├── day_16.vi
│ │ ├── day_17.vi
│ │ ├── day_18.vi
│ │ ├── day_19.vi
│ │ ├── day_20.vi
│ │ ├── day_21.vi
│ │ ├── day_22.vi
│ │ ├── day_23.vi
│ │ ├── day_24.vi
│ │ ├── day_25.vi
│ │ └── input/
│ │ ├── day_01
│ │ ├── day_02
│ │ ├── day_03
│ │ ├── day_04
│ │ ├── day_05
│ │ ├── day_06
│ │ ├── day_07
│ │ ├── day_08
│ │ ├── day_09
│ │ ├── day_10
│ │ ├── day_11
│ │ ├── day_12
│ │ ├── day_13
│ │ ├── day_14
│ │ ├── day_15
│ │ ├── day_16
│ │ ├── day_17
│ │ ├── day_18
│ │ ├── day_19
│ │ ├── day_20
│ │ ├── day_21
│ │ ├── day_22
│ │ ├── day_23
│ │ ├── day_24
│ │ └── day_25
│ ├── compile/
│ │ ├── opaque_ext_fn.vi
│ │ └── pre_reduce_opaque_fn.vi
│ ├── examples/
│ │ ├── cat
│ │ ├── fib
│ │ ├── fib_repl
│ │ ├── fizzbuzz
│ │ ├── guessing_game
│ │ ├── hello_world
│ │ ├── mandelbrot
│ │ ├── mandelbrot_sixel
│ │ ├── mandelbrot_tga
│ │ ├── primeness
│ │ ├── stream_primes
│ │ ├── sub_min
│ │ └── sum_divisors
│ ├── fail/
│ │ ├── atypical.vi
│ │ ├── bad_try.vi
│ │ ├── continue_what.vi
│ │ ├── hallo_world.vi
│ │ ├── inconfigurable.vi
│ │ ├── inflexible.vi
│ │ ├── informal.vi
│ │ ├── is_not.vi
│ │ ├── loader/
│ │ │ ├── ambiguous/
│ │ │ │ └── ambiguous.vi
│ │ │ ├── ambiguous.vi
│ │ │ ├── dir/
│ │ │ │ ├── child.vi
│ │ │ │ └── dir.vi
│ │ │ ├── file.vi
│ │ │ ├── foo.vi
│ │ │ └── loader.vi
│ │ ├── occurs.vi
│ │ ├── opaque_private.vi
│ │ ├── other_dual.vi
│ │ ├── recursive_type_alias.vi
│ │ ├── unsafe_.vi
│ │ └── visibility.vi
│ ├── fmt/
│ │ ├── comment.vi
│ │ ├── match.vi
│ │ ├── objects.vi
│ │ └── uses.vi
│ ├── input/
│ │ ├── brainfuck
│ │ ├── cat
│ │ ├── empty
│ │ ├── fib_repl
│ │ ├── fib_repl_iv
│ │ ├── guessing_game
│ │ ├── lambda
│ │ └── life
│ ├── ivy/
│ │ ├── cat
│ │ ├── fib_repl
│ │ ├── fizzbuzz
│ │ └── hihi
│ ├── misc/
│ │ └── basic_test.vi
│ ├── programs/
│ │ ├── array_from_list.vi
│ │ ├── array_order.vi
│ │ ├── array_smoothsort.vi
│ │ ├── array_to_list.vi
│ │ ├── basic_diverge.vi
│ │ ├── brainfuck.vi
│ │ ├── break_result.vi
│ │ ├── centimanes.vi
│ │ ├── classify_primes.vi
│ │ ├── cli_args.vi
│ │ ├── cond_diverge.vi
│ │ ├── configurable.vi
│ │ ├── cubes.vi
│ │ ├── cyclist.vi
│ │ ├── div_by_zero.vi
│ │ ├── empty_loop.vi
│ │ ├── f32_ops.vi
│ │ ├── f32_roundabout.vi
│ │ ├── f64_no_inline.vi
│ │ ├── f64_ops.vi
│ │ ├── f64_roundabout.vi
│ │ ├── file.vi
│ │ ├── final_countdown.vi
│ │ ├── find_primes.vi
│ │ ├── heap.vi
│ │ ├── int_edges.vi
│ │ ├── invalid_extrinsics.vi
│ │ ├── inverse.vi
│ │ ├── iterator_party.vi
│ │ ├── lambda.vi
│ │ ├── lcs.vi
│ │ ├── life.vi
│ │ ├── log_brute.vi
│ │ ├── logic.vi
│ │ ├── loop_break_continue.vi
│ │ ├── loop_vi_loop.vi
│ │ ├── main.vi
│ │ ├── mandelbrot_f64.vi
│ │ ├── map_ops.vi
│ │ ├── map_test.vi
│ │ ├── maybe_set.vi
│ │ ├── n64_div_rem.vi
│ │ ├── nat_div.vi
│ │ ├── nat_edges.vi
│ │ ├── no_return.vi
│ │ ├── nothing_lasts_forever.vi
│ │ ├── opaque.vi
│ │ ├── option_party.vi
│ │ ├── par.vi
│ │ ├── pretty_div.vi
│ │ ├── primenesses.vi
│ │ ├── quine.vi
│ │ ├── regex.vi
│ │ ├── segmented_sieve.vi
│ │ ├── sieve.vi
│ │ ├── so_random.vi
│ │ ├── sort.vi
│ │ ├── specializations.vi
│ │ ├── square_case.vi
│ │ ├── the_greatest_show.vi
│ │ ├── tiny_f64.vi
│ │ ├── verbose_add.vi
│ │ └── when_break_continue.vi
│ ├── repl/
│ │ ├── F64_misc.vi
│ │ ├── N64.vi
│ │ ├── Nat.vi
│ │ ├── advanced_repl.vi
│ │ ├── basic_repl.vi
│ │ ├── distribute_inverse.vi
│ │ ├── elementwise.vi
│ │ ├── extrinsics.vi
│ │ ├── f32_to_string.vi
│ │ ├── heap.vi
│ │ ├── holes.vi
│ │ ├── i32_misc.vi
│ │ ├── index.vi
│ │ ├── misc.vi
│ │ ├── objects.vi
│ │ ├── parse_error.vi
│ │ ├── parse_floats.vi
│ │ ├── randomness.vi
│ │ ├── set.vi
│ │ ├── shadow.vi
│ │ ├── slice_and_dice.vi
│ │ └── string_ops.vi
│ ├── snaps/
│ │ ├── aoc_2024/
│ │ │ ├── day_01/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_02/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_03/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_04/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_05/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_06/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_07/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_08/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_09/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_10/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_11/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_12/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_13/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_14/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_15/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_16/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_17/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_18/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_19/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_20/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_21/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_22/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_23/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── day_24/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ └── day_25/
│ │ │ ├── output.txt
│ │ │ └── stats
│ │ ├── compile/
│ │ │ ├── opaque_ext_fn.iv
│ │ │ └── pre_reduce_opaque_fn.iv
│ │ ├── examples/
│ │ │ ├── cat/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── fib/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── fib_repl/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── fizzbuzz/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── guessing_game/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── hello_world/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── mandelbrot/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── mandelbrot_sixel/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── mandelbrot_tga/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── primeness/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── stream_primes/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── sub_min/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ └── sum_divisors/
│ │ │ ├── output.txt
│ │ │ └── stats
│ │ ├── fail/
│ │ │ ├── atypical.error
│ │ │ ├── bad_try.error
│ │ │ ├── continue_what.error
│ │ │ ├── hallo_world.error
│ │ │ ├── inconfigurable.error
│ │ │ ├── inflexible.error
│ │ │ ├── informal.error
│ │ │ ├── is_not.error
│ │ │ ├── loader.error
│ │ │ ├── occurs.error
│ │ │ ├── opaque_private.error
│ │ │ ├── other_dual.error
│ │ │ ├── recursive_type_alias.error
│ │ │ ├── unsafe_.error
│ │ │ └── visibility.error
│ │ ├── fmt/
│ │ │ ├── comment.fmt.vi
│ │ │ ├── match.fmt.vi
│ │ │ ├── objects.fmt.vi
│ │ │ └── uses.fmt.vi
│ │ ├── ivy/
│ │ │ ├── cat/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── fib_repl/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── fizzbuzz/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ └── hihi/
│ │ │ ├── output.txt
│ │ │ └── stats
│ │ ├── misc/
│ │ │ ├── basic_test/
│ │ │ │ └── stderr.txt
│ │ │ ├── missing_no.error
│ │ │ └── reconfigure.txt
│ │ ├── programs/
│ │ │ ├── array_from_list/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── array_order/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── array_smoothsort/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── array_to_list/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── basic_diverge/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── brainfuck/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── break_result/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── centimanes/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── classify_primes/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── cli_args/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── cond_diverge/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── configurable/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── cubes/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── cyclist/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── div_by_zero/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── empty_loop/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── f32_ops/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── f32_roundabout/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── f64_no_inline/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── f64_ops/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── f64_roundabout/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── file/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── final_countdown/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── find_primes/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── heap/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── int_edges/
│ │ │ │ └── stats
│ │ │ ├── invalid_extrinsics/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── inverse/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── iterator_party/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── lambda/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── lcs/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── life/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── log_brute/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── logic/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── loop_break_continue/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── loop_vi_loop/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── main/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── mandelbrot_f64/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── map_ops/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── map_test/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── maybe_set/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── n64_div_rem/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── nat_div/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── nat_edges/
│ │ │ │ └── stats
│ │ │ ├── no_return/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── nothing_lasts_forever/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── opaque/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── option_party/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── par/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── pretty_div/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── primenesses/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── quine/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── regex/
│ │ │ │ └── stats
│ │ │ ├── segmented_sieve/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── sieve/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── so_random/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── sort/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── specializations/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── square_case/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── the_greatest_show/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── tiny_f64/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ ├── verbose_add/
│ │ │ │ ├── output.txt
│ │ │ │ └── stats
│ │ │ └── when_break_continue/
│ │ │ ├── output.txt
│ │ │ └── stats
│ │ └── repl/
│ │ ├── F64_misc.repl.vi
│ │ ├── N64.repl.vi
│ │ ├── Nat.repl.vi
│ │ ├── advanced_repl.repl.vi
│ │ ├── basic_repl.repl.vi
│ │ ├── distribute_inverse.repl.vi
│ │ ├── elementwise.repl.vi
│ │ ├── extrinsics.repl.vi
│ │ ├── f32_to_string.repl.vi
│ │ ├── heap.repl.vi
│ │ ├── holes.repl.vi
│ │ ├── i32_misc.repl.vi
│ │ ├── index.repl.vi
│ │ ├── misc.repl.vi
│ │ ├── objects.repl.vi
│ │ ├── parse_error.repl.vi
│ │ ├── parse_floats.repl.vi
│ │ ├── randomness.repl.vi
│ │ ├── set.repl.vi
│ │ ├── shadow.repl.vi
│ │ ├── slice_and_dice.repl.vi
│ │ └── string_ops.repl.vi
│ ├── snaps.nu
│ ├── tests.nix
│ └── verify/
│ ├── int_edges.py
│ ├── nat_edges.py
│ └── regex.rs
├── util/
│ ├── Cargo.toml
│ └── src/
│ ├── bicycle.rs
│ ├── idx.rs
│ ├── lexer.rs
│ ├── lib.rs
│ ├── multi_iter.rs
│ ├── nat.rs
│ ├── parser.rs
│ └── unwrap_vec.rs
└── vine/
├── Cargo.toml
├── examples/
│ ├── cat.vi
│ ├── fib.vi
│ ├── fib_repl.vi
│ ├── fizzbuzz.vi
│ ├── guessing_game.vi
│ ├── hello_world.vi
│ ├── mandelbrot.vi
│ ├── mandelbrot_sixel.vi
│ ├── mandelbrot_tga.vi
│ ├── primeness.vi
│ ├── stream_primes.vi
│ ├── sub_min.vi
│ └── sum_divisors.vi
└── src/
├── compiler.rs
├── components/
│ ├── analyzer/
│ │ └── effect.rs
│ ├── analyzer.rs
│ ├── charter.rs
│ ├── distiller.rs
│ ├── emitter.rs
│ ├── finder/
│ │ └── candidates.rs
│ ├── finder.rs
│ ├── lexer.rs
│ ├── loader.rs
│ ├── matcher.rs
│ ├── normalizer.rs
│ ├── parser.rs
│ ├── resolver.rs
│ ├── specializer.rs
│ └── synthesizer.rs
├── components.rs
├── features/
│ ├── annotation.rs
│ ├── assert.rs
│ ├── block.rs
│ ├── builtin.rs
│ ├── cast.rs
│ ├── coerce.rs
│ ├── composite.rs
│ ├── condition.rs
│ ├── const_.rs
│ ├── debug.rs
│ ├── do_.rs
│ ├── enum_.rs
│ ├── flex.rs
│ ├── fn_.rs
│ ├── for_.rs
│ ├── generics.rs
│ ├── hole.rs
│ ├── if_.rs
│ ├── impl_.rs
│ ├── import.rs
│ ├── index.rs
│ ├── inline_ivy.rs
│ ├── inverse.rs
│ ├── labels.rs
│ ├── let_.rs
│ ├── list.rs
│ ├── local.rs
│ ├── loop_.rs
│ ├── match_.rs
│ ├── method.rs
│ ├── mod_.rs
│ ├── numeric.rs
│ ├── ops.rs
│ ├── path.rs
│ ├── place.rs
│ ├── range.rs
│ ├── reference.rs
│ ├── string.rs
│ ├── struct_.rs
│ ├── trait_.rs
│ ├── try_.rs
│ ├── type_.rs
│ ├── union.rs
│ ├── when.rs
│ └── while_.rs
├── features.rs
├── lib.rs
├── structures/
│ ├── annotations.rs
│ ├── ast/
│ │ └── visit.rs
│ ├── ast.rs
│ ├── chart.rs
│ ├── checkpoint.rs
│ ├── diag.rs
│ ├── resolutions.rs
│ ├── signatures.rs
│ ├── specializations.rs
│ ├── template.rs
│ ├── tir.rs
│ ├── types.rs
│ └── vir.rs
├── structures.rs
├── tools/
│ ├── doc.rs
│ ├── fmt/
│ │ └── doc.rs
│ ├── fmt.rs
│ ├── repl/
│ │ ├── command.rs
│ │ └── show.rs
│ └── repl.rs
└── tools.rs
SYMBOL INDEX (1838 symbols across 123 files)
FILE: cli/src/bin/ivy.rs
function main (line 4) | fn main() -> Result<()> {
FILE: cli/src/bin/vine.rs
function main (line 4) | fn main() -> Result<()> {
FILE: cli/src/common.rs
type Optimizations (line 20) | pub struct Optimizations {
method apply (line 26) | pub fn apply(&self, nets: &mut Nets, entrypoints: &[String]) {
type RunArgs (line 34) | pub struct RunArgs {
method output (line 50) | pub fn output(&self, nets: &Nets) -> (RunResult, Vec<u8>) {
method check (line 72) | pub fn check(&self, nets: &Nets, debug_hint: bool) {
method run (line 76) | pub fn run<R: Read, W: Write>(
type RunResult (line 121) | pub struct RunResult {
method check (line 129) | pub fn check(&self, debug_hint: bool) {
method success (line 158) | pub fn success(&self) -> bool {
function parse_size (line 163) | fn parse_size(size: &str) -> anyhow::Result<usize> {
FILE: cli/src/ivy_cli.rs
type IvyCommand (line 15) | pub enum IvyCommand {
method execute (line 26) | pub fn execute() -> Result<()> {
type IvyRunCommand (line 37) | pub struct IvyRunCommand {
method execute (line 45) | pub fn execute(self) -> Result<()> {
type IvyOptimizeCommand (line 54) | pub struct IvyOptimizeCommand {
method execute (line 64) | pub fn execute(&self) -> Result<()> {
type IvyReplCommand (line 70) | pub struct IvyReplCommand {
method execute (line 78) | pub fn execute(self) -> Result<()> {
type IvyCompletionCommand (line 110) | pub struct IvyCompletionCommand {
method execute (line 115) | pub fn execute(self) -> Result<()> {
FILE: cli/src/vine_cli.rs
type VineCommand (line 37) | pub enum VineCommand {
method execute (line 58) | pub fn execute() -> Result<()> {
type LibArgs (line 74) | pub struct LibArgs {
method initialize (line 82) | fn initialize(mut self, compiler: &mut Compiler) -> IdxVec<FileId, Pat...
type CheckArgs (line 99) | pub struct CheckArgs {
type CompileArgs (line 106) | pub struct CompileArgs {
method initialize (line 117) | fn initialize(self) -> Compiler {
method compile (line 127) | fn compile(self) -> (Nets, Compiler) {
function root_source (line 140) | fn root_source() -> Source {
type VineRunCommand (line 161) | pub struct VineRunCommand {
method execute (line 171) | pub fn execute(self) -> Result<()> {
type VineTestCommand (line 181) | pub struct VineTestCommand {
method execute (line 200) | pub fn execute(mut self) -> Result<()> {
method matching_tests (line 238) | fn matching_tests(tests: &[String], compiler: &Compiler) -> Vec<(Strin...
type VineBuildCommand (line 254) | pub struct VineBuildCommand {
method execute (line 264) | pub fn execute(self) -> Result<()> {
type VineCheckCommand (line 277) | pub struct VineCheckCommand {
method execute (line 287) | pub fn execute(self) -> Result<()> {
type VineReplCommand (line 358) | pub struct VineReplCommand {
method execute (line 371) | pub fn execute(self) -> Result<()> {
type VineFmtCommand (line 415) | pub struct VineFmtCommand {
method execute (line 420) | pub fn execute(self) -> Result<()> {
method fmt (line 446) | fn fmt(path: impl fmt::Display, src: &str) -> Option<String> {
type VineLspCommand (line 458) | pub struct VineLspCommand {
method execute (line 464) | pub fn execute(self) -> Result<()> {
type VineCompletionCommand (line 473) | pub struct VineCompletionCommand {
method execute (line 478) | pub fn execute(self) -> Result<()> {
type VineDocCommand (line 490) | pub struct VineDocCommand {
method execute (line 497) | pub fn execute(self) -> Result<()> {
function eprint_diags (line 511) | fn eprint_diags(compiler: &Compiler) {
function print_diags (line 515) | fn print_diags(compiler: &Compiler) {
function _print_diags (line 519) | fn _print_diags(mut w: impl io::Write + IsTerminal, compiler: &Compiler)...
type Colors (line 558) | struct Colors {
function colors (line 568) | fn colors(t: &impl IsTerminal) -> Colors {
type Source (line 585) | struct Source {
type Parser (line 591) | type Parser = ParseSource;
method value_parser (line 592) | fn value_parser() -> Self::Parser {
type ParseSource (line 598) | struct ParseSource;
type Value (line 601) | type Value = Source;
method parse_ref (line 603) | fn parse_ref(
function build_config (line 641) | fn build_config(args: Vec<String>) -> HashMap<String, String> {
FILE: ivm/src/addr.rs
type Addr (line 14) | pub struct Addr(pub *const ());
constant NULL (line 20) | pub const NULL: Addr = Addr(ptr::null());
method as_word (line 27) | pub(crate) unsafe fn as_word<'ivm>(self) -> &'ivm AtomicWord {
method as_global (line 36) | pub unsafe fn as_global<'ivm>(self) -> &'ivm Global<'ivm> {
constant HALF_BIT (line 40) | const HALF_BIT: u64 = 0b1000;
method map_addr (line 43) | fn map_addr(self, f: impl FnOnce(u64) -> u64) -> Self {
method other_half (line 49) | pub fn other_half(self) -> Self {
method left_half (line 55) | pub fn left_half(self) -> Self {
method fmt (line 61) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
FILE: ivm/src/allocator.rs
type Allocator (line 10) | pub(crate) struct Allocator<'ivm> {
function new (line 20) | pub(crate) fn new(heap: &'ivm Heap) -> Self {
function shrink (line 24) | pub(crate) fn shrink(&mut self) {
function fork (line 29) | pub(crate) fn fork(&mut self, index: usize, count: usize) -> Self {
function new_node (line 46) | pub unsafe fn new_node(&mut self, tag: Tag, label: u16) -> (Port<'ivm>, ...
function new_wire (line 54) | pub fn new_wire(&mut self) -> (Wire<'ivm>, Wire<'ivm>) {
function new_wires (line 63) | pub fn new_wires(&mut self) -> ((Wire<'ivm>, Wire<'ivm>), (Wire<'ivm>, W...
function free_wire (line 75) | pub(crate) fn free_wire(&mut self, wire: Wire<'ivm>) {
function alloc_node (line 92) | fn alloc_node(&mut self) -> Addr {
FILE: ivm/src/ext.rs
type Extrinsics (line 34) | pub struct Extrinsics<'ivm> {
method default (line 48) | fn default() -> Self {
constant MAX_EXT_FN_COUNT (line 62) | pub const MAX_EXT_FN_COUNT: usize = 0x3FFF;
constant MAX_EXT_TY_COUNT (line 63) | pub const MAX_EXT_TY_COUNT: usize = 0x7FFF;
function new_split_ext_fn (line 65) | pub fn new_split_ext_fn(&mut self, f: impl ExtSplitFn<'ivm>) -> ExtFn<'i...
function new_merge_ext_fn (line 74) | pub fn new_merge_ext_fn(&mut self, f: impl ExtMergeFn<'ivm>) -> ExtFn<'i...
function new_ext_ty (line 83) | pub fn new_ext_ty<T: ExtTyCast<'ivm>>(&mut self) -> ExtTy<'ivm, T> {
function n32_ext_ty (line 90) | pub fn n32_ext_ty(&self) -> ExtTy<'ivm, u32> {
function ext_val_as_n32 (line 94) | pub fn ext_val_as_n32(&self, x: ExtVal<'ivm>) -> Option<u32> {
function get_ext_split_fn (line 98) | pub fn get_ext_split_fn(&self, ext_fn: ExtFn<'ivm>) -> &dyn ExtSplitFn<'...
function get_ext_merge_fn (line 102) | pub fn get_ext_merge_fn(&self, ext_fn: ExtFn<'ivm>) -> &dyn ExtMergeFn<'...
type ExtVal (line 116) | pub struct ExtVal<'ivm>(Word, PhantomData<fn(&'ivm ()) -> &'ivm ()>);
constant PAYLOAD_MASK (line 119) | const PAYLOAD_MASK: u64 = 0x0000_FFFF_FFFF_FFF8;
function from_bits (line 126) | pub unsafe fn from_bits(bits: Word) -> Self {
function bits (line 132) | pub fn bits(&self) -> Word {
function new (line 142) | pub fn new(ty_id: ExtTyId<'ivm>, payload: Word) -> Self {
function ty_id (line 157) | pub fn ty_id(&self) -> ExtTyId<'ivm> {
function payload (line 166) | fn payload(&self) -> Word {
function cast (line 176) | pub unsafe fn cast<T: ExtTyCast<'ivm>>(self) -> T {
method fmt (line 182) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type ExtTy (line 187) | pub struct ExtTy<'ivm, T>(ExtTyId<'ivm>, PhantomData<fn(T) -> T>);
method clone (line 190) | fn clone(&self) -> Self {
function new_unchecked (line 198) | pub fn new_unchecked(ty_id: ExtTyId<'ivm>) -> Self {
function ty_id (line 203) | pub fn ty_id(self) -> ExtTyId<'ivm> {
function unwrap_ext_val (line 212) | pub fn unwrap_ext_val(self, ext: ExtVal<'ivm>) -> Option<T>
function wrap_ext_val (line 221) | pub fn wrap_ext_val(self, value: T) -> ExtVal<'ivm>
type ExtTyCast (line 233) | pub trait ExtTyCast<'ivm> {
constant COPY (line 234) | const COPY: bool;
method into_payload (line 240) | fn into_payload(self) -> Word;
method from_payload (line 247) | unsafe fn from_payload(payload: Word) -> Self;
constant COPY (line 251) | const COPY: bool = true;
function into_payload (line 254) | fn into_payload(self) -> Word {
function from_payload (line 259) | unsafe fn from_payload(payload: Word) -> u32 {
constant COPY (line 265) | const COPY: bool = true;
function into_payload (line 268) | fn into_payload(self) -> Word {
function from_payload (line 273) | unsafe fn from_payload(payload: Word) -> f32 {
constant COPY (line 280) | const COPY: bool = false;
function into_payload (line 283) | fn into_payload(self) -> Word {
function from_payload (line 288) | unsafe fn from_payload(_payload: Word) {}
type Aligned (line 293) | pub struct Aligned<T>(T);
type Boxed (line 297) | pub struct Boxed<T>(Box<Aligned<T>>);
function from (line 300) | fn from(value: T) -> Self {
type Target (line 306) | type Target = T;
method deref (line 308) | fn deref(&self) -> &Self::Target {
method deref_mut (line 314) | fn deref_mut(&mut self) -> &mut Self::Target {
function ptr (line 320) | fn ptr(self) -> *mut Aligned<T> {
function into_inner (line 324) | pub fn into_inner(self) -> T {
function into_aligned_ptr (line 328) | fn into_aligned_ptr(value: T) -> *mut Aligned<T> {
function from_aligned_ptr (line 332) | unsafe fn from_aligned_ptr(ptr: *mut Aligned<T>) -> Self {
constant COPY (line 338) | const COPY: bool = false;
function into_payload (line 341) | fn into_payload(self) -> Word {
function from_payload (line 346) | unsafe fn from_payload(payload: Word) -> Self {
constant COPY (line 352) | const COPY: bool = false;
function into_payload (line 355) | fn into_payload(self) -> Word {
function from_payload (line 360) | unsafe fn from_payload(payload: Word) -> Self {
type ExtTyId (line 371) | pub struct ExtTyId<'ivm>(u16, PhantomData<&'ivm mut &'ivm ()>);
constant COPY_BIT (line 374) | const COPY_BIT: u16 = 0x8000;
function new (line 377) | fn new(ty_id: u16, copy: bool) -> Self {
function from_bits (line 382) | fn from_bits(bits: u16) -> Self {
function bits (line 387) | fn bits(self) -> u16 {
function is_copy (line 392) | pub fn is_copy(self) -> bool {
type ExtFn (line 404) | pub struct ExtFn<'ivm>(u16, PhantomData<fn(&'ivm ()) -> &'ivm ()>);
constant SWAP_BIT (line 407) | const SWAP_BIT: u16 = 0x8000;
constant MERGE_BIT (line 408) | const MERGE_BIT: u16 = 0x4000;
constant ID_MASK (line 409) | const ID_MASK: u16 = 0x3FFF;
function new_split (line 412) | fn new_split(id: usize) -> Self {
function new_merge (line 417) | fn new_merge(id: usize) -> Self {
function index (line 422) | fn index(&self) -> usize {
function bits (line 427) | pub fn bits(&self) -> u16 {
function is_swapped (line 432) | pub fn is_swapped(&self) -> bool {
function is_merge (line 437) | pub fn is_merge(&self) -> bool {
function swapped (line 442) | pub fn swapped(&self) -> Self {
method fmt (line 448) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type OpaqueExtFn (line 454) | pub struct OpaqueExtFn {
FILE: ivm/src/flags.rs
type Flags (line 3) | pub struct Flags {
method success (line 13) | pub fn success(self) -> bool {
FILE: ivm/src/global.rs
type Global (line 5) | pub struct Global<'ivm> {
type LabelSet (line 22) | pub struct LabelSet {
constant NONE (line 32) | pub const NONE: Self = Self { cap: 0, bits: Vec::new() };
method add (line 36) | pub fn add(&mut self, label: u16) {
method has (line 51) | pub fn has(&self, label: u16) -> bool {
method union (line 62) | pub fn union(&mut self, other: &LabelSet) {
FILE: ivm/src/heap.rs
type Heap (line 8) | pub struct Heap(pub(crate) [Node]);
method new (line 25) | pub fn new() -> Box<Self> {
method with_size (line 39) | pub fn with_size(bytes: usize) -> Option<Box<Self>> {
method slice (line 53) | pub(crate) fn slice(&self, range: impl SliceIndex<[Node], Output = [No...
type Node (line 12) | pub(crate) struct Node(pub AtomicWord, pub AtomicWord);
constant HEAP_SIZE_BYTES (line 15) | pub const HEAP_SIZE_BYTES: usize = if cfg!(miri) {
FILE: ivm/src/instruction.rs
type Instructions (line 11) | pub struct Instructions<'ivm> {
method default (line 21) | fn default() -> Self {
function new_register (line 29) | pub fn new_register(&mut self) -> Register {
function push (line 41) | pub unsafe fn push(&mut self, instruction: Instruction<'ivm>) {
function instructions (line 46) | pub fn instructions(&self) -> &[Instruction<'ivm>] {
type Instruction (line 57) | pub enum Instruction<'ivm> {
type Register (line 79) | pub struct Register {
constant ROOT (line 92) | pub const ROOT: Register = Register::new(0);
method new (line 96) | const fn new(index: usize) -> Self {
method index (line 102) | pub fn index(&self) -> usize {
constant REGISTER_SIZE (line 88) | const REGISTER_SIZE: u32 = 8;
method fmt (line 108) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
function link_register (line 119) | unsafe fn link_register(&mut self, register: Register, port: Port<'ivm>) {
function execute (line 133) | pub fn execute(&mut self, instructions: &Instructions<'ivm>, port: Port<...
FILE: ivm/src/interact.rs
function link (line 18) | pub fn link(&mut self, a: Port<'ivm>, b: Port<'ivm>) {
function link_wire (line 39) | pub fn link_wire(&mut self, a: Wire<'ivm>, b: Port<'ivm>) {
function link_wire_wire (line 53) | pub fn link_wire_wire(&mut self, a: Wire<'ivm>, b: Wire<'ivm>) {
function follow (line 59) | pub fn follow(&mut self, mut p: Port<'ivm>) -> Port<'ivm> {
function follow_ref (line 74) | pub fn follow_ref<'a>(&self, p: &'a Port<'ivm>) -> PortRef<'a, 'ivm> {
function interact (line 87) | pub(crate) fn interact(&mut self, a: Port<'ivm>, b: Port<'ivm>) {
function expand (line 120) | fn expand(&mut self, c: Port<'ivm>, p: Port<'ivm>) {
function annihilate (line 126) | fn annihilate(&mut self, a: Port<'ivm>, b: Port<'ivm>) {
function copy (line 134) | fn copy(&mut self, n: Port<'ivm>, b: Port<'ivm>) {
function commute (line 141) | fn commute(&mut self, a: Port<'ivm>, b: Port<'ivm>) {
function call (line 162) | fn call(&mut self, f: Port<'ivm>, lhs: Port<'ivm>) {
function branch (line 195) | fn branch(&mut self, b: Port<'ivm>, v: Port<'ivm>) {
FILE: ivm/src/ivm.rs
type IVM (line 14) | pub struct IVM<'ivm, 'ext> {
function new (line 42) | pub fn new(heap: &'ivm Heap, extrinsics: &'ext Extrinsics<'ivm>) -> Self {
function new_from_allocator (line 46) | pub(crate) fn new_from_allocator(
function normalize (line 65) | pub fn normalize(&mut self) {
function do_fast (line 78) | pub(crate) fn do_fast(&mut self) {
function normalize_breadth_first (line 88) | pub fn normalize_breadth_first(&mut self) {
FILE: ivm/src/parallel.rs
function normalize_parallel (line 11) | pub fn normalize_parallel(&mut self, threads: usize) {
type Msg (line 50) | struct Msg<'ivm> {
type Shared (line 57) | struct Shared<'ivm, 'ext> {
type Pairs (line 63) | type Pairs<'ivm> = Vec<(Port<'ivm>, Port<'ivm>)>;
type MsgKind (line 66) | enum MsgKind {
type Worker (line 75) | struct Worker<'w, 'ivm, 'ext> {
constant ERA_LENGTH (line 81) | const ERA_LENGTH: u32 = 512;
function execute (line 84) | fn execute(mut self) {
function work (line 89) | fn work(&mut self) {
type WorkerHandle (line 145) | struct WorkerHandle<'w, 'ivm, 'ext> {
type Dispatch (line 149) | struct Dispatch<'w, 'ivm, 'ext> {
function execute (line 155) | fn execute(mut self) {
FILE: ivm/src/port.rs
type Port (line 30) | pub struct Port<'ivm>(NonZeroWord, PhantomData<fn(&'ivm ()) -> &'ivm ()>);
type Tag (line 38) | pub enum Tag {
constant ERASE (line 75) | pub const ERASE: Self = unsafe { Port::from_bits(Word::from_bits(Tag::Er...
function from_bits (line 82) | pub(crate) const unsafe fn from_bits(word: Word) -> Self {
function bits (line 86) | pub(crate) fn bits(&self) -> Word {
function option_from_bits (line 96) | pub(crate) unsafe fn option_from_bits(word: Word) -> Option<Self> {
function new (line 105) | pub unsafe fn new(tag: Tag, label: u16, addr: Addr) -> Self {
function tag (line 117) | pub fn tag(&self) -> Tag {
function label (line 124) | pub fn label(&self) -> u16 {
function addr (line 131) | pub fn addr(&self) -> Addr {
function new_global (line 137) | pub fn new_global(global: &'ivm Global) -> Self {
function new_wire (line 143) | pub fn new_wire(wire: Wire<'ivm>) -> Self {
function new_ext_val (line 149) | pub fn new_ext_val(val: ExtVal) -> Self {
function clone (line 161) | pub unsafe fn clone(&self) -> Self {
function as_ext_fn (line 170) | pub unsafe fn as_ext_fn(&self) -> ExtFn<'ivm> {
function as_wire (line 182) | pub unsafe fn as_wire(self) -> Wire<'ivm> {
function as_ext_val (line 194) | pub unsafe fn as_ext_val(&self) -> ExtVal<'ivm> {
function as_global (line 204) | pub unsafe fn as_global(&self) -> &'ivm Global<'ivm> {
function aux (line 217) | pub unsafe fn aux(self) -> (Wire<'ivm>, Wire<'ivm>) {
function aux_ref (line 227) | pub unsafe fn aux_ref(&self) -> (WireRef<'_, 'ivm>, WireRef<'_, 'ivm>) {
method fmt (line 238) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type PortRef (line 252) | pub struct PortRef<'a, 'ivm>(Port<'ivm>, PhantomData<&'a ()>);
function from_port (line 255) | pub(crate) fn from_port(port: Port<'ivm>) -> Self {
function new_wire (line 260) | pub fn new_wire(wire: &Wire<'ivm>) -> Self {
type Target (line 266) | type Target = Port<'ivm>;
method deref (line 268) | fn deref(&self) -> &Self::Target {
function from (line 274) | fn from(port: &'a Port<'ivm>) -> Self {
FILE: ivm/src/stats.rs
type Stats (line 10) | pub struct Stats {
method interactions (line 44) | pub fn interactions(&self) -> u64 {
method speed (line 49) | pub fn speed(&self) -> u64 {
method clock_speed (line 54) | pub fn clock_speed(&self) -> u64 {
method worker_avg (line 59) | pub fn worker_avg(&self) -> u64 {
method breadth (line 64) | pub fn breadth(&self) -> u64 {
method speedup (line 68) | pub fn speedup(&self) -> u64 {
method clear_perf (line 72) | pub fn clear_perf(&mut self) {
method add_assign (line 188) | fn add_assign(&mut self, rhs: Stats) {
method fmt (line 82) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
function measure_int (line 178) | const fn measure_int(int: u64) -> usize {
FILE: ivm/src/wire.rs
type Wire (line 21) | pub struct Wire<'ivm>(Addr, PhantomData<&'ivm mut &'ivm ()>);
function from_addr (line 27) | pub unsafe fn from_addr(addr: Addr) -> Self {
function target (line 31) | fn target(&self) -> &'ivm AtomicWord {
function load_target (line 36) | pub(crate) fn load_target(&self) -> Option<Port<'ivm>> {
function swap_target (line 41) | pub(crate) fn swap_target(&self, new: Option<Port<'ivm>>) -> Option<Port...
function addr (line 47) | pub(crate) fn addr(&self) -> Addr {
function clone (line 59) | pub unsafe fn clone(&self) -> Self {
method fmt (line 65) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type WireRef (line 71) | pub struct WireRef<'a, 'ivm>(Wire<'ivm>, PhantomData<&'a ()>);
function from_wire (line 74) | pub(crate) fn from_wire(wire: Wire<'ivm>) -> Self {
type Target (line 80) | type Target = Wire<'ivm>;
method deref (line 82) | fn deref(&self) -> &Self::Target {
function from (line 88) | fn from(wire: &'a Wire<'ivm>) -> Self {
FILE: ivm/src/word.rs
type Word (line 22) | pub struct Word(#[cfg(not(miri))] u64, #[cfg(miri)] *mut ());
method from_bits (line 28) | pub const fn from_bits(bits: u64) -> Self {
method from_bits (line 35) | pub const fn from_bits(bits: u64) -> Self {
method from_ptr (line 41) | pub fn from_ptr(ptr: *const ()) -> Self {
method bits (line 48) | pub fn bits(self) -> u64 {
method bits (line 55) | pub fn bits(self) -> u64 {
method ptr (line 61) | pub fn ptr(self) -> *const () {
method map_bits (line 68) | pub fn map_bits(self, f: impl FnOnce(u64) -> u64) -> Self {
method map_bits (line 75) | pub fn map_bits(self, f: impl FnOnce(u64) -> u64) -> Self {
type AtomicWord (line 82) | pub(crate) struct AtomicWord(#[cfg(not(miri))] AtomicU64, #[cfg(miri)] A...
method load (line 86) | pub fn load(&self) -> Word {
method store (line 91) | pub fn store(&self, word: Word) {
method swap (line 96) | pub fn swap(&self, word: Word) -> Word {
method compare_exchange (line 101) | pub fn compare_exchange(&self, current: Word, new: Word) -> Result<Wor...
type NonZeroWord (line 109) | pub(crate) struct NonZeroWord(#[cfg(not(miri))] NonZeroU64, #[cfg(miri)]...
method new_unchecked (line 114) | pub const unsafe fn new_unchecked(word: Word) -> Self {
method new_unchecked (line 120) | pub const unsafe fn new_unchecked(word: Word) -> Self {
method get (line 126) | pub fn get(&self) -> Word {
method get (line 132) | pub fn get(&self) -> Word {
FILE: ivy/src/ast.rs
type Tree (line 12) | pub enum Tree {
method n_ary (line 107) | pub fn n_ary(
method children (line 118) | pub fn children(&self) -> impl DoubleEndedIterator + ExactSizeIterator...
method children_mut (line 130) | pub fn children_mut(&mut self) -> impl DoubleEndedIterator + ExactSize...
type Net (line 27) | pub struct Net {
method new (line 33) | pub fn new(root: Tree) -> Self {
method trees (line 98) | pub fn trees(&self) -> impl DoubleEndedIterator<Item = &Tree> + Clone {
method trees_mut (line 101) | pub fn trees_mut(&mut self) -> impl DoubleEndedIterator<Item = &mut Tr...
type Nets (line 39) | pub struct Nets(IndexMap<String, Net>);
type Target (line 42) | type Target = IndexMap<String, Net>;
method deref (line 43) | fn deref(&self) -> &Self::Target {
method deref_mut (line 49) | fn deref_mut(&mut self) -> &mut Self::Target {
method fmt (line 55) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method fmt (line 74) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method fmt (line 89) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
FILE: ivy/src/host.rs
type Host (line 18) | pub struct Host<'ivm> {
function get (line 42) | pub fn get(&self, name: &str) -> Option<&'ivm Global<'ivm>> {
function get_raw (line 46) | fn get_raw(&self, name: &str) -> Option<*const Global<'ivm>> {
function label_to_u16 (line 50) | pub fn label_to_u16<'l>(
function label_from_u16 (line 64) | pub fn label_from_u16(label: u16, labels: &IndexMap<String, ()>) -> &str {
function ext_ty (line 68) | fn ext_ty<T>(&self, name: &'static str) -> ExtTy<'ivm, T> {
function new_f32 (line 72) | pub fn new_f32(&self, payload: f32) -> ExtVal<'ivm> {
function new_f64 (line 76) | pub fn new_f64(&self, payload: f64) -> ExtVal<'ivm> {
function new_n32 (line 80) | pub fn new_n32(&self, payload: u32) -> ExtVal<'ivm> {
function new_io (line 84) | pub fn new_io(&self) -> ExtVal<'ivm> {
function instantiate_ext_fn (line 88) | pub fn instantiate_ext_fn(&self, ext_fn_name: &str, swap: bool) -> Optio...
FILE: ivy/src/host/ext.rs
function register_ext_fn (line 128) | pub fn register_ext_fn(&mut self, name: impl Into<String>, f: ExtFn<'ivm...
function register_ext_ty_id (line 134) | pub fn register_ext_ty_id(&mut self, name: String, ty_id: ExtTyId<'ivm>) {
function register_n32_ext_ty (line 139) | fn register_n32_ext_ty(&mut self, extrinsics: &mut Extrinsics<'ivm>) -> ...
function register_ext_ty (line 145) | fn register_ext_ty<T: ExtTyCast<'ivm>>(
function register_default_extrinsics (line 155) | pub fn register_default_extrinsics(&mut self, extrinsics: &mut Extrinsic...
function register_runtime_extrinsics (line 247) | pub fn register_runtime_extrinsics<R: Read, W: Write>(
function read_char (line 433) | fn read_char<R: Read>(mut reader: R) -> Result<(usize, Option<char>), io...
function read_bytes_into_char (line 453) | fn read_bytes_into_char<R: Read>(
function ext_val_as_str (line 471) | fn ext_val_as_str<'ivm>(n32: ExtTy<'ivm, u32>, chars: Vec<ExtVal<'ivm>>)...
FILE: ivy/src/host/readback.rs
function read (line 13) | pub fn read<'ext>(&self, ivm: &IVM<'ivm, 'ext>, port: &Port<'ivm>) -> Tr...
function reader (line 17) | pub fn reader<'ctx, 'ext>(&'ctx self, ivm: &'ctx IVM<'ivm, 'ext>) -> Rea...
type Reader (line 22) | pub struct Reader<'ctx, 'ivm, 'ext> {
function new (line 30) | fn new(ivm: &'ctx IVM<'ivm, 'ext>, host: &'ctx Host<'ivm>) -> Self {
function read_port (line 34) | pub fn read_port(&mut self, p: &Port<'ivm>) -> Tree {
function read_wire (line 92) | fn read_wire(&mut self, w: &Wire<'ivm>) -> Box<Tree> {
FILE: ivy/src/host/serialize.rs
function insert_nets (line 67) | pub fn insert_nets(self: &mut &'ivm mut Host<'ivm>, nets: &Nets) {
function _insert_nets (line 71) | pub(crate) fn _insert_nets(self: &mut &'ivm mut Host<'ivm>, nets: &Nets,...
type Serializer (line 118) | struct Serializer<'host, 'ast, 'ivm> {
function push (line 130) | fn push(&mut self, instruction: Instruction<'ivm>) {
function serialize_net (line 134) | fn serialize_net(&mut self, net: &'ast Net) {
function serialize_pair (line 169) | fn serialize_pair(&mut self, a: &'ast Tree, b: &'ast Tree) {
function serialize_tree (line 181) | fn serialize_tree(&mut self, tree: &'ast Tree) -> Register {
function serialize_tree_to (line 192) | fn serialize_tree_to(&mut self, tree: &'ast Tree, to: Register) {
function unbox (line 268) | fn unbox(&mut self, mut tree: &'ast Tree) -> &'ast Tree {
type PropagateLabels (line 278) | struct PropagateLabels<'ivm> {
type Node (line 283) | type Node = &'ivm UnsafeCell<Global<'ivm>>;
method state (line 285) | fn state(&mut self, cur: Self::Node) -> &BicycleState {
method visit (line 289) | fn visit(&mut self, cur: Self::Node, mut recurse: impl FnMut(&mut Self, ...
FILE: ivy/src/lexer.rs
type Token (line 9) | pub enum Token {
type Lexer (line 33) | pub struct Lexer<'src> {
function new (line 38) | pub fn new(src: &'src str) -> Self {
type Token (line 44) | type Token = Token;
type Error (line 45) | type Error = ParseError<'src>;
function state (line 47) | fn state(&self) -> &LexerState<'src> {
function state_mut (line 51) | fn state_mut(&mut self) -> &mut LexerState<'src> {
function lex (line 55) | fn lex(&mut self) -> Result<Self::Token, Self::Error> {
method into_u8 (line 119) | fn into_u8(self) -> u8 {
FILE: ivy/src/optimize.rs
type Optimizer (line 15) | pub struct Optimizer {
method optimize (line 20) | pub fn optimize(&mut self, nets: &mut Nets, entrypoints: &[String]) {
method _optimize (line 26) | fn _optimize(&mut self, nets: &mut Nets, entrypoints: &[String]) {
FILE: ivy/src/optimize/eta_reduce.rs
method eta_reduce (line 11) | pub fn eta_reduce(&mut self) -> bool {
type NodeKind (line 26) | enum NodeKind {
type WalkTrees (line 37) | struct WalkTrees<'a> {
function walk_tree (line 43) | fn walk_tree(&mut self, tree: &'a Tree) {
type ReduceTrees (line 71) | struct ReduceTrees<'a> {
function reduce_tree (line 78) | fn reduce_tree(&mut self, tree: &mut Tree) -> &'a NodeKind {
FILE: ivy/src/optimize/inline_globals.rs
function inline_globals (line 6) | pub fn inline_globals(nets: &mut Nets) -> bool {
type Inliner (line 18) | struct Inliner {
method populate_candidates (line 24) | fn populate_candidates(&mut self, nets: &Nets) {
method process (line 40) | fn process(&mut self, tree: &mut Tree) {
method should_inline (line 55) | fn should_inline(&self) -> bool {
method is_nilary (line 61) | fn is_nilary(&self) -> bool {
FILE: ivy/src/optimize/inline_vars.rs
type InlineVars (line 9) | pub(super) struct InlineVars {
method apply (line 16) | pub fn apply(&mut self, net: &mut Net) {
method apply_tree (line 46) | fn apply_tree(&mut self, tree: &mut Tree) {
FILE: ivy/src/optimize/pre_reduce.rs
function pre_reduce (line 13) | pub fn pre_reduce(nets: &mut Nets) {
type PreReduce (line 56) | struct PreReduce<'a> {
function visit_global (line 62) | fn visit_global(&mut self, name: &str) {
function visit_net (line 78) | fn visit_net(&mut self, net: &Net) {
function visit_tree (line 84) | fn visit_tree(&mut self, tree: &Tree) {
FILE: ivy/src/optimize/prune.rs
function prune (line 6) | pub fn prune(nets: &mut Nets, entrypoints: &[String]) {
type Prune (line 19) | struct Prune<'a> {
function visit_global (line 25) | fn visit_global(&mut self, name: &str) {
function visit_net (line 31) | fn visit_net(&mut self, net: &Net) {
function visit_tree (line 37) | fn visit_tree(&mut self, tree: &Tree) {
FILE: ivy/src/parser.rs
type Parser (line 11) | pub struct Parser<'src> {
type ParseError (line 16) | pub enum ParseError<'src> {
type Token (line 25) | type Token = Token;
type Lexer (line 26) | type Lexer = Lexer<'src>;
type Error (line 27) | type Error = ParseError<'src>;
function state (line 29) | fn state(&mut self) -> &mut ParserState<'src, Lexer<'src>> {
function unexpected_error (line 33) | fn unexpected_error(&self) -> ParseError<'src> {
function new (line 42) | pub fn new(lexer: Lexer<'src>) -> Result<Self, ParseError<'src>> {
function parse (line 46) | pub fn parse(src: &'src str) -> Result<Nets, ParseError<'src>> {
function parse_n32 (line 57) | fn parse_n32(&mut self) -> Result<u32, ParseError<'src>> {
function parse_f32 (line 62) | fn parse_f32(&mut self) -> Result<f32, ParseError<'src>> {
function parse_f64 (line 67) | fn parse_f64(&mut self) -> Result<f64, ParseError<'src>> {
function parse_net (line 72) | fn parse_net(&mut self) -> Result<Net, ParseError<'src>> {
function parse_net_inner (line 80) | pub fn parse_net_inner(&mut self) -> Result<Net, ParseError<'src>> {
function parse_pair (line 89) | pub(super) fn parse_pair(&mut self) -> Result<(Tree, Tree), ParseError<'...
function parse_tree (line 96) | fn parse_tree(&mut self) -> Result<Tree, ParseError<'src>> {
FILE: ivy/src/repl.rs
type Repl (line 18) | pub struct Repl<'host, 'ctx, 'ivm, 'ext> {
function new (line 25) | pub fn new(host: &'host mut Host<'ivm>, ivm: &'ctx mut IVM<'ivm, 'ext>) ...
function exec (line 30) | pub fn exec<'s>(&mut self, line: &'s str) -> Result<(), ParseError<'s>> {
function exec_pair (line 42) | pub fn exec_pair(&mut self, pair: (Tree, Tree)) {
function inject_to (line 49) | fn inject_to(&mut self, tree: Tree, to: Wire<'ivm>) {
function inject (line 66) | fn inject(&mut self, tree: Tree) -> Port<'ivm> {
method fmt (line 111) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
FILE: lsp/client/src/extension.ts
function activate (line 43) | async function activate(context: vscode.ExtensionContext) {
function activateLsp (line 48) | function activateLsp(context: vscode.ExtensionContext) {
function activateHighlighting (line 90) | async function activateHighlighting(context: vscode.ExtensionContext) {
function deactivate (line 144) | function deactivate() {
function applyChanges (line 148) | function applyChanges(tree: Tree, changes: readonly vscode.TextDocumentC...
class TreeSitterSemanticTokensProvider (line 180) | class TreeSitterSemanticTokensProvider implements vscode.DocumentSemanti...
method constructor (line 181) | constructor(public onDidChangeSemanticTokens: vscode.Event<void>) {}
method provideDocumentSemanticTokens (line 183) | async provideDocumentSemanticTokens(
FILE: lsp/src/lib.rs
type Backend (line 28) | struct Backend {
method refresh (line 37) | async fn refresh(&self) {
type Lsp (line 92) | struct Lsp {
method workspace_symbols (line 98) | fn workspace_symbols(&self, params: WorkspaceSymbolParams) -> Option<V...
method document_symbols (line 123) | fn document_symbols(&self, params: DocumentSymbolParams) -> Option<Doc...
method definitions (line 165) | fn definitions(&self, params: GotoDefinitionParams) -> Option<GotoDefi...
method references (line 171) | fn references(&self, params: ReferenceParams) -> Option<Vec<Location>> {
method occurrences (line 181) | fn occurrences(&self, params: DocumentHighlightParams) -> Option<Vec<D...
method hover (line 197) | fn hover(&self, params: HoverParams) -> Option<Hover> {
method lookup_span (line 226) | fn lookup_span<'a, T>(&self, map: &'a BTreeMap<Span, T>, span: Span) -...
method get_def (line 232) | fn get_def(&self, span: Span) -> Option<(Span, Span)> {
method file_to_uri (line 237) | fn file_to_uri(&self, file: FileId) -> Url {
method uri_to_file_id (line 243) | fn uri_to_file_id(&self, uri: Url) -> Option<FileId> {
method byte_to_position (line 247) | fn byte_to_position(&self, file: FileId, byte: usize) -> Position {
method span_to_range (line 252) | fn span_to_range(&self, span: Span) -> Range {
method position_to_byte (line 259) | fn position_to_byte(&self, file: FileId, position: Position) -> Option...
method position_to_span (line 266) | fn position_to_span(&self, file: FileId, position: Position) -> Option...
method document_position_to_span (line 271) | fn document_position_to_span(&self, doc_pos: TextDocumentPositionParam...
method span_to_location (line 276) | fn span_to_location(&self, span: Span) -> Location {
method diag_to_diagnostic (line 280) | fn diag_to_diagnostic(&self, diag: &Diag, severity: DiagnosticSeverity...
method initialize (line 298) | async fn initialize(&self, params: InitializeParams) -> Result<Initializ...
method initialized (line 331) | async fn initialized(&self, _: InitializedParams) {
method did_save (line 335) | async fn did_save(&self, _: DidSaveTextDocumentParams) {
method did_open (line 339) | async fn did_open(&self, params: DidOpenTextDocumentParams) {
method did_change (line 346) | async fn did_change(&self, params: DidChangeTextDocumentParams) {
method did_close (line 353) | async fn did_close(&self, params: DidCloseTextDocumentParams) {
method symbol (line 358) | async fn symbol(&self, params: WorkspaceSymbolParams) -> Result<Option<V...
method document_symbol (line 362) | async fn document_symbol(
method goto_definition (line 369) | async fn goto_definition(
method references (line 376) | async fn references(&self, params: ReferenceParams) -> Result<Option<Vec...
method document_highlight (line 380) | async fn document_highlight(
method hover (line 387) | async fn hover(&self, params: HoverParams) -> Result<Option<Hover>> {
method formatting (line 391) | async fn formatting(&self, params: DocumentFormattingParams) -> Result<O...
method shutdown (line 414) | async fn shutdown(&self) -> Result<()> {
function lsp (line 421) | pub async fn lsp(
FILE: lsp/tree-sitter-vine/grammar.js
constant BINARY_OP_TABLE (line 62) | const BINARY_OP_TABLE = [
constant LOGICAL_OP_TABLE (line 78) | const LOGICAL_OP_TABLE = [
FILE: tests/verify/regex.rs
function main (line 11) | fn main() {
FILE: util/src/bicycle.rs
type BicycleState (line 8) | pub struct BicycleState(Cell<usize>);
method reset (line 21) | pub fn reset(&self) {
method fmt (line 11) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type Bicycle (line 26) | pub trait Bicycle {
method state (line 28) | fn state(&mut self, node: Self::Node) -> &BicycleState;
method visit (line 29) | fn visit(&mut self, node: Self::Node, recurse: impl FnMut(&mut Self, S...
method visit_all (line 31) | fn visit_all(&mut self, nodes: impl IntoIterator<Item = Self::Node> + ...
function visit (line 41) | fn visit<B: Bicycle + ?Sized>(bi: &mut B, node: B::Node, depth: usize) -...
function _visit (line 65) | fn _visit<B: Bicycle + ?Sized>(bi: &mut B, node: B::Node, depth: usize) ...
FILE: util/src/idx.rs
type Idx (line 16) | pub trait Idx: Copy + Eq + Ord + Hash + IsEnabled + From<usize> + Into<u...
type IdxVec (line 50) | pub struct IdxVec<I: Idx, T> {
function new (line 57) | pub const fn new() -> Self {
function repeat (line 62) | pub fn repeat(value: T, len: usize) -> Self
function len (line 70) | pub fn len(&self) -> usize {
function is_empty (line 75) | pub fn is_empty(&self) -> bool {
function range (line 80) | pub fn range(&self) -> Range<I> {
function next_index (line 85) | pub fn next_index(&self) -> I {
function push (line 91) | pub fn push(&mut self, value: T) -> I {
function push_to (line 98) | pub fn push_to(&mut self, index: I, value: T) {
function get (line 104) | pub fn get(&self, index: I) -> Option<&T> {
function get_mut (line 109) | pub fn get_mut(&mut self, index: I) -> Option<&mut T> {
function last (line 114) | pub fn last(&self) -> Option<&T> {
function last_mut (line 119) | pub fn last_mut(&mut self) -> Option<&mut T> {
function pop (line 124) | pub fn pop(&mut self) -> Option<T> {
function get2_mut (line 128) | pub fn get2_mut(&mut self, a: I, b: I) -> Option<(&mut T, &mut T)> {
function iter (line 145) | pub fn iter(&self) -> Iter<'_, I, T> {
function iter_mut (line 150) | pub fn iter_mut(&mut self) -> IterMut<'_, I, T> {
function slice (line 155) | pub fn slice(&self, range: Range<I>) -> slice::Iter<'_, T> {
function slice_mut (line 160) | pub fn slice_mut(&mut self, range: Range<I>) -> slice::IterMut<'_, T> {
function keys (line 165) | pub fn keys(&self) -> RangeIter<I> {
function keys_from (line 170) | pub fn keys_from(&self, index: I) -> impl Iterator<Item = I> + Clone + u...
function into_values (line 175) | pub fn into_values(self) -> vec::IntoIter<T> {
function values (line 180) | pub fn values(&self) -> slice::Iter<'_, T> {
function values_mut (line 185) | pub fn values_mut(&mut self) -> slice::IterMut<'_, T> {
function get_or_extend (line 189) | pub fn get_or_extend(&mut self, index: I) -> &mut T
function get_or_extend_with (line 196) | pub fn get_or_extend_with(&mut self, index: I, f: impl FnMut() -> T) -> ...
function truncate (line 204) | pub fn truncate(&mut self, len: usize) {
function clear (line 208) | pub fn clear(&mut self) {
function drain (line 212) | pub fn drain(&mut self) -> Map<Enumerate<vec::Drain<'_, T>>, MapEntry<I,...
function fill (line 216) | pub fn fill(&mut self, value: T)
type Output (line 225) | type Output = T;
function index (line 227) | fn index(&self, index: I) -> &T {
function index_mut (line 233) | fn index_mut(&mut self, index: I) -> &mut T {
method fmt (line 239) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
function from (line 247) | fn from(vec: Vec<T>) -> Self {
function from (line 253) | fn from(value: IdxVec<I, T>) -> Self {
function from (line 259) | fn from(value: [T; N]) -> Self {
method default (line 265) | fn default() -> Self {
function map_entry (line 270) | fn map_entry<I: Idx, T>((index, value): (usize, T)) -> (I, T) {
type MapEntry (line 274) | type MapEntry<I, T> = fn((usize, T)) -> (I, T);
type IntoIter (line 275) | pub type IntoIter<I, T> = Map<Enumerate<vec::IntoIter<T>>, MapEntry<I, T>>;
type Iter (line 276) | pub type Iter<'a, I, T> = Map<Enumerate<slice::Iter<'a, T>>, MapEntry<I,...
type IterMut (line 277) | pub type IterMut<'a, I, T> = Map<Enumerate<slice::IterMut<'a, T>>, MapEn...
type Item (line 280) | type Item = (I, T);
type IntoIter (line 281) | type IntoIter = IntoIter<I, T>;
method into_iter (line 282) | fn into_iter(self) -> Self::IntoIter {
type Item (line 288) | type Item = (I, &'a T);
type IntoIter (line 289) | type IntoIter = Iter<'a, I, T>;
method into_iter (line 290) | fn into_iter(self) -> Self::IntoIter {
type Item (line 296) | type Item = (I, &'a mut T);
type IntoIter (line 297) | type IntoIter = IterMut<'a, I, T>;
method into_iter (line 298) | fn into_iter(self) -> Self::IntoIter {
function from_iter (line 304) | fn from_iter<It: IntoIterator<Item = T>>(iter: It) -> Self {
type RangeIter (line 309) | pub type RangeIter<I> = Map<Range<usize>, fn(usize) -> I>;
type RangeExt (line 310) | pub trait RangeExt<I: Idx> {
method iter (line 311) | fn iter(&self) -> RangeIter<I>;
method get (line 312) | fn get(&self, i: usize) -> I;
function iter (line 316) | fn iter(&self) -> RangeIter<I> {
function get (line 320) | fn get(&self, i: usize) -> I {
type Counter (line 328) | pub struct Counter<I: Idx>(pub I);
function next (line 333) | pub fn next(&mut self) -> I {
function chunk (line 339) | pub fn chunk(&mut self, len: usize) -> Range<I> {
function peek_next (line 346) | pub fn peek_next(&self) -> I {
function count (line 350) | pub fn count(&self) -> usize {
function reset (line 354) | pub fn reset(&mut self)
FILE: util/src/lexer.rs
type LexerState (line 7) | pub struct LexerState<'src> {
function new (line 17) | pub fn new(src: &'src str) -> Self {
function bump (line 23) | pub fn bump(&mut self) {
function teleport (line 30) | pub fn teleport(&mut self, offset: usize) {
type Lex (line 36) | pub trait Lex<'src> {
method state (line 40) | fn state(&self) -> &LexerState<'src>;
method state_mut (line 41) | fn state_mut(&mut self) -> &mut LexerState<'src>;
method lex (line 43) | fn lex(&mut self) -> Result<Self::Token, Self::Error>;
method src (line 45) | fn src(&self) -> &'src str {
method range (line 49) | fn range(&self) -> Range<usize> {
method slice (line 54) | fn slice(&self) -> &'src str {
method offset (line 58) | fn offset(&self) -> usize {
method bump (line 62) | fn bump(&mut self) -> Option<char> {
method eat (line 67) | fn eat(&mut self, char: char) -> bool {
method start_token (line 76) | fn start_token(&mut self) {
method bump_ok (line 81) | fn bump_ok(&mut self, token: Self::Token) -> Result<Self::Token, Self:...
method teleport (line 86) | fn teleport(&mut self, offset: usize) {
method char (line 90) | fn char(&self) -> Option<char> {
method bump_while (line 94) | fn bump_while(&mut self, f: impl Fn(char) -> bool) -> usize {
method skip_whitespace (line 103) | fn skip_whitespace(&mut self) {
method skip_block_comment_content (line 107) | fn skip_block_comment_content(&mut self) {
type Token (line 131) | pub trait Token: Copy + Eq + Debug {
method into_u8 (line 132) | fn into_u8(self) -> u8;
type TokenSet (line 136) | pub struct TokenSet<T: Token> {
method default (line 143) | fn default() -> Self {
function reset (line 149) | pub fn reset(&mut self) {
function add (line 155) | pub fn add(&mut self, token: T) {
function start_group (line 165) | pub fn start_group(&mut self, token: T) {
function end_group (line 170) | pub fn end_group(&mut self) {
method fmt (line 176) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method fmt (line 182) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
FILE: util/src/nat.rs
type Nat (line 2) | pub struct Nat(pub Vec<u32>);
constant ZERO (line 5) | pub const ZERO: Nat = Nat(Vec::new());
method add_u32 (line 7) | pub fn add_u32(&mut self, mut n: u32) {
method mul_u32 (line 21) | pub fn mul_u32(&mut self, n: u32) {
FILE: util/src/parser.rs
type ParserState (line 7) | pub struct ParserState<'src, L: Lex<'src, Token: Token>> {
function new (line 15) | pub fn new(mut lexer: L) -> Result<Self, L::Error> {
type Parse (line 20) | pub trait Parse<'src> {
method state (line 25) | fn state(&mut self) -> &mut ParserState<'src, Self::Lexer>;
method unexpected_error (line 27) | fn unexpected_error(&self) -> Self::Error;
method lexer (line 29) | fn lexer<'a>(&'a mut self) -> &'a mut Self::Lexer
method bump (line 36) | fn bump(&mut self) -> Result<(), Self::Error> {
method check (line 43) | fn check(&mut self, kind: Self::Token) -> bool {
method eat (line 48) | fn eat(&mut self, kind: Self::Token) -> Result<bool, Self::Error> {
method check_then (line 56) | fn check_then<T>(
method eat_then (line 64) | fn eat_then<T>(
method expect (line 72) | fn expect(&mut self, kind: Self::Token) -> Result<&'src str, Self::Err...
method unexpected (line 82) | fn unexpected<T>(&self) -> Result<T, Self::Error> {
method teleport (line 86) | fn teleport(&mut self, offset: usize) -> Result<(), Self::Error> {
method parse_delimited (line 91) | fn parse_delimited<T>(
method parse_u32_like (line 122) | fn parse_u32_like(
method parse_nat_like (line 141) | fn parse_nat_like(
method extract_radix (line 161) | fn extract_radix(bytes: &[u8]) -> (u32, &[u8]) {
method parse_f32_like (line 171) | fn parse_f32_like(
method parse_f64_like (line 179) | fn parse_f64_like(
type Delimiters (line 188) | pub struct Delimiters<T: Token> {
FILE: util/src/unwrap_vec.rs
function unwrap_vec (line 5) | pub fn unwrap_vec<T>(vec: Vec<Option<T>>) -> Vec<T> {
function unwrap_idx_vec (line 15) | pub fn unwrap_idx_vec<I: Idx, T>(vec: IdxVec<I, Option<T>>) -> IdxVec<I,...
FILE: vine/src/compiler.rs
type Compiler (line 35) | pub struct Compiler {
method new (line 53) | pub fn new(debug: bool, config: HashMap<String, String>) -> Self {
method check (line 57) | pub fn check(&mut self, hooks: impl Hooks) -> Result<(), ErrorGuarante...
method compile (line 62) | pub fn compile(&mut self, hooks: impl Hooks) -> Result<Nets, ErrorGuar...
method _compile (line 67) | fn _compile(
method _check (line 76) | fn _check(
method nets_from (line 132) | pub fn nets_from(&mut self, checkpoint: &Checkpoint) -> Nets {
method entrypoint_name (line 180) | pub fn entrypoint_name(&mut self, fragment_id: FragmentId) -> String {
method insert_main_net (line 188) | pub fn insert_main_net(&mut self, nets: &mut Nets, main: FragmentId) {
type Hooks (line 194) | pub trait Hooks {
method chart (line 195) | fn chart(&mut self, _charter: &mut Charter<'_>) {}
method pre_resolve (line 196) | fn pre_resolve(&mut self, _resolver: &mut Resolver<'_>) {}
method resolve (line 197) | fn resolve(&mut self, _resolver: &mut Resolver<'_>) {}
method distill (line 198) | fn distill(&mut self, _fragment_id: FragmentId, _vir: &mut Vir) {}
FILE: vine/src/components/analyzer.rs
function analyze (line 22) | pub fn analyze(chart: &Chart, diags: &mut Diags, span: Span, vir: &mut V...
type Analyzer (line 45) | struct Analyzer<'a> {
constant PASS (line 68) | pub const PASS: Self = EffectVar(0);
function analyze (line 72) | fn analyze(&mut self) {
function sweep (line 85) | fn sweep(&mut self, interface_id: InterfaceId) {
function build (line 102) | fn build(&mut self) {
function process_local (line 209) | fn process_local(&mut self, local: Local, declared: Vec<StageId>) {
function fill_segments (line 221) | fn fill_segments(&mut self, local: Local, declared: Vec<StageId>) {
function fixed_point (line 239) | fn fixed_point(&mut self, inv: Inverted) {
function set_wires (line 257) | fn set_wires(&mut self, local: Local, inv: Inverted, fork: bool) {
function new_relation (line 280) | fn new_relation(&mut self, a: EffectVar, b: EffectVar, c: EffectVar, o: ...
function new_var (line 287) | fn new_var(&mut self) -> EffectVar {
function mark_dirty (line 294) | fn mark_dirty(&mut self, var: EffectVar) {
function get_transfer (line 302) | fn get_transfer(&mut self, interface: InterfaceId) -> (EffectVar, Effect...
function report_errors (line 313) | fn report_errors(&mut self, local: Local, info: &VirLocal) {
method effect (line 407) | fn effect(&self, inv: Inverted, fork: bool) -> Effect {
FILE: vine/src/components/analyzer/effect.rs
type Effect (line 5) | pub enum Effect {
method join (line 65) | pub fn join(self: Effect, other: Effect) -> Effect {
method union (line 69) | pub fn union(self: Effect, other: Effect) -> Effect {
method read (line 73) | pub fn read(self) -> bool {
method pass (line 77) | pub fn pass(self) -> bool {
method barrier (line 81) | pub fn barrier(self) -> bool {
method write (line 85) | pub fn write(self) -> bool {
constant JOIN (line 35) | const JOIN: &[[Effect; 11]; 11] = &[
constant UNION (line 50) | const UNION: &[[Effect; 11]; 11] = &[
function effects (line 94) | fn effects() -> impl Iterator<Item = Effect> {
function join_identity (line 99) | fn join_identity() {
function join_associative (line 107) | fn join_associative() {
function join_idempotent (line 118) | fn join_idempotent() {
function union_identity (line 125) | fn union_identity() {
function union_commutative (line 133) | fn union_commutative() {
function union_associative (line 142) | fn union_associative() {
function union_idempotent (line 153) | fn union_idempotent() {
function distributive (line 160) | fn distributive() {
FILE: vine/src/components/charter.rs
type Charter (line 15) | pub struct Charter<'a> {
function chart (line 22) | pub fn chart(&mut self, modules: Vec<Module>) {
function new_def (line 46) | pub(crate) fn new_def(&mut self, name: Ident, path: String, parent: Opti...
function chart_mod_kind (line 70) | pub(crate) fn chart_mod_kind(
function chart_item (line 91) | pub fn chart_item(
function chart_attrs (line 171) | pub(crate) fn chart_attrs(&mut self, vis: VisId, item: ChartedItem, attr...
function chart_unsafe (line 284) | pub(crate) fn chart_unsafe(&mut self, span: Span, item: ChartedItem) {
function chart_child (line 307) | pub(crate) fn chart_child(
function resolve_vis (line 351) | pub(crate) fn resolve_vis(&mut self, base: DefId, vis: Vis) -> VisId {
function ensure_implemented (line 368) | pub(crate) fn ensure_implemented<T: From<ErrorGuaranteed>>(
function define_value (line 376) | pub(crate) fn define_value(&mut self, span: Span, def: DefId, vis: VisId...
function define_type (line 385) | pub(crate) fn define_type(&mut self, span: Span, def: DefId, vis: VisId,...
function define_pattern (line 394) | pub(crate) fn define_pattern(
function define_trait (line 409) | pub(crate) fn define_trait(&mut self, span: Span, def: DefId, vis: VisId...
function define_impl (line 418) | pub(crate) fn define_impl(&mut self, span: Span, def: DefId, vis: VisId,...
type ChartedItem (line 425) | pub enum ChartedItem {
method def (line 441) | pub fn def(&self) -> Option<DefId> {
function extract_subitems (line 458) | fn extract_subitems(item: &mut Item) -> Vec<Item> {
type ExtractItems (line 467) | pub struct ExtractItems {
method visit_item (line 472) | fn visit_item(&mut self, item: &mut Item) {
FILE: vine/src/components/distiller.rs
type Distiller (line 28) | pub struct Distiller<'r> {
type TargetDistillation (line 50) | pub(crate) struct TargetDistillation {
type Return (line 57) | pub(crate) struct Return {
type Poly (line 63) | pub(crate) enum Poly<T = Port> {
function new (line 71) | pub fn new(
function distill_fragment (line 96) | pub fn distill_fragment(&mut self, fragment: &Fragment) -> Vir {
function new_stage (line 136) | pub(crate) fn new_stage(
function new_layer (line 157) | pub(crate) fn new_layer(&mut self) -> Layer {
function child_layer (line 162) | pub(crate) fn child_layer(&mut self, parent_stage: &mut Stage, span: Spa...
function root_layer (line 170) | fn root_layer(&mut self, span: Span) -> (Layer, Stage) {
function finish_stage (line 176) | pub(crate) fn finish_stage(&mut self, stage: Stage) -> StageId {
function finish_layer (line 182) | pub(crate) fn finish_layer(&mut self, layer: Layer) {
function new_unconditional_stage (line 187) | pub(crate) fn new_unconditional_stage(&mut self, layer: &mut Layer, span...
function new_local (line 195) | pub(crate) fn new_local(&mut self, stage: &mut Stage, span: Span, ty: Ty...
function find_impl (line 201) | pub(crate) fn find_impl(&mut self, span: Span, ty: &ImplType, basic: boo...
function distill_vec (line 214) | pub(crate) fn distill_vec<T>(
function distill_vec_pair (line 229) | pub(crate) fn distill_vec_pair<T>(
function distill_expr_nil (line 246) | pub(crate) fn distill_expr_nil(&mut self, stage: &mut Stage, expr: &TirE...
function distill_expr_value (line 262) | pub(crate) fn distill_expr_value(&mut self, stage: &mut Stage, expr: &Ti...
function distill_expr_space (line 327) | pub(crate) fn distill_expr_space(&mut self, stage: &mut Stage, expr: &Ti...
function distill_expr_place (line 346) | pub(crate) fn distill_expr_place(&mut self, stage: &mut Stage, expr: &Ti...
function distill_expr_poly (line 367) | pub(crate) fn distill_expr_poly(&mut self, stage: &mut Stage, expr: &Tir...
function distill_pat_uninit (line 386) | pub(crate) fn distill_pat_uninit(&mut self, stage: &mut Stage, pat: &Tir...
function distill_pat_loop (line 406) | pub(crate) fn distill_pat_loop(&mut self, stage: &mut Stage, pat: &TirPa...
function distill_pat_value (line 426) | pub(crate) fn distill_pat_value(&mut self, stage: &mut Stage, pat: &TirP...
function distill_pat_space (line 449) | pub(crate) fn distill_pat_space(&mut self, stage: &mut Stage, pat: &TirP...
function distill_pat_place (line 470) | pub(crate) fn distill_pat_place(&mut self, stage: &mut Stage, pat: &TirP...
FILE: vine/src/components/emitter.rs
function emit (line 19) | pub fn emit(
type Emitter (line 45) | pub(crate) struct Emitter<'a> {
function emit_stage (line 61) | pub fn emit_stage(&mut self, stage: &Stage) -> Option<TemplateStage> {
function emit_transfer (line 80) | pub fn emit_transfer(&mut self, transfer: &Transfer) {
function inline_stage (line 116) | fn inline_stage(&mut self, stage: &Stage) {
function _emit_stage (line 124) | fn _emit_stage(&mut self, stage: &Stage) {
function emit_interface (line 135) | fn emit_interface(&mut self, interface: &Interface, interior: bool) -> T...
function emit_step (line 167) | fn emit_step(&mut self, step: &Step) {
function emit_link (line 203) | fn emit_link(&mut self, a: &Port, b: &Port) {
function emit_ext_fn (line 209) | fn emit_ext_fn(
function emit_fn_rel (line 229) | pub(crate) fn emit_fn_rel(&mut self, rel: FnRelId) -> Tree {
function emit_const_rel (line 235) | pub(crate) fn emit_const_rel(&mut self, rel: ConstRelId) -> Tree {
function emit_stage_rel (line 241) | pub(crate) fn emit_stage_rel(&mut self, stage: StageId) -> Tree {
function emit_port (line 247) | pub(crate) fn emit_port(&mut self, port: &Port) -> Tree {
function emit_header (line 259) | fn emit_header(&mut self, header: &Header, root: Tree) -> Tree {
function new_wire (line 295) | pub(crate) fn new_wire(&mut self) -> (Tree, Tree) {
function main_net (line 301) | pub(crate) fn main_net(debug: bool, main: Tree) -> Net {
FILE: vine/src/components/finder.rs
type Finder (line 20) | pub struct Finder<'a> {
type FinderCache (line 32) | pub struct FinderCache {
type FlexImpls (line 37) | pub struct FlexImpls {
constant STEPS_LIMIT (line 44) | const STEPS_LIMIT: u32 = 2_000;
type Error (line 47) | pub(crate) enum Error {
method from (line 53) | fn from(err: ErrorGuaranteed) -> Self {
function new (line 59) | pub fn new(
function find_method (line 71) | pub fn find_method(
function find_method_candidates (line 101) | fn find_method_candidates(
function find_flex (line 117) | pub fn find_flex(&mut self, types: &mut Types, ty: Type) -> Result<FlexI...
function _find_flex (line 121) | fn _find_flex(&mut self, types: &mut Types, ty: Type) -> Result<FlexImpl...
function find_impl (line 194) | pub fn find_impl(&mut self, types: &mut Types, query: &ImplType, basic: ...
function try_find_impl (line 200) | pub fn try_find_impl(
function _find_impl (line 233) | fn _find_impl(
function find_impl_params (line 275) | pub(crate) fn find_impl_params(
function find_subimpls (line 289) | fn find_subimpls(
function find_impl_candidates (line 312) | fn find_impl_candidates(
function step (line 340) | fn step(&mut self) -> Result<(), Error> {
function find_auto_impls (line 345) | fn find_auto_impls(
function general_candidates (line 378) | fn general_candidates(&self) -> &candidates::CandidateSet {
function get_candidates (line 382) | fn get_candidates<T: Copy + Hash + Ord>(
FILE: vine/src/components/finder/candidates.rs
type CandidateSets (line 21) | pub struct CandidateSets {
method build_since (line 84) | pub fn build_since(&mut self, chart: &Chart, sigs: &Signatures) {
method get_within (line 97) | pub fn get_within(&self, def: DefId) -> &CandidateSet {
method get_within_ancestors (line 101) | pub fn get_within_ancestors(&self, def: DefId) -> &CandidateSet {
method get (line 105) | fn get<'a>(&'a self, handle: &'a CandidateSetHandle) -> &'a CandidateS...
method get_owned (line 113) | fn get_owned(&self, handle: CandidateSetHandle) -> CandidateSet {
method get_mut (line 121) | fn get_mut<'a>(&self, handle: &'a mut CandidateSetHandle) -> &'a mut C...
method insert (line 127) | fn insert(&mut self, handle: CandidateSetHandle) -> CandidateSetHandle {
method merge (line 131) | fn merge(&self, chart: &Chart, a: &mut CandidateSetHandle, vis: VisId,...
type CandidateSetHandle (line 31) | pub enum CandidateSetHandle {
type Level (line 41) | pub(crate) enum Level {
type CandidateSet (line 51) | pub struct CandidateSet {
type VisSet (line 58) | pub enum VisSet {
method insert (line 70) | pub fn insert(&mut self, vis: VisId) {
method merge_vis_sets (line 322) | fn merge_vis_sets(&mut self, chart: &Chart, vis: VisId, b: &VisSet) {
method default (line 64) | fn default() -> Self {
type CandidateSetBuilder (line 166) | pub struct CandidateSetBuilder<'a> {
type NodeState (line 176) | struct NodeState {
type Node (line 181) | type Node = (DefId, Level);
function visit_all (line 184) | fn visit_all(&mut self) {
function visit (line 192) | fn visit(&mut self, node: Node) -> Option<usize> {
function for_each_child (line 248) | fn for_each_child(&mut self, (def_id, level): Node, mut f: impl FnMut(&m...
function add_direct_candidate (line 294) | fn add_direct_candidate(&self, set: &mut CandidateSetHandle, (def_id, le...
FILE: vine/src/components/lexer.rs
type Token (line 13) | pub enum Token {
method fmt (line 344) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type Lexer (line 114) | pub struct Lexer<'src> {
function new (line 120) | pub fn new(file: FileId, src: &'src str) -> Self {
function span (line 124) | pub fn span(&self) -> Span {
type Token (line 131) | type Token = Token;
method fmt (line 344) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type Error (line 132) | type Error = Diag;
function state (line 134) | fn state(&self) -> &LexerState<'src> {
function state_mut (line 138) | fn state_mut(&mut self) -> &mut LexerState<'src> {
function lex (line 142) | fn lex(&mut self) -> Result<Self::Token, Self::Error> {
function keyword (line 292) | fn keyword(str: &str) -> Option<Token> {
function is_ident (line 332) | pub fn is_ident(str: &str) -> bool {
method into_u8 (line 338) | fn into_u8(self) -> u8 {
FILE: vine/src/components/loader.rs
type Loader (line 22) | pub struct Loader<'a, F: FS> {
type Module (line 30) | pub struct Module {
function new (line 37) | pub fn new(
function load_main_mod (line 51) | pub fn load_main_mod(&mut self, name: Ident, path: F::Path) {
function load_mod (line 55) | pub fn load_mod(&mut self, name: Ident, path: F::Path) {
function _load_mod (line 59) | fn _load_mod(&mut self, name: Ident, path: F::Path, main: bool) {
function load_file (line 75) | fn load_file(
function error_mod (line 100) | fn error_mod(&mut self, diag: Diag) -> ModKind {
function load_dir (line 104) | fn load_dir(&mut self, span: Span, name: &Ident, path: DisplayPath<F>) -...
function load_child (line 109) | fn load_child(&mut self, span: Span, base: Option<&DisplayPath<F>>, name...
function load_children (line 136) | fn load_children<'t>(&mut self, base: Option<&DisplayPath<F>>, visitee: ...
type LoadChildren (line 141) | struct LoadChildren<'a, 'b, F: FS> {
function visit_item (line 147) | fn visit_item(&mut self, item: &mut Item) {
type DisplayFS (line 158) | struct DisplayFS<F>(F);
type DisplayPath (line 160) | struct DisplayPath<F: FS> {
type FS (line 211) | pub trait FS {
type Path (line 166) | type Path = DisplayPath<F>;
method kind (line 168) | fn kind(&mut self, path: &Self::Path) -> Option<EntryKind> {
method child_dir (line 172) | fn child_dir(&mut self, path: &Self::Path, name: &Ident) -> Self::Path {
method child_file (line 179) | fn child_file(&mut self, path: &Self::Path, name: &Ident) -> Self::Path {
method read_file (line 186) | fn read_file(&mut self, path: &Self::Path) -> Option<String> {
type Path (line 192) | type Path = F::Path;
method kind (line 194) | fn kind(&mut self, path: &Self::Path) -> Option<EntryKind> {
method child_dir (line 198) | fn child_dir(&mut self, path: &Self::Path, name: &Ident) -> Self::Path {
method child_file (line 202) | fn child_file(&mut self, path: &Self::Path, name: &Ident) -> Self::Path {
method read_file (line 206) | fn read_file(&mut self, path: &Self::Path) -> Option<String> {
method kind (line 214) | fn kind(&mut self, path: &Self::Path) -> Option<EntryKind>;
method child_dir (line 216) | fn child_dir(&mut self, path: &Self::Path, name: &Ident) -> Self::Path;
method child_file (line 217) | fn child_file(&mut self, path: &Self::Path, name: &Ident) -> Self::Path;
method read_file (line 219) | fn read_file(&mut self, path: &Self::Path) -> Option<String>;
type Path (line 226) | type Path = PathBuf;
method kind (line 228) | fn kind(&mut self, path: &Self::Path) -> Option<EntryKind> {
method child_dir (line 239) | fn child_dir(&mut self, path: &Self::Path, name: &Ident) -> Self::Path {
method child_file (line 243) | fn child_file(&mut self, path: &Self::Path, name: &Ident) -> Self::Path {
method read_file (line 249) | fn read_file(&mut self, path: &Self::Path) -> Option<String> {
type RealFS (line 223) | pub struct RealFS;
method detect_name (line 255) | pub fn detect_name(path: &Path) -> Option<Ident> {
type EntryKind (line 263) | pub enum EntryKind {
FILE: vine/src/components/matcher.rs
function distill_pattern_match (line 18) | pub fn distill_pattern_match(
type MatchVarForm (line 40) | pub(crate) enum MatchVarForm {
type Row (line 48) | pub struct Row<'p> {
type MatchVar (line 55) | pub(crate) struct MatchVar {
type MatchVarKind (line 61) | pub(crate) enum MatchVarKind {
method form (line 70) | fn form(&self) -> MatchVarForm {
function new (line 79) | pub fn new(pat: Option<&'p TirPat>, arm: InterfaceId) -> Self {
function add (line 87) | fn add(&mut self, var: VarId, pat: &'p TirPat) {
type Matcher (line 97) | pub(crate) struct Matcher<'d, 'r> {
function distill_rows (line 104) | pub(crate) fn distill_rows<'p>(
function eliminate_col (line 152) | pub(crate) fn eliminate_col<
function new_var (line 178) | pub(crate) fn new_var(
function distill_row (line 190) | fn distill_row<'p>(&mut self, stage: &mut Stage, vars: &IdxVec<VarId, Ma...
function borrow_var (line 209) | pub(crate) fn borrow_var(
function restore_var (line 221) | pub(crate) fn restore_var(
function take_var (line 239) | pub(crate) fn take_var(
function set_var (line 269) | fn set_var(&mut self, stage: &mut Stage, var: &MatchVar) -> Option<Port> {
FILE: vine/src/components/normalizer.rs
function normalize (line 22) | pub fn normalize(
type Normalizer (line 65) | struct Normalizer<'a> {
function normalize_layer (line 86) | fn normalize_layer(&mut self, layer: &Layer) {
function layer_divergence (line 193) | fn layer_divergence(&mut self, layer: &Layer) -> LayerId {
function step_divergence (line 211) | fn step_divergence(&mut self, step: &Step) -> LayerId {
function update_open_wires (line 224) | fn update_open_wires(open_wires: &mut BTreeMap<WireId, (Span, Type)>, po...
FILE: vine/src/components/parser.rs
type Parser (line 21) | pub struct Parser<'src> {
type Token (line 27) | type Token = Token;
type Lexer (line 28) | type Lexer = Lexer<'src>;
type Error (line 29) | type Error = Diag;
function state (line 31) | fn state(&mut self) -> &mut ParserState<'src, Lexer<'src>> {
function unexpected_error (line 35) | fn unexpected_error(&self) -> Diag {
function new (line 45) | pub fn new(lexer: Lexer<'src>) -> Result<Self, Diag> {
function parse (line 49) | pub fn parse(file: FileId, src: &'src str) -> Result<Vec<Item>, Diag> {
function parse_item (line 58) | pub(crate) fn parse_item(&mut self) -> Result<Item, Diag> {
function maybe_parse_item (line 62) | fn maybe_parse_item(&mut self) -> Result<Option<Item>, Diag> {
function parse_vis (line 98) | pub(crate) fn parse_vis(&mut self) -> Result<Vis, Diag> {
function parse_attr (line 113) | fn parse_attr(&mut self) -> Result<Attr, Diag> {
function parse_ident (line 147) | pub fn parse_ident(&mut self) -> Result<Ident, Diag> {
function parse_flex (line 152) | pub(crate) fn parse_flex(&mut self) -> Result<Flex, Diag> {
function parse_exprs (line 164) | pub(crate) fn parse_exprs(&mut self) -> Result<Vec<Expr>, Diag> {
function parse_expr (line 168) | pub(crate) fn parse_expr(&mut self) -> Result<Expr, Diag> {
function maybe_parse_expr_bp (line 172) | pub(crate) fn maybe_parse_expr_bp(&mut self, bp: BP) -> Result<Option<Ex...
function parse_expr_bp (line 185) | pub(crate) fn parse_expr_bp(&mut self, bp: BP) -> Result<Expr, Diag> {
function maybe_parse_expr_prefix (line 192) | fn maybe_parse_expr_prefix(&mut self) -> Result<Option<Expr>, Diag> {
function _maybe_parse_expr_prefix (line 201) | fn _maybe_parse_expr_prefix(&mut self, span: usize) -> Result<Option<Exp...
function parse_expr_postfix (line 289) | fn parse_expr_postfix(&mut self, lhs: Expr, bp: BP) -> Result<Result<Exp...
function parse_pats (line 414) | pub(crate) fn parse_pats(&mut self) -> Result<Vec<Pat>, Diag> {
function parse_pat (line 418) | pub(crate) fn parse_pat(&mut self) -> Result<Pat, Diag> {
function parse_pat_bp (line 422) | pub(crate) fn parse_pat_bp(&mut self, bp: BP) -> Result<Pat, Diag> {
function parse_pat_prefix (line 433) | fn parse_pat_prefix(&mut self) -> Result<Pat, Diag> {
function _parse_pat_prefix (line 440) | fn _parse_pat_prefix(&mut self, span: usize) -> Result<PatKind, Diag> {
function parse_pat_postfix (line 471) | fn parse_pat_postfix(&mut self, lhs: Pat, bp: BP) -> Result<Result<PatKi...
function parse_ty (line 479) | pub(crate) fn parse_ty(&mut self) -> Result<Ty, Diag> {
function _parse_ty (line 486) | fn _parse_ty(&mut self, span: usize) -> Result<TyKind, Diag> {
function parse_arrow_ty (line 522) | pub(crate) fn parse_arrow_ty(&mut self) -> Result<Option<Ty>, Diag> {
function parse_impl (line 526) | pub(crate) fn parse_impl(&mut self) -> Result<Impl, Diag> {
function _parse_impl (line 533) | fn _parse_impl(&mut self) -> Result<ImplKind, Diag> {
function parse_trait (line 550) | pub(crate) fn parse_trait(&mut self) -> Result<Trait, Diag> {
function _parse_trait (line 557) | fn _parse_trait(&mut self) -> Result<TraitKind, Diag> {
function parse_stmt (line 570) | pub(crate) fn parse_stmt(&mut self) -> Result<Stmt, Diag> {
function _parse_stmt (line 577) | fn _parse_stmt(&mut self) -> Result<StmtKind, Diag> {
function start_span (line 620) | pub(crate) fn start_span(&self) -> usize {
function end_span (line 624) | pub(crate) fn end_span(&self, span: usize) -> Span {
function span (line 628) | pub(crate) fn span(&self) -> Span {
type Delimiters (line 635) | pub(crate) type Delimiters = vine_util::parser::Delimiters<Token>;
constant PAREN_COMMA (line 637) | pub(crate) const PAREN_COMMA: Delimiters = Delimiters {
constant BRACE (line 643) | pub(crate) const BRACE: Delimiters =
constant BRACE_COMMA (line 646) | pub(crate) const BRACE_COMMA: Delimiters = Delimiters {
constant BRACKET_COMMA (line 652) | pub(crate) const BRACKET_COMMA: Delimiters = Delimiters {
constant PATH (line 658) | pub(crate) const PATH: Delimiters =
type Associativity (line 663) | enum Associativity {
type BP (line 671) | pub(crate) enum BP {
method inc (line 693) | const fn inc(self) -> Self {
method permits (line 697) | pub(crate) fn permits(self, other: Self) -> bool {
constant BINARY_OP_TABLE (line 703) | const BINARY_OP_TABLE: &[(BP, Associativity, Token, BinaryOp)] = &[
constant COMPARISON_OP_TABLE (line 719) | const COMPARISON_OP_TABLE: &[(Token, ComparisonOp)] = &[
FILE: vine/src/components/resolver.rs
type Resolver (line 33) | pub struct Resolver<'a> {
type ScopeEntry (line 60) | pub(crate) struct ScopeEntry {
type TargetInfo (line 67) | pub(crate) struct TargetInfo {
type ScopeBinding (line 74) | pub(crate) enum ScopeBinding {
function new (line 80) | pub fn new(
function resolve_all (line 115) | pub fn resolve_all(&mut self) {
function resolve_since (line 119) | pub(crate) fn resolve_since(&mut self, checkpoint: &Checkpoint) {
function resolve_main (line 179) | fn resolve_main(&mut self, main_mod: DefId) {
function _resolve_main (line 190) | fn _resolve_main(&mut self, main_mod: DefId) -> Result<ConcreteFnId, Dia...
function initialize (line 203) | pub(crate) fn initialize(&mut self, def_id: DefId, generics_id: Generics...
function _resolve_repl (line 220) | pub(crate) fn _resolve_repl(
function expect_fn_sig (line 265) | pub(crate) fn expect_fn_sig(
function expect_entrypoint_sig (line 282) | pub(crate) fn expect_entrypoint_sig(&mut self, concrete_fn_id: ConcreteF...
function resolve_trait (line 303) | pub(crate) fn resolve_trait(&mut self, trait_: &Trait) -> ImplType {
function resolve_impl_type (line 321) | pub(crate) fn resolve_impl_type(&mut self, impl_: &Impl, ty: &ImplType) ...
function find_impl (line 332) | pub(crate) fn find_impl(&mut self, span: Span, ty: &ImplType, basic: boo...
function bind (line 345) | pub(crate) fn bind(&mut self, ident: Ident, binding: ScopeBinding) {
function enter_scope (line 360) | pub(crate) fn enter_scope(&mut self) {
function exit_scope (line 364) | pub(crate) fn exit_scope(&mut self) {
function finish_binding (line 380) | fn finish_binding(
function error_expr (line 399) | pub(crate) fn error_expr(&mut self, span: Span, diag: Diag) -> TirExpr {
function error_pat (line 404) | pub(crate) fn error_pat(&mut self, span: Span, diag: Diag) -> TirPat {
function expect_type (line 409) | pub(crate) fn expect_type(
function finish_fragment (line 426) | pub(crate) fn finish_fragment(
function builtin_ty (line 450) | pub(crate) fn builtin_ty(
function bool (line 463) | pub(crate) fn bool(&mut self, span: Span) -> Type {
function builtin_fn (line 467) | pub(crate) fn builtin_fn<const N: usize>(
function resolve_expr_type (line 488) | pub(crate) fn resolve_expr_type(&mut self, expr: &Expr, ty: Type) -> Tir...
function resolve_expr (line 494) | pub(crate) fn resolve_expr(&mut self, expr: &Expr) -> TirExpr {
function _resolve_expr (line 498) | pub(crate) fn _resolve_expr(&mut self, expr: &Expr) -> Result<TirExpr, D...
function resolve_pat_type (line 565) | pub(crate) fn resolve_pat_type(&mut self, pat: &Pat, ty: Type) -> TirPat {
function resolve_pat (line 574) | pub(crate) fn resolve_pat(&mut self, pat: &Pat) -> TirPat {
function _resolve_pat (line 578) | pub(crate) fn _resolve_pat(&mut self, pat: &Pat) -> Result<TirPat, Diag> {
function resolve_pat_sig (line 595) | pub(crate) fn resolve_pat_sig(&mut self, pat: &Pat, inference: bool) -> ...
function resolve_ty (line 615) | pub(crate) fn resolve_ty(&mut self, ty: &Ty, inference: bool) -> Type {
function resolve_arrow_ty (line 635) | pub(crate) fn resolve_arrow_ty(&mut self, span: Span, ty: &Option<Ty>, i...
function resolve_test_fn (line 648) | pub(crate) fn resolve_test_fn(&mut self, concrete_fn_id: ConcreteFnId) {
function safe (line 654) | pub(crate) fn safe<T>(&mut self, span: Span, f: impl FnOnce(&mut Self) -...
function unsafe_ (line 671) | pub(crate) fn unsafe_(&mut self, span: Span) {
FILE: vine/src/components/specializer.rs
type Specializer (line 21) | pub struct Specializer<'a> {
function specialize_since (line 30) | pub fn specialize_since(&mut self, checkpoint: &Checkpoint) {
function specialize (line 38) | fn specialize(&mut self, id: FragmentId, impl_args: Vec<ImplTree>) -> Sp...
function instantiate_rels (line 58) | fn instantiate_rels(
function instantiate_const_rel (line 74) | fn instantiate_const_rel(
function instantiate_fn_rel (line 120) | fn instantiate_fn_rel(
function instantiate_fn_id (line 152) | pub(crate) fn instantiate_fn_id(
function instantiate_synthetic_item (line 221) | fn instantiate_synthetic_item(&mut self, item: SyntheticItem, impls: Vec...
function _closure_stage (line 242) | fn _closure_stage(&self, fragment_id: FragmentId, closure_id: Option<Clo...
function _closure_interface (line 249) | fn _closure_interface(
function instantiate (line 262) | pub(crate) fn instantiate(
FILE: vine/src/components/synthesizer.rs
type SyntheticImpl (line 25) | pub enum SyntheticImpl {
method fn_ (line 424) | pub fn fn_(self, _: &Chart, fn_id: TraitFnId) -> SyntheticItem {
method const_ (line 444) | pub fn const_(self, chart: &Chart, const_id: TraitConstId) -> Syntheti...
type SyntheticItem (line 35) | pub enum SyntheticItem {
method rels (line 473) | pub fn rels(&self) -> Rels {
type Synthesizer (line 52) | struct Synthesizer<'a> {
function synthesize (line 64) | pub fn synthesize(
function new_wire (line 89) | fn new_wire(&mut self) -> (Tree, Tree) {
function list (line 94) | fn list<T>(
function string (line 114) | fn string(&mut self, str: &str) -> Tree {
function synthesize (line 118) | fn synthesize(&mut self, item: &SyntheticItem) {
function synthesize_composite_deconstruct (line 139) | fn synthesize_composite_deconstruct(&mut self, len: usize) -> Net {
function synthesize_composite_reconstruct (line 148) | fn synthesize_composite_reconstruct(&mut self, len: usize) -> Net {
function synthesize_ident (line 158) | fn synthesize_ident(&mut self, ident: Ident) -> Net {
function synthesize_identity (line 163) | fn synthesize_identity(&mut self) -> Net {
function new_stage (line 168) | fn new_stage(&mut self) -> String {
function synthesize_enum_variant_names (line 173) | fn synthesize_enum_variant_names(&mut self, enum_id: EnumId) -> Net {
function synthesize_enum_match (line 179) | fn synthesize_enum_match(&mut self, enum_id: EnumId) -> Net {
function synthesize_enum_reconstruct (line 225) | fn synthesize_enum_reconstruct(&mut self, enum_id: EnumId) -> Net {
function synthesize_const_alias (line 258) | fn synthesize_const_alias(&self) -> Net {
function synthesize_fn_from_call (line 262) | fn synthesize_fn_from_call(&mut self, params: usize) -> Net {
function synthesize_call_from_fn (line 267) | fn synthesize_call_from_fn(&mut self, params: usize) -> Net {
function _fn_call (line 272) | fn _fn_call(&mut self, params: usize) -> (Tree, Tree) {
function synthesize_frame (line 299) | fn synthesize_frame(&mut self, path: String, span: Span) -> Net {
function synthesize_debug_state (line 308) | fn synthesize_debug_state(&mut self) -> Net {
function synthesize_n32 (line 326) | fn synthesize_n32(&mut self, n32: u32) -> Net {
function synthesize_string (line 330) | fn synthesize_string(&mut self, string: String) -> Net {
function enum_ (line 334) | fn enum_(
function match_enum (line 351) | fn match_enum(
function variant (line 373) | fn variant(&mut self, variant_id: VariantId, data: Option<Tree>) -> Tree {
function fn_rel (line 382) | fn fn_rel(&self, id: FnRelId) -> Tree {
function const_rel (line 391) | fn const_rel(&self, id: ConstRelId) -> Tree {
function fn_receiver (line 400) | fn fn_receiver(&mut self) -> Tree {
function const_ (line 413) | fn const_(&mut self, value: Tree) -> Net {
FILE: vine/src/features/annotation.rs
function resolve_pat_annotation (line 12) | pub(crate) fn resolve_pat_annotation(
function fmt_pat_annotation (line 24) | pub(crate) fn fmt_pat_annotation(&self, pat: &Pat, ty: &Ty) -> Doc<'src> {
FILE: vine/src/features/assert.rs
function parse_stmt_assert (line 15) | pub(crate) fn parse_stmt_assert(&mut self) -> Result<StmtKind, Diag> {
function fmt_stmt_assert (line 25) | pub(crate) fn fmt_stmt_assert(&self, stmt: &AssertStmt) -> Doc<'src> {
function resolve_stmts_assert (line 36) | pub(crate) fn resolve_stmts_assert(
FILE: vine/src/features/block.rs
function parse_block (line 20) | pub(crate) fn parse_block(&mut self) -> Result<Block, Diag> {
function fmt_block (line 29) | pub(crate) fn fmt_block(&self, block: &Block, force_open: bool) -> Doc<'...
function resolve_block_nil (line 46) | pub(crate) fn resolve_block_nil(&mut self, block: &Block) -> TirExpr {
function resolve_block_type (line 51) | pub(crate) fn resolve_block_type(&mut self, block: &Block, ty: Type) -> ...
function resolve_stmts_type (line 58) | pub(crate) fn resolve_stmts_type(&mut self, span: Span, stmts: &[Stmt], ...
function distill_seq (line 110) | pub(crate) fn distill_seq(
FILE: vine/src/features/builtin.rs
type Builtin (line 16) | pub enum Builtin {
function parse_builtin (line 66) | pub(crate) fn parse_builtin(&mut self) -> Result<Builtin, Diag> {
type Builtins (line 139) | pub struct Builtins {
function chart_builtin (line 199) | pub(crate) fn chart_builtin(&mut self, item: ChartedItem, builtin: Built...
FILE: vine/src/features/cast.rs
function fmt_expr_cast (line 12) | pub(crate) fn fmt_expr_cast(&self, expr: &Expr, ty: &Ty, postfix: bool) ...
function resolve_expr_cast (line 22) | pub(crate) fn resolve_expr_cast(
FILE: vine/src/features/coerce.rs
function distill_expr_value_coerce_poly (line 16) | pub(crate) fn distill_expr_value_coerce_poly(
function distill_expr_space_coerce_poly (line 33) | pub(crate) fn distill_expr_space_coerce_poly(
function distill_expr_place_coerce_poly (line 50) | pub(crate) fn distill_expr_place_coerce_poly(
function distill_expr_nil_coerce_value (line 65) | pub(crate) fn distill_expr_nil_coerce_value(&mut self, stage: &mut Stage...
function distill_expr_value_coerce_nil (line 70) | pub(crate) fn distill_expr_value_coerce_nil(
function coerce_place_value (line 80) | fn coerce_place_value(&mut self, span: Span, stage: &mut Stage, place: (...
function coerce_place_space (line 84) | fn coerce_place_space(&mut self, span: Span, stage: &mut Stage, place: (...
function _coerce_place (line 88) | fn _coerce_place(
function drop (line 142) | pub(crate) fn drop(&mut self, span: Span, stage: &mut Stage, ty: Type, p...
function drop_space (line 153) | pub(crate) fn drop_space(&mut self, span: Span, stage: &mut Stage, ty: T...
FILE: vine/src/features/composite.rs
function parse_expr_paren (line 28) | pub(crate) fn parse_expr_paren(&mut self) -> Result<ExprKind, Diag> {
function parse_pat_paren (line 58) | pub(crate) fn parse_pat_paren(&mut self) -> Result<PatKind, Diag> {
function parse_ty_paren (line 74) | pub(crate) fn parse_ty_paren(&mut self) -> Result<TyKind, Diag> {
function _parse_expr_tuple_field (line 90) | pub(crate) fn _parse_expr_tuple_field(&mut self, lhs: Expr) -> Result<Ex...
function parse_expr_object (line 97) | pub(crate) fn parse_expr_object(&mut self) -> Result<ExprKind, Diag> {
function parse_pat_object (line 109) | pub(crate) fn parse_pat_object(&mut self) -> Result<PatKind, Diag> {
function parse_ty_object (line 136) | pub(crate) fn parse_ty_object(&mut self) -> Result<TyKind, Diag> {
function parse_key (line 145) | fn parse_key(&mut self) -> Result<Key, Diag> {
function fmt_expr_tuple (line 154) | pub(crate) fn fmt_expr_tuple(&self, t: &[Expr]) -> Doc<'src> {
function fmt_expr_tuple_field (line 158) | pub(crate) fn fmt_expr_tuple_field(&self, expr: &Expr, index: usize) -> ...
function fmt_pat_tuple (line 162) | pub(crate) fn fmt_pat_tuple(&self, t: &[Pat]) -> Doc<'src> {
function fmt_ty_tuple (line 166) | pub(crate) fn fmt_ty_tuple(&self, elements: &[Ty]) -> Doc<'src> {
function fmt_expr_object (line 170) | pub(crate) fn fmt_expr_object(&self, entries: &[(Key, Expr)]) -> Doc<'sr...
function fmt_expr_object_field (line 182) | pub(crate) fn fmt_expr_object_field(&self, expr: &Expr, key: &Key) -> Do...
function fmt_pat_object (line 186) | pub(crate) fn fmt_pat_object(&self, entries: &[(Key, Pat)]) -> Doc<'src> {
function fmt_ty_object (line 216) | pub(crate) fn fmt_ty_object(&self, entries: &[(Key, Ty)]) -> Doc<'src> {
function resolve_expr_tuple (line 224) | pub(crate) fn resolve_expr_tuple(
function resolve_pat_tuple (line 234) | pub(crate) fn resolve_pat_tuple(&mut self, span: Span, elements: &[Pat])...
function resolve_pat_sig_tuple (line 240) | pub(crate) fn resolve_pat_sig_tuple(&mut self, elements: &[Pat], inferen...
function resolve_ty_tuple (line 246) | pub(crate) fn resolve_ty_tuple(&mut self, tys: &[Ty], inference: bool) -...
function resolve_expr_object (line 251) | pub(crate) fn resolve_expr_object(
function resolve_pat_object (line 262) | pub(crate) fn resolve_pat_object(
function resolve_pat_sig_object (line 273) | pub(crate) fn resolve_pat_sig_object(&mut self, entries: &[(Key, Pat)], ...
function resolve_ty_object (line 277) | pub(crate) fn resolve_ty_object(&mut self, entries: &[(Key, Ty)], infere...
function _build_object (line 281) | fn _build_object<T, U>(
function _build_object_type (line 298) | fn _build_object_type<T>(
function resolve_expr_tuple_field (line 318) | pub(crate) fn resolve_expr_tuple_field(
function _resolve_expr_tuple_field (line 333) | fn _resolve_expr_tuple_field(
function resolve_expr_object_field (line 356) | pub(crate) fn resolve_expr_object_field(
function _resolve_expr_object_field (line 373) | fn _resolve_expr_object_field(
function distill_expr_value_composite (line 415) | pub(crate) fn distill_expr_value_composite(
function distill_expr_space_composite (line 425) | pub(crate) fn distill_expr_space_composite(
function distill_expr_place_composite (line 435) | pub(crate) fn distill_expr_place_composite(
function distill_expr_poly_composite (line 445) | pub(crate) fn distill_expr_poly_composite(
function distill_pat_value_composite (line 494) | pub(crate) fn distill_pat_value_composite(
function distill_pat_space_composite (line 504) | pub(crate) fn distill_pat_space_composite(
function distill_pat_place_composite (line 514) | pub(crate) fn distill_pat_place_composite(
function distill_expr_poly_field (line 531) | pub(crate) fn distill_expr_poly_field(
function match_composite (line 573) | pub(crate) fn match_composite<'p>(
function emit_composite (line 604) | pub(crate) fn emit_composite(&mut self, port: &Port, tuple: &[Port]) {
function find_auto_impls_tuple (line 611) | pub(crate) fn find_auto_impls_tuple(
function find_auto_impls_object (line 641) | pub(crate) fn find_auto_impls_object(
FILE: vine/src/features/condition.rs
function fmt_expr_bool (line 16) | pub(crate) fn fmt_expr_bool(&self, bool: bool) -> Doc<'src> {
function fmt_expr_not (line 20) | pub(crate) fn fmt_expr_not(&self, expr: &Expr) -> Doc<'src> {
function fmt_expr_is (line 24) | pub(crate) fn fmt_expr_is(&self, expr: &Expr, pat: &Pat) -> Doc<'src> {
function fmt_expr_logical_op (line 28) | pub(crate) fn fmt_expr_logical_op(&self, op: &LogicalOp, lhs: &Expr, rhs...
function resolve_expr_not (line 42) | pub(crate) fn resolve_expr_not(&mut self, span: Span, inner: &Expr) -> R...
function resolve_cond (line 55) | pub(crate) fn resolve_cond(&mut self, cond: &Expr) -> TirExpr {
function resolve_scoped_cond (line 62) | pub(crate) fn resolve_scoped_cond(&mut self, cond: &Expr) -> TirExpr {
function _resolve_scoped_cond (line 72) | pub(crate) fn _resolve_scoped_cond(&mut self, cond: &Expr) -> Result<Tir...
function distill_cond_bool (line 112) | pub(crate) fn distill_cond_bool(
function distill_cond (line 155) | pub(crate) fn distill_cond(
function swap (line 222) | fn swap<T>((a, b): (T, T)) -> (T, T) {
function swap_if (line 226) | fn swap_if<T>(bool: bool, (a, b): (T, T)) -> (T, T) {
FILE: vine/src/features/const_.rs
function parse_const_item (line 30) | pub(crate) fn parse_const_item(&mut self) -> Result<(Span, ItemKind), Di...
function fmt_const_item (line 44) | pub(crate) fn fmt_const_item(&self, c: &ConstItem) -> Doc<'src> {
function chart_const (line 61) | pub(crate) fn chart_const(
function resolve_const_sig (line 89) | pub(crate) fn resolve_const_sig(&mut self, const_id: ConcreteConstId) {
function resolve_const_def (line 106) | pub(crate) fn resolve_const_def(&mut self, const_id: ConcreteConstId) {
function resolve_config (line 128) | fn resolve_config(&mut self, span: Span, const_id: ConcreteConstId, name...
function resolve_expr_path_const (line 171) | pub(crate) fn resolve_expr_path_const(
function distill_expr_value_const (line 189) | pub(crate) fn distill_expr_value_const(
function emit_const (line 203) | pub(crate) fn emit_const(&mut self, span: &Span, rel: &ConstRelId, out: ...
FILE: vine/src/features/debug.rs
function tap_debug (line 14) | pub(crate) fn tap_debug(&mut self) -> Tree {
function tap_debug_call (line 20) | pub(crate) fn tap_debug_call(&mut self, span: Span) -> Tree {
function with_debug (line 62) | pub fn with_debug(&mut self, inner: Tree) -> Tree {
function main_net_debug (line 78) | pub(crate) fn main_net_debug(main: Tree) -> Net {
FILE: vine/src/features/do_.rs
function parse_expr_do (line 20) | pub(crate) fn parse_expr_do(&mut self) -> Result<ExprKind, Diag> {
function fmt_expr_do (line 30) | pub(crate) fn fmt_expr_do(&self, label: Label, ty: &Option<Ty>, body: &B...
function resolve_expr_do (line 42) | pub(crate) fn resolve_expr_do(
function distill_do (line 62) | pub(crate) fn distill_do(
FILE: vine/src/features/enum_.rs
function parse_enum_item (line 34) | pub(crate) fn parse_enum_item(&mut self) -> Result<(Span, ItemKind), Dia...
function parse_variant (line 46) | fn parse_variant(&mut self) -> Result<Variant, Diag> {
function fmt_enum_item (line 54) | pub(crate) fn fmt_enum_item(&self, e: &EnumItem) -> Doc<'src> {
function chart_enum (line 78) | pub(crate) fn chart_enum(
function resolve_enum_sig (line 108) | pub(crate) fn resolve_enum_sig(&mut self, enum_id: EnumId) {
function resolve_expr_path_enum (line 126) | pub(crate) fn resolve_expr_path_enum(
function resolve_pat_path_enum (line 159) | pub(crate) fn resolve_pat_path_enum(
function resolve_pat_sig_path_enum (line 189) | pub(crate) fn resolve_pat_sig_path_enum(&mut self, path: &Path, enum_id:...
function resolve_ty_path_enum (line 194) | pub(crate) fn resolve_ty_path_enum(
function distill_expr_value_enum (line 207) | pub(crate) fn distill_expr_value_enum(
function match_enum (line 224) | pub(crate) fn match_enum<'p>(
function emit_enum (line 271) | pub(crate) fn emit_enum(
function find_auto_impls_enum (line 300) | pub(crate) fn find_auto_impls_enum(
FILE: vine/src/features/flex.rs
function find_auto_impls_fork (line 10) | pub(crate) fn find_auto_impls_fork(
function find_auto_impls_drop (line 29) | pub(crate) fn find_auto_impls_drop(
FILE: vine/src/features/fn_.rs
function parse_fn_item (line 33) | pub(crate) fn parse_fn_item(&mut self) -> Result<(Span, ItemKind), Diag> {
function parse_expr_fn (line 45) | pub(crate) fn parse_expr_fn(&mut self) -> Result<ExprKind, Diag> {
function parse_stmt_return (line 54) | pub(crate) fn parse_stmt_return(&mut self) -> Result<StmtKind, Diag> {
function _parse_stmt_let_fn (line 60) | pub(crate) fn _parse_stmt_let_fn(&mut self) -> Result<StmtKind, Diag> {
function fmt_fn_item (line 73) | pub(crate) fn fmt_fn_item(&self, f: &FnItem) -> Doc<'src> {
function fmt_stmt_let_fn (line 89) | pub(crate) fn fmt_stmt_let_fn(&self, d: &LetFnStmt) -> Doc<'src> {
function fmt_expr_fn (line 102) | pub(crate) fn fmt_expr_fn(
function fmt_expr_call (line 120) | pub(crate) fn fmt_expr_call(&self, func: &Expr, args: &[Expr]) -> Doc<'s...
function fmt_stmt_return (line 124) | pub(crate) fn fmt_stmt_return(&self, expr: &Option<Expr>) -> Doc<'src> {
function fmt_return_ty (line 131) | fn fmt_return_ty(&self, r: Option<&Ty>) -> Doc<'src> {
function chart_fn (line 140) | pub(crate) fn chart_fn(
function resolve_fn_sig (line 170) | pub(crate) fn resolve_fn_sig(&mut self, fn_id: ConcreteFnId) {
function _resolve_fn_sig (line 189) | pub(crate) fn _resolve_fn_sig(&mut self, params: &[Pat], ret: &Option<Ty...
function resolve_fn_def (line 195) | pub(crate) fn resolve_fn_def(&mut self, fn_id: ConcreteFnId) {
function resolve_expr_fn (line 209) | pub(crate) fn resolve_expr_fn(
function resolve_stmts_let_fn_group (line 221) | pub(crate) fn resolve_stmts_let_fn_group<'s>(&mut self, mut stmts: &'s [...
function resolve_closure (line 258) | pub(crate) fn resolve_closure(
function resolve_expr_path_fn (line 288) | pub(crate) fn resolve_expr_path_fn(
function resolve_ty_fn (line 329) | pub(crate) fn resolve_ty_fn(&mut self, path: &Path) -> Type {
function resolve_trait_fn (line 336) | pub(crate) fn resolve_trait_fn(
function resolve_impl_fn (line 355) | pub(crate) fn resolve_impl_fn(&mut self, span: Span, path: &Path, ty: &I...
function resolve_expr_call (line 383) | pub(crate) fn resolve_expr_call(
function _resolve_expr_call (line 393) | pub(crate) fn _resolve_expr_call(
function resolve_expr_return (line 412) | pub(crate) fn resolve_expr_return(
function param_name (line 435) | pub(crate) fn param_name(&self, param: &Pat) -> Option<Ident> {
function distill_closures (line 454) | pub(crate) fn distill_closures(&mut self, fragment: &Fragment) {
function distill_closure (line 463) | fn distill_closure(&mut self, id: ClosureId, closure: &TirClosure) {
function distill_expr_value_fn (line 507) | pub(crate) fn distill_expr_value_fn(&mut self, ty: Type) -> Port {
function distill_expr_value_closure (line 511) | pub(crate) fn distill_expr_value_closure(
function distill_expr_value_call (line 524) | pub(crate) fn distill_expr_value_call(
function distill_return (line 540) | pub(crate) fn distill_return(&mut self, stage: &mut Stage, span: Span, v...
function emit_call (line 553) | pub(crate) fn emit_call(
function find_auto_impls_fn (line 578) | pub(crate) fn find_auto_impls_fn(
FILE: vine/src/features/for_.rs
function parse_expr_for (line 24) | pub(crate) fn parse_expr_for(&mut self) -> Result<ExprKind, Diag> {
function fmt_expr_for (line 38) | pub(crate) fn fmt_expr_for(
function resolve_expr_for (line 66) | pub(crate) fn resolve_expr_for(
function distill_for (line 116) | pub(crate) fn distill_for(
FILE: vine/src/features/generics.rs
function parse_generic_params (line 21) | pub(crate) fn parse_generic_params(&mut self) -> Result<GenericParams, D...
function parse_type_param (line 25) | pub(crate) fn parse_type_param(&mut self) -> Result<TypeParam, Diag> {
function parse_impl_param (line 33) | fn parse_impl_param(&mut self) -> Result<ImplParam, Diag> {
function parse_generic_args (line 50) | pub(crate) fn parse_generic_args(&mut self) -> Result<GenericArgs, Diag> {
function parse_generics (line 54) | fn parse_generics<T, I>(
function parse_generics_section (line 74) | fn parse_generics_section<E>(
function fmt_generic_params (line 93) | pub(crate) fn fmt_generic_params(&self, generics: &GenericParams) -> Doc...
function fmt_generic_args (line 97) | pub(crate) fn fmt_generic_args(&self, generics: &GenericArgs) -> Doc<'sr...
function fmt_type_param (line 101) | pub(crate) fn fmt_type_param(&self, param: &TypeParam) -> Doc<'src> {
function fmt_impl_param (line 105) | fn fmt_impl_param(&self, param: &ImplParam) -> Doc<'src> {
function fmt_generics (line 112) | pub(crate) fn fmt_generics<T, I>(
function fmt_generics_section (line 147) | fn fmt_generics_section<E>(
function chart_generics (line 166) | pub(crate) fn chart_generics(
function resolve_type_params (line 184) | pub(crate) fn resolve_type_params(&mut self, generics_id: GenericsId) {
function resolve_impl_params (line 206) | pub(crate) fn resolve_impl_params(&mut self, generics_id: GenericsId) {
function resolve_generics (line 278) | pub fn resolve_generics(
function _resolve_generics (line 287) | pub(crate) fn _resolve_generics(
function show_generics (line 363) | pub(crate) fn show_generics(&self, generics: GenericsId, impl_params: bo...
FILE: vine/src/features/hole.rs
function parse_expr_hole (line 17) | pub(crate) fn parse_expr_hole(&mut self) -> Result<ExprKind, Diag> {
function resolve_expr_hole (line 28) | pub(crate) fn resolve_expr_hole(&mut self, span: Span, ty: Option<&Ty>) ...
function resolve_pat_hole (line 33) | pub(crate) fn resolve_pat_hole(&mut self, span: Span) -> Result<TirPat, ...
function resolve_ty_hole (line 37) | pub(crate) fn resolve_ty_hole(&mut self, span: Span, inference: bool) ->...
function distill_expr_value_hole (line 47) | pub(crate) fn distill_expr_value_hole(
function distill_expr_space_hole (line 63) | pub(crate) fn distill_expr_space_hole(
function distill_expr_place_hole (line 72) | pub(crate) fn distill_expr_place_hole(
function distill_pat_value_hole (line 81) | pub(crate) fn distill_pat_value_hole(&mut self, stage: &mut Stage, span:...
function distill_pat_space_hole (line 85) | pub(crate) fn distill_pat_space_hole(&mut self, stage: &mut Stage, span:...
function distill_pat_place_hole (line 89) | pub(crate) fn distill_pat_place_hole(
function fmt_expr_hole (line 101) | pub(crate) fn fmt_expr_hole(&self, ty: &Option<Ty>) -> Doc<'src> {
FILE: vine/src/features/if_.rs
function parse_expr_if (line 20) | pub(crate) fn parse_expr_if(&mut self) -> Result<ExprKind, Diag> {
function parse_ty_if (line 36) | pub(crate) fn parse_ty_if(&mut self) -> Result<TyKind, Diag> {
function fmt_expr_if (line 54) | pub(crate) fn fmt_expr_if(
function fmt_expr_if_const (line 74) | pub(crate) fn fmt_expr_if_const(
function fmt_ty_if_const (line 92) | pub(crate) fn fmt_ty_if_const(&self, cond: &Path, then: &Ty, else_: &Opt...
function resolve_expr_if (line 108) | pub(crate) fn resolve_expr_if(
function resolve_expr_if_const (line 129) | pub(crate) fn resolve_expr_if_const(
function resolve_ty_if_const (line 170) | pub(crate) fn resolve_ty_if_const(
function distill_if (line 204) | pub(crate) fn distill_if(
function find_auto_impls_if_const (line 236) | pub(crate) fn find_auto_impls_if_const(
FILE: vine/src/features/impl_.rs
function parse_impl_item (line 30) | pub(crate) fn parse_impl_item(&mut self) -> Result<(Span, ItemKind), Dia...
function fmt_impl_item (line 53) | pub(crate) fn fmt_impl_item(&self, i: &ImplItem) -> Doc<'src> {
function chart_impl (line 76) | pub(crate) fn chart_impl(
function chart_impl_fn (line 144) | fn chart_impl_fn(
function chart_impl_const (line 183) | fn chart_impl_const(
function chart_flex_impls (line 220) | pub fn chart_flex_impls(
function chart_derive_impls (line 237) | pub fn chart_derive_impls(
function chart_derive_impl (line 250) | fn chart_derive_impl(
function resolve_impl_sig (line 283) | pub(crate) fn resolve_impl_sig(&mut self, impl_id: ImplId) {
function resolve_derive_kind (line 323) | pub(crate) fn resolve_derive_kind(&mut self, kind: &DeriveKind) -> Resul...
function resolve_derive_impl_ty (line 350) | fn resolve_derive_impl_ty(&mut self, kind: &DeriveKind, ty: DefTypeKind)...
function resolve_impl_def (line 375) | pub(crate) fn resolve_impl_def(&mut self, impl_id: ImplId) {
function resolve_impl_become (line 420) | pub(crate) fn resolve_impl_become(&mut self, impl_id: ImplId) -> Become {
function _resolve_impl_become (line 438) | fn _resolve_impl_become(
function resolve_tir_impl_become (line 479) | fn resolve_tir_impl_become(
function resolve_impl_subitem_fn (line 497) | fn resolve_impl_subitem_fn(
function resolve_impl_subitem_const (line 528) | fn resolve_impl_subitem_const(
function resolve_impl_subitem_generics (line 566) | fn resolve_impl_subitem_generics(
function resolve_impl_path_impl (line 624) | pub(crate) fn resolve_impl_path_impl(
FILE: vine/src/features/import.rs
function parse_use_item (line 25) | pub(crate) fn parse_use_item(&mut self) -> Result<(Span, ItemKind), Diag> {
function parse_use_tree (line 54) | fn parse_use_tree(&mut self, map: &mut BTreeMap<Ident, UseTree>) -> Resu...
function parse_use_tree_alias (line 78) | fn parse_use_tree_alias(&mut self, name: Ident, tree: &mut UseTree) -> R...
function fmt_use_item (line 94) | pub(crate) fn fmt_use_item(&self, u: &UseItem) -> Doc<'src> {
function fmt_use_tree (line 109) | pub(crate) fn fmt_use_tree(&self, name: Ident, tree: &UseTree) -> Doc<'s...
function chart_use (line 140) | pub(crate) fn chart_use(&mut self, parent: DefId, vis: VisId, use_item: ...
function chart_use_tree (line 150) | pub(crate) fn chart_use_tree(
function resolve_import (line 182) | pub(crate) fn resolve_import(&mut self, import_id: ImportId) -> Result<D...
function _resolve_import (line 203) | fn _resolve_import(&mut self, import: ImportDef) -> Result<DefId, ErrorG...
FILE: vine/src/features/index.rs
function fmt_expr_index (line 19) | pub(crate) fn fmt_expr_index(&self, expr: &Expr, index: &Expr) -> Doc<'s...
function resolve_expr_index (line 25) | pub(crate) fn resolve_expr_index(
function distill_expr_value_index (line 46) | pub(crate) fn distill_expr_value_index(
function distill_expr_space_index (line 74) | pub(crate) fn distill_expr_space_index(
function distill_expr_place_index (line 103) | pub(crate) fn distill_expr_place_index(
function distill_expr_poly_index (line 135) | pub(crate) fn distill_expr_poly_index(
FILE: vine/src/features/inline_ivy.rs
function parse_inline_ivy (line 27) | pub(crate) fn parse_inline_ivy(&mut self) -> Result<ExprKind, Diag> {
function fmt_expr_inline_ivy (line 56) | pub(crate) fn fmt_expr_inline_ivy(
function resolve_inline_ivy (line 80) | pub(crate) fn resolve_inline_ivy(
function distill_expr_value_inline_ivy (line 97) | pub(crate) fn distill_expr_value_inline_ivy(
function emit_inline_ivy (line 125) | pub(crate) fn emit_inline_ivy(&mut self, binds: &Vec<(String, Port)>, ou...
FILE: vine/src/features/inverse.rs
function fmt_expr_inverse (line 17) | pub(crate) fn fmt_expr_inverse(&self, expr: &Expr, postfix: bool) -> Doc...
function fmt_pat_inverse (line 25) | pub(crate) fn fmt_pat_inverse(&self, pat: &Pat) -> Doc<'src> {
function fmt_ty_inverse (line 29) | pub(crate) fn fmt_ty_inverse(&self, ty: &Ty) -> Doc<'src> {
function resolve_expr_inverse (line 35) | pub(crate) fn resolve_expr_inverse(&mut self, span: Span, inner: &Expr) ...
function resolve_pat_inverse (line 40) | pub(crate) fn resolve_pat_inverse(&mut self, span: Span, inner: &Pat) ->...
function resolve_pat_sig_inverse (line 45) | pub(crate) fn resolve_pat_sig_inverse(&mut self, inner: &Pat, inference:...
function resolve_ty_inverse (line 50) | pub(crate) fn resolve_ty_inverse(&mut self, inner: &Ty, inference: bool)...
function distill_expr_value_inverse (line 57) | pub(crate) fn distill_expr_value_inverse(&mut self, stage: &mut Stage, i...
function distill_expr_space_inverse (line 61) | pub(crate) fn distill_expr_space_inverse(&mut self, stage: &mut Stage, i...
function distill_expr_place_inverse (line 65) | pub(crate) fn distill_expr_place_inverse(
function distill_expr_poly_inverse (line 74) | pub(crate) fn distill_expr_poly_inverse(&mut self, stage: &mut Stage, in...
function distill_pat_value_inverse (line 83) | pub(crate) fn distill_pat_value_inverse(&mut self, stage: &mut Stage, in...
function distill_pat_space_inverse (line 87) | pub(crate) fn distill_pat_space_inverse(&mut self, stage: &mut Stage, in...
function distill_pat_place_inverse (line 91) | pub(crate) fn distill_pat_place_inverse(
FILE: vine/src/features/labels.rs
function parse_label (line 20) | pub(crate) fn parse_label(&mut self) -> Result<Label, Diag> {
function parse_target (line 24) | pub(crate) fn parse_target(&mut self) -> Result<Target, Diag> {
function parse_stmt_break (line 44) | pub(crate) fn parse_stmt_break(&mut self) -> Result<StmtKind, Diag> {
function parse_stmt_continue (line 51) | pub(crate) fn parse_stmt_continue(&mut self) -> Result<StmtKind, Diag> {
function fmt_label (line 59) | pub(crate) fn fmt_label(&self, label: Label) -> Doc<'src> {
function fmt_target (line 63) | pub(crate) fn fmt_target(&self, target: Target) -> Doc<'src> {
function fmt_stmt_break (line 75) | pub(crate) fn fmt_stmt_break(&self, target: Target, expr: &Option<Expr>)...
function fmt_stmt_continue (line 88) | pub(crate) fn fmt_stmt_continue(&self, target: Target) -> Doc<'src> {
function bind_target (line 94) | pub(crate) fn bind_target<T>(
function resolve_expr_break (line 112) | pub(crate) fn resolve_expr_break(
function resolve_expr_continue (line 144) | pub(crate) fn resolve_expr_continue(
function distill_break (line 159) | pub(crate) fn distill_break(
function distill_continue (line 177) | pub(crate) fn distill_continue(&mut self, stage: &mut Stage, label: Targ...
FILE: vine/src/features/let_.rs
function parse_stmt_let (line 16) | pub(crate) fn parse_stmt_let(&mut self) -> Result<StmtKind, Diag> {
function fmt_stmt_let (line 36) | pub(crate) fn fmt_stmt_let(&self, stmt: &LetStmt) -> Doc<'src> {
function resolve_stmts_let (line 52) | pub(crate) fn resolve_stmts_let(
function distill_let (line 73) | pub(crate) fn distill_let(
FILE: vine/src/features/list.rs
function parse_expr_list (line 22) | pub(crate) fn parse_expr_list(&mut self) -> Result<ExprKind, Diag> {
function fmt_expr_list (line 29) | pub(crate) fn fmt_expr_list(&self, elements: &[Expr]) -> Doc<'src> {
function resolve_expr_list (line 35) | pub(crate) fn resolve_expr_list(
function distill_expr_value_list (line 55) | pub(crate) fn distill_expr_value_list(
function emit_list (line 67) | pub(crate) fn emit_list(&mut self, port: &Port, list: &[Port]) {
function build_list (line 73) | pub(crate) fn build_list<T>(
FILE: vine/src/features/local.rs
function distill_expr_value_local (line 16) | pub(crate) fn distill_expr_value_local(
function distill_expr_space_local (line 26) | pub(crate) fn distill_expr_space_local(
function distill_expr_place_local (line 36) | pub(crate) fn distill_expr_place_local(
function distill_pat_value_local (line 46) | pub(crate) fn distill_pat_value_local(
function distill_pat_space_local (line 57) | pub(crate) fn distill_pat_space_local(
function distill_pat_place_local (line 68) | pub(crate) fn distill_pat_place_local(
function distill_pat_uninit_local (line 80) | pub(crate) fn distill_pat_uninit_local(&mut self, stage: &mut Stage, spa...
function distill_pat_loop_local (line 85) | pub(crate) fn distill_pat_loop_local(&mut self, stage: &mut Stage, local...
type LocalEmissionState (line 91) | pub(crate) struct LocalEmissionState {
method read (line 212) | fn read(&mut self, tree: Tree) {
method read_barrier (line 219) | fn read_barrier(&mut self, tree: Tree) {
method write (line 224) | fn write(&mut self, tree: Tree) {
method barrier_write (line 231) | fn barrier_write(&mut self, tree: Tree) {
method read_write (line 236) | fn read_write(&mut self, a: Tree, b: Tree) {
method barrier (line 241) | fn barrier(&mut self) {
function local (line 99) | fn local(&mut self, local: Local) -> &mut LocalEmissionState {
function emit_invocation (line 108) | pub(crate) fn emit_invocation(&mut self, local: &Local, invocation: &Inv...
function emit_compound_invocation (line 135) | pub(crate) fn emit_compound_invocation(
function finish_local (line 158) | pub(crate) fn finish_local(&mut self, local: &VirLocal, mut state: Local...
FILE: vine/src/features/loop_.rs
function parse_expr_loop (line 21) | pub(crate) fn parse_expr_loop(&mut self) -> Result<ExprKind, Diag> {
function fmt_expr_loop (line 31) | pub(crate) fn fmt_expr_loop(&self, label: Label, ty: &Option<Ty>, body: ...
function resolve_expr_loop (line 43) | pub(crate) fn resolve_expr_loop(
function distill_loop (line 63) | pub(crate) fn distill_loop(
FILE: vine/src/features/match_.rs
function parse_expr_match (line 22) | pub(crate) fn parse_expr_match(&mut self) -> Result<ExprKind, Diag> {
function fmt_expr_match (line 36) | pub(crate) fn fmt_expr_match(
function resolve_match (line 57) | pub(crate) fn resolve_match(
function distill_match (line 78) | pub(crate) fn distill_match(
FILE: vine/src/features/method.rs
function fmt_expr_method (line 15) | pub(crate) fn fmt_expr_method(
function resolve_method (line 33) | pub(crate) fn resolve_method(
function find_method (line 95) | fn find_method(
FILE: vine/src/features/mod_.rs
function parse_mod_item (line 18) | pub(crate) fn parse_mod_item(&mut self) -> Result<(Span, ItemKind), Diag> {
function fmt_mod_item (line 41) | pub(crate) fn fmt_mod_item(&self, m: &ModItem) -> Doc<'src> {
function chart_mod (line 59) | pub(crate) fn chart_mod(
FILE: vine/src/features/numeric.rs
function parse_expr_numeric (line 19) | pub(crate) fn parse_expr_numeric(&mut self) -> Result<ExprKind, Diag> {
function fmt_expr_nat (line 43) | pub(crate) fn fmt_expr_nat(&self, lit_span: Span, ty: &Ty) -> Doc<'src> {
function fmt_expr_float (line 47) | pub(crate) fn fmt_expr_float(&self, lit_span: Span, ty: &Ty) -> Doc<'src> {
function resolve_expr_n32 (line 53) | pub(crate) fn resolve_expr_n32(&mut self, span: Span, n: u32) -> Result<...
function resolve_expr_f32 (line 58) | pub(crate) fn resolve_expr_f32(&mut self, span: Span, n: f32) -> Result<...
function resolve_expr_float (line 63) | pub(crate) fn resolve_expr_float(
function resolve_expr_nat (line 85) | pub(crate) fn resolve_expr_nat(&mut self, span: Span, n: &Nat, ty: &Ty) ...
function distill_expr_value_n32 (line 105) | pub(crate) fn distill_expr_value_n32(&mut self, ty: Type, n: u32) -> Port {
function distill_expr_value_f32 (line 109) | pub(crate) fn distill_expr_value_f32(&mut self, ty: Type, f: f32) -> Port {
function distill_expr_value_f64 (line 113) | pub(crate) fn distill_expr_value_f64(&mut self, ty: Type, f: f64) -> Port {
function distill_expr_value_nat (line 117) | pub(crate) fn distill_expr_value_nat(&mut self, ty: Type, n: &Nat) -> Po...
function emit_nat (line 123) | pub(crate) fn emit_nat(&mut self, n: &Nat) -> Tree {
FILE: vine/src/features/ops.rs
function fmt_expr_assign (line 15) | pub(crate) fn fmt_expr_assign(&self, inverted: bool, space: &Expr, value...
function fmt_expr_sign (line 23) | pub(crate) fn fmt_expr_sign(&self, sign: Sign, expr: &Expr) -> Doc<'src> {
function fmt_expr_binary_op (line 33) | pub(crate) fn fmt_expr_binary_op(&self, op: &BinaryOp, lhs: &Expr, rhs: ...
function fmt_expr_binary_op_assign (line 37) | pub(crate) fn fmt_expr_binary_op_assign(
function fmt_expr_comparison_op (line 46) | pub(crate) fn fmt_expr_comparison_op(
function resolve_expr_assign (line 58) | pub(crate) fn resolve_expr_assign(
function resolve_expr_sign (line 70) | pub(crate) fn resolve_expr_sign(
function resolve_expr_binary_op (line 85) | pub(crate) fn resolve_expr_binary_op(
function resolve_expr_binary_op_assign (line 100) | pub(crate) fn resolve_expr_binary_op_assign(
function resolve_expr_comparison_op (line 114) | pub(crate) fn resolve_expr_comparison_op(
function distill_expr_nil_assign (line 151) | pub(crate) fn distill_expr_nil_assign(
function distill_expr_nil_call_assign (line 169) | pub(crate) fn distill_expr_nil_call_assign(
function distill_expr_value_call_compare (line 182) | pub(crate) fn distill_expr_value_call_compare(
FILE: vine/src/features/path.rs
function parse_path (line 23) | pub(crate) fn parse_path(&mut self) -> Result<Path, Diag> {
function parse_expr_path (line 32) | pub(crate) fn parse_expr_path(&mut self) -> Result<ExprKind, Diag> {
function parse_pat_path (line 38) | pub(crate) fn parse_pat_path(&mut self) -> Result<PatKind, Diag> {
function fmt_path (line 46) | pub(crate) fn fmt_path(&self, path: &Path) -> Doc<'src> {
function fmt_expr_path (line 65) | pub(crate) fn fmt_expr_path(&self, path: &Path, args: &Option<Vec<Expr>>...
function fmt_pat_path (line 74) | pub(crate) fn fmt_pat_path(&self, path: &Path, args: &Option<Vec<Pat>>) ...
function resolve_path (line 85) | pub fn resolve_path<T>(
function resolve_path_impl (line 113) | pub fn resolve_path_impl(
function _resolve_path (line 144) | fn _resolve_path(&mut self, source: DefId, path: &Path) -> Result<DefId,...
function resolve_absolute (line 158) | pub(crate) fn resolve_absolute(&mut self, span: Span, ident: Ident) -> R...
function resolve_local (line 165) | pub(crate) fn resolve_local(
function resolve_segment (line 190) | pub(crate) fn resolve_segment(
function _resolve_segment (line 201) | fn _resolve_segment(
function resolve_expr_path (line 235) | pub(crate) fn resolve_expr_path(
function resolve_pat_path (line 276) | pub(crate) fn resolve_pat_path(
function resolve_pat_sig_path (line 306) | pub(crate) fn resolve_pat_sig_path(&mut self, span: Span, path: &Path, i...
function resolve_ty_path (line 322) | pub(crate) fn resolve_ty_path(&mut self, path: &Path, inference: bool) -...
function resolve_impl_path (line 341) | pub(crate) fn resolve_impl_path(&mut self, path: &Path, ty: &ImplType) -...
FILE: vine/src/features/place.rs
function fmt_expr_place (line 13) | pub(crate) fn fmt_expr_place(&self, v: &Expr, s: &Expr) -> Doc<'src> {
function resolve_expr_place (line 19) | pub(crate) fn resolve_expr_place(
function distill_expr_place_place (line 41) | pub(crate) fn distill_expr_place_place(
FILE: vine/src/features/range.rs
function _parse_expr_range (line 19) | pub(crate) fn _parse_expr_range(&mut self, left_bound: Option<Expr>) -> ...
function fmt_expr_range_inclusive (line 33) | pub(crate) fn fmt_expr_range_inclusive(&self, start: &Option<Expr>, end:...
function fmt_expr_range_exclusive (line 43) | pub(crate) fn fmt_expr_range_exclusive(
function resolve_expr_range (line 61) | pub(crate) fn resolve_expr_range(
function resolve_range_bound (line 86) | fn resolve_range_bound(
FILE: vine/src/features/reference.rs
function parse_expr_ref (line 24) | pub(crate) fn parse_expr_ref(&mut self, span: usize) -> Result<ExprKind,...
function parse_expr_deref (line 35) | pub(crate) fn parse_expr_deref(&mut self, span: usize) -> Result<ExprKin...
function parse_pat_ref (line 46) | pub(crate) fn parse_pat_ref(&mut self, span: usize) -> Result<PatKind, D...
function parse_pat_deref (line 57) | pub(crate) fn parse_pat_deref(&mut self, span: usize) -> Result<PatKind,...
function parse_ty_ref (line 68) | pub(crate) fn parse_ty_ref(&mut self, span: usize) -> Result<TyKind, Dia...
function fmt_expr_ref (line 81) | pub(crate) fn fmt_expr_ref(&self, expr: &Expr, postfix: bool) -> Doc<'sr...
function fmt_expr_deref (line 89) | pub(crate) fn fmt_expr_deref(&self, expr: &Expr, postfix: bool) -> Doc<'...
function fmt_pat_ref (line 97) | pub(crate) fn fmt_pat_ref(&self, pat: &Pat) -> Doc<'src> {
function fmt_pat_deref (line 101) | pub(crate) fn fmt_pat_deref(&self, pat: &Pat) -> Doc<'src> {
function fmt_ty_ref (line 105) | pub(crate) fn fmt_ty_ref(&self, ty: &Ty) -> Doc<'src> {
function resolve_expr_ref (line 111) | pub(crate) fn resolve_expr_ref(&mut self, span: Span, inner: &Expr) -> R...
function resolve_expr_deref (line 116) | pub(crate) fn resolve_expr_deref(&mut self, span: Span, inner: &Expr) ->...
function resolve_pat_ref (line 123) | pub(crate) fn resolve_pat_ref(&mut self, span: Span, inner: &Pat) -> Res...
function resolve_pat_sig_ref (line 128) | pub(crate) fn resolve_pat_sig_ref(&mut self, inner: &Pat, inference: boo...
function resolve_pat_deref (line 133) | pub(crate) fn resolve_pat_deref(&mut self, span: Span, inner: &Pat) -> R...
function resolve_ty_ref (line 140) | pub(crate) fn resolve_ty_ref(&mut self, inner: &Ty, inference: bool) -> ...
function distill_expr_value_ref (line 147) | pub(crate) fn distill_expr_value_ref(
function distill_expr_place_deref (line 158) | pub(crate) fn distill_expr_place_deref(
function distill_pat_value_ref (line 172) | pub(crate) fn distill_pat_value_ref(
function distill_pat_place_ref (line 185) | pub(crate) fn distill_pat_place_ref(
function distill_pat_place_deref (line 201) | pub(crate) fn distill_pat_place_deref(
function match_ref (line 217) | pub(crate) fn match_ref<'p>(
function emit_ref (line 239) | pub(crate) fn emit_ref(&mut self, reference: &Port, value: &Port, space:...
FILE: vine/src/features/string.rs
function parse_string (line 24) | pub(crate) fn parse_string(&mut self) -> Result<String, Diag> {
function parse_expr_string (line 36) | pub(crate) fn parse_expr_string(&mut self) -> Result<ExprKind, Diag> {
function parse_string_segment (line 54) | fn parse_string_segment(&mut self) -> Result<(StringSegment, bool), Diag> {
function parse_expr_char (line 73) | pub(crate) fn parse_expr_char(&mut self) -> Result<ExprKind, Diag> {
type StrToken (line 102) | pub enum StrToken {
type StrLexer (line 111) | pub struct StrLexer<'src> {
function new (line 117) | fn new(file: FileId, src: &'src str) -> Self {
function span (line 121) | fn span(&self) -> Span {
function invalid_escape (line 126) | fn invalid_escape(&self) -> Diag {
type Token (line 132) | type Token = StrToken;
type Error (line 133) | type Error = Diag;
function state (line 135) | fn state(&self) -> &LexerState<'src> {
function state_mut (line 139) | fn state_mut(&mut self) -> &mut LexerState<'src> {
function lex (line 143) | fn lex(&mut self) -> Result<Self::Token, Self::Error> {
function fmt_expr_string (line 194) | pub(crate) fn fmt_expr_string(
function resolve_expr_char (line 210) | pub(crate) fn resolve_expr_char(&mut self, span: Span, char: char) -> Re...
function resolve_expr_string (line 215) | pub(crate) fn resolve_expr_string(
function distill_expr_value_char (line 246) | pub(crate) fn distill_expr_value_char(&mut self, ty: Type, char: char) -...
function distill_expr_value_string (line 250) | pub(crate) fn distill_expr_value_string(
function emit_string (line 267) | pub(crate) fn emit_string(&mut self, port: &Port, init: &str, rest: &Vec...
FILE: vine/src/features/struct_.rs
function parse_struct_item (line 34) | pub(crate) fn parse_struct_item(&mut self) -> Result<(Span, ItemKind), D...
function fmt_struct_item (line 54) | pub(crate) fn fmt_struct_item(&self, s: &StructItem) -> Doc<'src> {
function fmt_expr_unwrap (line 87) | pub(crate) fn fmt_expr_unwrap(&self, expr: &Expr) -> Doc<'src> {
function chart_struct (line 93) | pub(crate) fn chart_struct(
function resolve_struct_sig (line 124) | pub(crate) fn resolve_struct_sig(&mut self, struct_id: StructId) {
function resolve_expr_path_struct (line 150) | pub(crate) fn resolve_expr_path_struct(
function resolve_pat_path_struct (line 180) | pub(crate) fn resolve_pat_path_struct(
function resolve_pat_sig_path_struct (line 205) | pub(crate) fn resolve_pat_sig_path_struct(&mut self, path: &Path, struct...
function resolve_ty_path_struct (line 211) | pub(crate) fn resolve_ty_path_struct(
function resolve_expr_unwrap (line 222) | pub(crate) fn resolve_expr_unwrap(&mut self, span: Span, inner: &Expr) -...
function get_struct_data (line 237) | pub(crate) fn get_struct_data(
function distill_expr_value_rewrap (line 258) | pub(crate) fn distill_expr_value_rewrap(
function distill_expr_space_rewrap (line 271) | pub(crate) fn distill_expr_space_rewrap(
function distill_expr_place_rewrap (line 284) | pub(crate) fn distill_expr_place_rewrap(
function distill_expr_poly_rewrap (line 299) | pub(crate) fn distill_expr_poly_rewrap(
function distill_pat_value_struct (line 328) | pub(crate) fn distill_pat_value_struct(
function distill_pat_space_struct (line 341) | pub(crate) fn distill_pat_space_struct(
function distill_pat_place_struct (line 354) | pub(crate) fn distill_pat_place_struct(
function match_struct (line 371) | pub(crate) fn match_struct<'p>(
function find_auto_impls_struct (line 396) | pub(crate) fn find_auto_impls_struct(
FILE: vine/src/features/trait_.rs
function parse_trait_item (line 26) | pub(crate) fn parse_trait_item(&mut self) -> Result<(Span, ItemKind), Di...
function fmt_trait_item (line 43) | pub(crate) fn fmt_trait_item(&self, t: &TraitItem) -> Doc<'src> {
function chart_trait (line 57) | pub(crate) fn chart_trait(
function chart_trait_fn (line 139) | fn chart_trait_fn(
function chart_trait_const (line 172) | fn chart_trait_const(
function resolve_trait_sig (line 205) | pub(crate) fn resolve_trait_sig(&mut self, trait_id: TraitId) {
FILE: vine/src/features/try_.rs
function fmt_expr_try (line 15) | pub(crate) fn fmt_expr_try(&self, expr: &Expr) -> Doc<'src> {
function resolve_expr_try (line 21) | pub(crate) fn resolve_expr_try(&mut self, span: Span, result: &Expr) -> ...
function distill_try (line 50) | pub(crate) fn distill_try(
FILE: vine/src/features/type_.rs
function parse_type_item (line 26) | pub(crate) fn parse_type_item(&mut self) -> Result<(Span, ItemKind), Dia...
function fmt_type_item (line 38) | pub(crate) fn fmt_type_item(&self, t: &TypeItem) -> Doc<'src> {
function chart_type (line 53) | pub(crate) fn chart_type(
function resolve_type_alias (line 81) | pub(crate) fn resolve_type_alias(&mut self, alias_id: TypeAliasId) {
function resolve_opaque_type (line 117) | pub(crate) fn resolve_opaque_type(&mut self, opaque_id: OpaqueTypeId) {
function resolve_ty_path_alias (line 124) | pub(crate) fn resolve_ty_path_alias(
function resolve_ty_path_opaque (line 150) | pub(crate) fn resolve_ty_path_opaque(
function find_auto_impls_opaque (line 163) | pub(crate) fn find_auto_impls_opaque(
FILE: vine/src/features/union.rs
function chart_union (line 27) | pub(crate) fn chart_union(
function resolve_union_sig (line 60) | pub(crate) fn resolve_union_sig(&mut self, union_id: UnionId) {
function resolve_expr_path_union (line 85) | pub(crate) fn resolve_expr_path_union(
function resolve_pat_path_union (line 119) | pub(crate) fn resolve_pat_path_union(
function resolve_pat_sig_path_union (line 148) | pub(crate) fn resolve_pat_sig_path_union(&mut self, path: &Path, union_i...
function resolve_ty_path_union (line 153) | pub(crate) fn resolve_ty_path_union(
function distill_pat_value_union (line 166) | pub(crate) fn distill_pat_value_union(
function distill_pat_space_union (line 179) | pub(crate) fn distill_pat_space_union(
function distill_pat_place_union (line 192) | pub(crate) fn distill_pat_place_union(
function emit_union (line 209) | pub(crate) fn emit_union(
FILE: vine/src/features/when.rs
function parse_expr_when (line 21) | pub(crate) fn parse_expr_when(&mut self) -> Result<ExprKind, Diag> {
function fmt_expr_when (line 39) | pub(crate) fn fmt_expr_when(
function resolve_expr_when (line 64) | pub(crate) fn resolve_expr_when(
function distill_when (line 108) | pub(crate) fn distill_when(
FILE: vine/src/features/while_.rs
function parse_expr_while (line 21) | pub(crate) fn parse_expr_while(&mut self) -> Result<ExprKind, Diag> {
function fmt_expr_while (line 33) | pub(crate) fn fmt_expr_while(
function resolve_expr_while (line 58) | pub(crate) fn resolve_expr_while(
function distill_while (line 91) | pub(crate) fn distill_while(
FILE: vine/src/structures/annotations.rs
type Annotations (line 6) | pub struct Annotations {
method record_reference (line 19) | pub fn record_reference(&mut self, ref_span: Span, def_span: Span) {
method record_signature (line 24) | pub fn record_signature(&mut self, span: Span, signature: String) {
method record_docs (line 28) | pub fn record_docs(&mut self, span: Span, doc: Vec<String>) {
type Hover (line 13) | pub struct Hover {
FILE: vine/src/structures/ast.rs
type Item (line 19) | pub struct Item {
type ItemKind (line 30) | pub enum ItemKind {
type FnItem (line 45) | pub struct FnItem {
type ConstItem (line 55) | pub struct ConstItem {
type TypeItem (line 63) | pub struct TypeItem {
type StructItem (line 70) | pub struct StructItem {
type EnumItem (line 80) | pub struct EnumItem {
type Variant (line 89) | pub struct Variant {
type ModItem (line 95) | pub struct ModItem {
type ModKind (line 102) | pub enum ModKind {
type TraitItem (line 109) | pub struct TraitItem {
type ImplItem (line 118) | pub struct ImplItem {
type ImplItemKind (line 127) | pub enum ImplItemKind {
type UseItem (line 133) | pub struct UseItem {
type UseTree (line 139) | pub struct UseTree {
method empty (line 148) | pub fn empty(span: Span) -> Self {
method prune (line 158) | pub fn prune(&mut self) -> bool {
type Vis (line 165) | pub enum Vis {
type Attr (line 172) | pub struct Attr {
type AttrKind (line 179) | pub enum AttrKind {
type GenericParams (line 191) | pub type GenericParams = Generics<TypeParam, ImplParam>;
type GenericArgs (line 192) | pub type GenericArgs = Generics<Ty, Impl>;
type Generics (line 195) | pub struct Generics<T, I> {
function empty (line 203) | pub fn empty(span: Span) -> Self {
type TypeParam (line 209) | pub struct TypeParam {
type ImplParam (line 216) | pub struct ImplParam {
type Flex (line 223) | pub enum Flex {
method fork (line 231) | pub fn fork(self) -> bool {
method drop (line 235) | pub fn drop(self) -> bool {
method sigil (line 239) | pub fn sigil(self) -> &'static str {
type Block (line 250) | pub struct Block {
method from (line 664) | fn from(err: ErrorGuaranteed) -> Self {
type Stmt (line 256) | pub struct Stmt {
method from (line 658) | fn from(err: ErrorGuaranteed) -> Self {
type StmtKind (line 262) | pub enum StmtKind {
type LetStmt (line 275) | pub struct LetStmt {
type LetStmtKind (line 281) | pub enum LetStmtKind {
type AssertStmt (line 288) | pub struct AssertStmt {
type LetFnStmt (line 294) | pub struct LetFnStmt {
type Expr (line 304) | pub struct Expr {
method from (line 652) | fn from(err: ErrorGuaranteed) -> Self {
type ExprKind (line 310) | pub enum ExprKind {
method from (line 634) | fn from(err: ErrorGuaranteed) -> Self {
type Label (line 361) | pub struct Label(pub Option<Ident>);
type Target (line 364) | pub enum Target {
type StringSegment (line 375) | pub struct StringSegment {
type Sign (line 381) | pub enum Sign {
type Pat (line 387) | pub struct Pat {
type PatKind (line 393) | pub enum PatKind {
method from (line 640) | fn from(err: ErrorGuaranteed) -> Self {
type Path (line 408) | pub struct Path {
method as_ident (line 416) | pub fn as_ident(&self) -> Option<Ident> {
method from (line 607) | fn from(key: Key) -> Self {
type Ty (line 427) | pub struct Ty {
type TyKind (line 433) | pub enum TyKind {
method from (line 646) | fn from(err: ErrorGuaranteed) -> Self {
type Impl (line 449) | pub struct Impl {
type ImplKind (line 455) | pub enum ImplKind {
type Trait (line 464) | pub struct Trait {
type TraitKind (line 470) | pub enum TraitKind {
type BinaryOp (line 477) | pub enum BinaryOp {
method as_str (line 499) | pub fn as_str(&self) -> &'static str {
method fmt (line 493) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type LogicalOp (line 518) | pub enum LogicalOp {
type ComparisonOp (line 525) | pub enum ComparisonOp {
method as_str (line 535) | pub fn as_str(&self) -> &'static str {
type Ident (line 548) | pub struct Ident(pub String);
method new (line 551) | pub fn new(str: &str) -> Option<Ident> {
type Key (line 557) | pub struct Key {
method fmt (line 563) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type Span (line 569) | pub struct Span {
constant NONE (line 588) | pub const NONE: Span = Span { file: FileId(usize::MAX), start: 0, end:...
method cmp (line 576) | fn cmp(&self, other: &Self) -> Ordering {
method partial_cmp (line 582) | fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
method fmt (line 592) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method fmt (line 613) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
FILE: vine/src/structures/ast/visit.rs
type VisitMut (line 35) | pub trait VisitMut<'a> {
method visit_expr (line 36) | fn visit_expr(&mut self, expr: &'a mut Expr) {
method visit_pat (line 40) | fn visit_pat(&mut self, pat: &'a mut Pat) {
method visit_type (line 44) | fn visit_type(&mut self, ty: &'a mut Ty) {
method visit_impl (line 48) | fn visit_impl(&mut self, ty: &'a mut Impl) {
method visit_trait (line 52) | fn visit_trait(&mut self, trait_: &'a mut Trait) {
method visit_stmt (line 56) | fn visit_stmt(&mut self, stmt: &'a mut Stmt) {
method visit_item (line 60) | fn visit_item(&mut self, item: &'a mut Item) {
method visit_block (line 64) | fn visit_block(&mut self, block: &'a mut Block) {
method visit_generic_params (line 68) | fn visit_generic_params(&mut self, generics: &'a mut GenericParams) {
method visit_generic_args (line 72) | fn visit_generic_args(&mut self, generics: &'a mut GenericArgs) {
method _visit_expr (line 76) | fn _visit_expr(&mut self, expr: &'a mut Expr) {
method _visit_pat (line 212) | fn _visit_pat(&mut self, pat: &'a mut Pat) {
method _visit_type (line 241) | fn _visit_type(&mut self, ty: &'a mut Ty) {
method _visit_impl (line 266) | fn _visit_impl(&mut self, impl_: &'a mut Impl) {
method _visit_trait (line 274) | fn _visit_trait(&mut self, trait_: &'a mut Trait) {
method _visit_stmt (line 286) | fn _visit_stmt(&mut self, stmt: &'a mut Stmt) {
method _visit_item (line 318) | fn _visit_item(&mut self, item: &'a mut Item) {
method _visit_block (line 363) | fn _visit_block(&mut self, block: &'a mut Block) {
method _visit_generic_params (line 369) | fn _visit_generic_params(&mut self, generics: &'a mut GenericParams) {
method _visit_generic_args (line 373) | fn _visit_generic_args(&mut self, generics: &'a mut GenericArgs) {
method visit (line 378) | fn visit(&mut self, visitee: impl Visitee<'a>) {
type Visitee (line 383) | pub trait Visitee<'t>: Sized {
method visit (line 384) | fn visit(self, visitor: &mut (impl VisitMut<'t> + ?Sized));
function visit (line 388) | fn visit(self, visitor: &mut (impl VisitMut<'t> + ?Sized)) {
function visit (line 394) | fn visit(self, visitor: &mut (impl VisitMut<'t> + ?Sized)) {
function visit (line 400) | fn visit(self, visitor: &mut (impl VisitMut<'t> + ?Sized)) {
function visit (line 406) | fn visit(self, visitor: &mut (impl VisitMut<'t> + ?Sized)) {
function visit (line 412) | fn visit(self, visitor: &mut (impl VisitMut<'t> + ?Sized)) {
function visit (line 418) | fn visit(self, visitor: &mut (impl VisitMut<'t> + ?Sized)) {
function visit (line 424) | fn visit(self, visitor: &mut (impl VisitMut<'t> + ?Sized)) {
function visit (line 430) | fn visit(self, visitor: &mut (impl VisitMut<'t> + ?Sized)) {
function visit (line 436) | fn visit(self, visitor: &mut (impl VisitMut<'t> + ?Sized)) {
function visit (line 442) | fn visit(self, visitor: &mut (impl VisitMut<'t> + ?Sized)) {
method visit (line 448) | fn visit(self, visitor: &mut (impl VisitMut<'t> + ?Sized)) {
FILE: vine/src/structures/chart.rs
type Chart (line 12) | pub struct Chart {
method visible (line 329) | pub fn visible(&self, vis: VisId, from: DefId) -> bool {
method fn_is_method (line 338) | pub fn fn_is_method(&self, fn_id: FnId) -> bool {
method fn_generics (line 345) | pub fn fn_generics(&self, fn_id: FnId) -> GenericsId {
method fn_is_unsafe (line 352) | pub fn fn_is_unsafe(&self, fn_id: FnId) -> bool {
method const_generics (line 359) | pub fn const_generics(&self, const_id: ConstId) -> GenericsId {
method const_is_unsafe (line 366) | pub fn const_is_unsafe(&self, const_id: ConstId) -> bool {
method fn_span (line 373) | pub fn fn_span(&self, fn_id: FnId) -> Span {
type Def (line 34) | pub struct Def {
method fn_id (line 382) | pub fn fn_id(&self) -> Option<Binding<FnId>> {
type VisId (line 55) | pub enum VisId {
type Binding (line 61) | pub struct Binding<T> {
type MemberKind (line 68) | pub enum MemberKind {
type DefValueKind (line 74) | pub enum DefValueKind {
type ConstId (line 83) | pub enum ConstId {
type FnId (line 89) | pub enum FnId {
type DefTypeKind (line 95) | pub enum DefTypeKind {
type DefPatternKind (line 104) | pub enum DefPatternKind {
type DefTraitKind (line 111) | pub enum DefTraitKind {
type DefImplKind (line 116) | pub enum DefImplKind {
type ImportDef (line 122) | pub struct ImportDef {
type ImportParent (line 130) | pub enum ImportParent {
type GenericsDef (line 138) | pub struct GenericsDef {
type GenericsKind (line 147) | pub enum GenericsKind {
type DeriveKind (line 155) | pub enum DeriveKind {
type ConcreteConstDef (line 163) | pub struct ConcreteConstDef {
type ConcreteFnDef (line 176) | pub struct ConcreteFnDef {
type OpaqueTypeDef (line 191) | pub struct OpaqueTypeDef {
type TypeAliasDef (line 200) | pub struct TypeAliasDef {
type StructDef (line 210) | pub struct StructDef {
type EnumDef (line 222) | pub struct EnumDef {
type EnumVariant (line 232) | pub struct EnumVariant {
type UnionDef (line 241) | pub struct UnionDef {
type UnionVariant (line 251) | pub struct UnionVariant {
type TraitDef (line 260) | pub struct TraitDef {
type TraitConst (line 273) | pub struct TraitConst {
type TraitFn (line 283) | pub struct TraitFn {
type ImplDef (line 295) | pub struct ImplDef {
type ImplDefKind (line 309) | pub enum ImplDefKind {
type ImplSubitem (line 316) | pub struct ImplSubitem {
type ImplSubitemKind (line 323) | pub enum ImplSubitemKind {
constant NONE (line 393) | pub const NONE: Self = Self(usize::MAX);
constant NONE (line 397) | pub const NONE: Self = Self(0);
FILE: vine/src/structures/checkpoint.rs
type Checkpoint (line 24) | pub struct Checkpoint {
method checkpoint (line 46) | pub fn checkpoint(&self) -> Checkpoint {
method revert (line 69) | pub fn revert(&mut self, checkpoint: &Checkpoint) {
method revert (line 101) | fn revert(&mut self, checkpoint: &Checkpoint) {
method revert (line 147) | fn revert(&mut self, checkpoint: &Checkpoint) {
method after (line 173) | fn after(&self, checkpoint: &Checkpoint) -> bool {
method after (line 187) | fn after(&self, checkpoint: &Checkpoint) -> bool {
method after (line 199) | fn after(&self, checkpoint: &Checkpoint) -> bool {
method after (line 209) | fn after(&self, checkpoint: &Checkpoint) -> bool {
method after (line 217) | fn after(&self, checkpoint: &Checkpoint) -> bool {
method revert (line 225) | fn revert(&mut self, checkpoint: &Checkpoint) {
method revert (line 324) | fn revert(&mut self, checkpoint: &Checkpoint) {
method revert (line 358) | fn revert(&mut self, checkpoint: &Checkpoint) {
method revert (line 369) | fn revert(&mut self, checkpoint: &Checkpoint) {
method revert (line 386) | fn revert(&mut self, checkpoint: &Checkpoint) {
function revert_idx (line 395) | fn revert_idx<T: Idx>(option: &mut Option<T>, checkpoint: T) {
function revert_fn (line 401) | fn revert_fn(builtin: &mut Option<FnId>, checkpoint: &Checkpoint) {
method revert (line 410) | pub(crate) fn revert(&mut self, checkpoint: &Checkpoint) {
FILE: vine/src/structures/diag.rs
type Diags (line 15) | pub struct Diags {
method error (line 21) | pub(crate) fn error(&mut self, diag: Diag) -> ErrorGuaranteed {
method warn (line 26) | pub(crate) fn warn(&mut self, diag: Diag) {
method bail (line 30) | pub fn bail(&mut self) -> Result<(), ErrorGuaranteed> {
method revert (line 34) | pub(crate) fn revert(&mut self, checkpoint: &Checkpoint) {
function plural (line 342) | fn plural<'a>(n: usize, plural: &'a str, singular: &'a str) -> &'a str {
method show_span (line 347) | pub fn show_span(&self, span: Span) -> Option<String> {
type ErrorGuaranteed (line 353) | pub struct ErrorGuaranteed(());
method new_unchecked (line 356) | pub const fn new_unchecked() -> Self {
method from (line 407) | fn from(value: &ErrorGuaranteed) -> Self {
method from (line 362) | fn from(value: ErrorGuaranteed) -> Self {
type FileInfo (line 367) | pub struct FileInfo {
method new (line 374) | pub fn new(name: String, src: String) -> Self {
method get_pos (line 381) | pub fn get_pos(&self, byte: usize) -> Pos<'_> {
type Pos (line 388) | pub struct Pos<'f> {
method fmt (line 395) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
function from (line 401) | fn from(value: ErrorGuaranteed) -> Self {
FILE: vine/src/structures/resolutions.rs
type Resolutions (line 18) | pub struct Resolutions {
type ResolvedImpl (line 27) | pub struct ResolvedImpl {
type Become (line 34) | pub enum Become {
type ResolvedImplKind (line 41) | pub enum ResolvedImplKind {
type Fragment (line 51) | pub struct Fragment {
type Rels (line 63) | pub struct Rels {
method fork_rel (line 75) | pub fn fork_rel(&mut self, chart: &Chart, impl_: TirImpl) -> FnRelId {
method drop_rel (line 80) | pub fn drop_rel(&mut self, chart: &Chart, impl_: TirImpl) -> FnRelId {
type FnRel (line 69) | pub enum FnRel {
FILE: vine/src/structures/signatures.rs
type Signatures (line 17) | pub struct Signatures {
method const_sig (line 105) | pub fn const_sig(&self, const_id: ConstId) -> &TypeCtx<ConstSig> {
method fn_sig (line 112) | pub fn fn_sig(&self, fn_id: FnId) -> &TypeCtx<FnSig> {
method get_member (line 119) | pub fn get_member(&self, member: MemberKind) -> Option<DefId> {
type ImportState (line 33) | pub enum ImportState {
type TypeAliasState (line 40) | pub enum TypeAliasState {
type TypeParams (line 48) | pub struct TypeParams {
type ImplParams (line 54) | pub struct ImplParams {
type ConstSig (line 60) | pub struct ConstSig {
type FnSig (line 65) | pub struct FnSig {
type TypeAliasSig (line 72) | pub struct TypeAliasSig {
type StructSig (line 77) | pub struct StructSig {
type EnumSig (line 82) | pub struct EnumSig {
type UnionSig (line 88) | pub struct UnionSig {
type TraitSig (line 94) | pub struct TraitSig {
type ImplSig (line 100) | pub struct ImplSig {
method transfer (line 131) | fn transfer(&self, t: &mut TypeTransfer<'_>) -> Self {
method transfer (line 137) | fn transfer(&self, t: &mut TypeTransfer<'_>) -> Self {
method transfer (line 147) | fn transfer(&self, t: &mut TypeTransfer<'_>) -> Self {
method transfer (line 153) | fn transfer(&self, t: &mut TypeTransfer<'_>) -> Self {
method transfer (line 159) | fn transfer(&self, t: &mut TypeTransfer<'_>) -> Self {
method transfer (line 168) | fn transfer(&self, t: &mut TypeTransfer<'_>) -> Self {
FILE: vine/src/structures/specializations.rs
type Specializations (line 17) | pub struct Specializations {
method spec (line 24) | pub fn spec(&self, spec_id: SpecId) -> &Spec {
type Spec (line 31) | pub struct Spec {
type SpecKind (line 40) | pub enum SpecKind {
type SpecRels (line 46) | pub struct SpecRels {
type ImplTree (line 52) | pub enum ImplTree {
FILE: vine/src/structures/template.rs
type Template (line 13) | pub struct Template {
method instantiate (line 18) | pub fn instantiate(&self, nets: &mut Nets, specs: &Specializations, sp...
type TemplateStage (line 28) | pub struct TemplateStage {
method instantiate (line 41) | pub fn instantiate(&self, specs: &Specializations, spec: &Spec) -> Net {
type TemplateStageRels (line 34) | pub struct TemplateStageRels {
function global_name (line 58) | pub fn global_name(spec: &Spec, stage_id: StageId) -> String {
FILE: vine/src/structures/tir.rs
type Tir (line 21) | pub struct Tir {
type TirClosure (line 31) | pub struct TirClosure {
type TirLocal (line 40) | pub struct TirLocal {
type TirExpr (line 46) | pub struct TirExpr {
method new (line 195) | pub fn new(span: Span, ty: Type, kind: TirExprKind) -> Self {
type TirExprKind (line 53) | pub enum TirExprKind {
type TirExprLetKind (line 145) | pub enum TirExprLetKind {
type TirPat (line 152) | pub struct TirPat {
method new (line 201) | pub fn new(span: Span, ty: Type, kind: TirPatKind) -> Self {
type TirPatKind (line 159) | pub enum TirPatKind {
type TirImpl (line 183) | pub enum TirImpl {
FILE: vine/src/structures/types.rs
type Type (line 24) | pub struct Type(usize);
method new (line 29) | fn new(inv: Inverted, idx: TypeIdx) -> Type {
method inv (line 33) | fn inv(self) -> Inverted {
method idx (line 37) | fn idx(self) -> TypeIdx {
method invert_if (line 41) | pub fn invert_if(self, inv: Inverted) -> Type {
method inverse (line 45) | pub fn inverse(self) -> Type {
method from (line 54) | fn from(value: TypeIdx) -> Self {
constant INV_BIT (line 27) | const INV_BIT: usize = isize::MIN as usize;
type Inverted (line 51) | pub struct Inverted(pub bool);
type Output (line 60) | type Output = Self;
method bitxor (line 61) | fn bitxor(self, rhs: Self) -> Self::Output {
method bitxor_assign (line 67) | fn bitxor_assign(&mut self, rhs: Self) {
method fmt (line 73) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type TypeKind (line 82) | pub enum TypeKind {
method map (line 730) | fn map(&self, mut f: impl FnMut(Type) -> Type) -> Self {
method children (line 760) | fn children(&self) -> impl Iterator<Item = Type> + '_ {
method self_dual (line 783) | fn self_dual(&self) -> bool {
type TypeNode (line 102) | enum TypeNode {
type TypeState (line 115) | enum TypeState {
method kind (line 128) | fn kind(&self) -> Option<(Inverted, &TypeKind)> {
method take_kind (line 135) | fn take_kind(&mut self) -> Option<(Inverted, TypeKind)> {
method default (line 147) | fn default() -> Self {
type ImplType (line 153) | pub enum ImplType {
method approx_eq (line 797) | pub fn approx_eq(&self, other: &ImplType) -> bool {
method map (line 803) | fn map(&self, f: impl FnMut(Type) -> Type) -> Self {
type Types (line 159) | pub struct Types {
method new (line 167) | pub fn new(&mut self, kind: TypeKind) -> Type {
method new_var (line 171) | pub fn new_var(&mut self, span: Span) -> Type {
method new_struct (line 175) | pub fn new_struct(&mut self, chart: &Chart, struct_id: StructId, type_...
method new_union (line 179) | pub fn new_union(&mut self, chart: &Chart, union_id: UnionId, type_par...
method new_vars (line 183) | pub fn new_vars(&mut self, span: Span, len: usize) -> Vec<Type> {
method error (line 187) | pub fn error(&mut self, err: ErrorGuaranteed) -> Type {
method nil (line 193) | pub fn nil(&mut self) -> Type {
method unify (line 202) | pub fn unify(&mut self, a: Type, b: Type) -> UnifyResult {
method unify_types (line 300) | pub fn unify_types(&mut self, a: &[Type], b: &[Type], inv: Inverted) -...
method unify_objects (line 308) | pub fn unify_objects(
method unify_impl_type (line 319) | pub fn unify_impl_type(&mut self, a: &ImplType, b: &ImplType) -> Unify...
method unify_fn_sig (line 329) | pub fn unify_fn_sig(&mut self, a: &FnSig, b: &FnSig) -> UnifyResult {
method occurs (line 335) | fn occurs(&self, var: Type, ty: Type) -> bool {
method find (line 344) | fn find(&self, ty: Type) -> Type {
method find_mut (line 354) | fn find_mut(&mut self, ty: Type) -> Type {
method kind (line 367) | pub(crate) fn kind(&self, ty: Type) -> Option<(Inverted, &TypeKind)> {
method self_inverse (line 373) | pub(crate) fn self_inverse(&self, ty: Type) -> bool {
method _self_inverse (line 377) | pub(crate) fn _self_inverse(
method force_kind (line 393) | pub(crate) fn force_kind(&mut self, diags: &mut Diags, ty: Type) -> (I...
method show (line 408) | pub fn show(&self, chart: &Chart, ty: Type) -> String {
method _show (line 414) | fn _show(&self, chart: &Chart, mut ty: Type, str: &mut String) {
method _show_params (line 524) | fn _show_params(&self, chart: &Chart, params: &[Type], inv: Inverted, ...
method _show_comma_separated (line 532) | fn _show_comma_separated(&self, chart: &Chart, tys: &[Type], inv: Inve...
method show_impl_type (line 543) | pub fn show_impl_type(&self, chart: &Chart, ty: &ImplType) -> String {
method show_fn_sig (line 555) | pub fn show_fn_sig(&self, chart: &Chart, sig: &FnSig) -> String {
method _show_fn_sig (line 561) | fn _show_fn_sig(&self, chart: &Chart, sig: &FnSig, str: &mut String) {
method import (line 584) | pub fn import<T: TransferTypes>(&mut self, source: &TypeCtx<T>, params...
method import_with (line 588) | pub fn import_with<T, U>(
method export (line 600) | pub fn export<T>(&self, f: impl FnOnce(&mut TypeTransfer<'_>) -> T) ->...
method get_mod (line 610) | pub fn get_mod(&self, chart: &Chart, ty: Type) -> Result<Option<DefId>...
method reset (line 631) | pub fn reset(&mut self) {
method finish_inference (line 637) | pub fn finish_inference(&mut self) {
type UnifyResult (line 650) | pub enum UnifyResult {
method and (line 659) | pub fn and(self, other: Self) -> Self {
method all (line 667) | pub fn all(i: impl IntoIterator<Item = Self>) -> Self {
method from_bool (line 671) | pub fn from_bool(b: bool) -> Self {
method is_success (line 675) | pub fn is_success(self) -> bool {
method is_failure (line 679) | pub fn is_failure(self) -> bool {
type TypeTransfer (line 684) | pub struct TypeTransfer<'ctx> {
function transfer (line 692) | pub fn transfer<T: TransferTypes>(&mut self, t: &T) -> T {
function transfer_type (line 696) | fn transfer_type(&mut self, ty: Type) -> Type {
function transfer_impl_type (line 724) | fn transfer_impl_type(&mut self, ty: &ImplType) -> ImplType {
type TypeCtx (line 812) | pub struct TypeCtx<T> {
type TransferTypes (line 817) | pub trait TransferTypes {
method transfer (line 818) | fn transfer(&self, t: &mut TypeTransfer<'_>) -> Self;
method transfer (line 822) | fn transfer(&self, t: &mut TypeTransfer<'_>) -> Self {
method transfer (line 828) | fn transfer(&self, t: &mut TypeTransfer<'_>) -> Self {
method transfer (line 834) | fn transfer(&self, t: &mut TypeTransfer<'_>) -> Self {
method transfer (line 840) | fn transfer(&self, t: &mut TypeTransfer<'_>) -> Self {
method transfer (line 846) | fn transfer(&self, t: &mut TypeTransfer<'_>) -> Self {
FILE: vine/src/structures/vir.rs
constant NONE (line 33) | pub const NONE: LayerId = LayerId(usize::MAX);
type Vir (line 37) | pub struct Vir {
type Layer (line 48) | pub struct Layer {
type Interface (line 55) | pub struct Interface {
method new (line 67) | pub fn new(id: InterfaceId, layer: LayerId, kind: InterfaceKind) -> Se...
method inline (line 79) | pub fn inline(&self) -> bool {
type InterfaceKind (line 87) | pub enum InterfaceKind {
method stages (line 96) | pub fn stages(&self) -> impl Iterator<Item = StageId> + use<> {
type Stage (line 111) | pub struct Stage {
method new_wire (line 257) | pub fn new_wire(&mut self, span: Span, ty: Type) -> Wire {
method local_read_to (line 265) | pub fn local_read_to(&mut self, local: Local, span: Span, to: Port) {
method local_write_to (line 269) | pub fn local_write_to(&mut self, local: Local, span: Span, to: Port) {
method local_read_barrier_to (line 273) | pub fn local_read_barrier_to(&mut self, local: Local, span: Span, to: ...
method local_barrier_write_to (line 277) | pub fn local_barrier_write_to(&mut self, local: Local, span: Span, to:...
method local_read_write_to (line 281) | pub fn local_read_write_to(&mut self, local: Local, span: Span, o: Por...
method local_read (line 285) | pub fn local_read(&mut self, local: Local, span: Span, ty: Type) -> Po...
method local_write (line 291) | pub fn local_write(&mut self, local: Local, span: Span, ty: Type) -> P...
method local_read_barrier (line 297) | pub fn local_read_barrier(&mut self, local: Local, span: Span, ty: Typ...
method local_barrier_write (line 303) | pub fn local_barrier_write(&mut self, local: Local, span: Span, ty: Ty...
method local_read_write (line 309) | pub fn local_read_write(&mut self, local: Local, span: Span, ty: Type)...
method local_barrier (line 316) | pub fn local_barrier(&mut self, local: Local, span: Span) {
method ext_fn (line 320) | pub fn ext_fn(
method ref_place (line 334) | pub fn ref_place(&mut self, span: Span, ty: Type, (value, space): (Por...
type Header (line 124) | pub enum Header {
method ports (line 156) | pub fn ports(&self) -> impl Iterator<Item = &Port> {
type Step (line 135) | pub enum Step {
method ports (line 169) | pub fn ports(&self) -> impl Iterator<Item = &Port> {
type Invocation (line 193) | pub enum Invocation {
method ports (line 203) | fn ports(&self) -> impl Iterator<Item = &Port> {
type Port (line 217) | pub struct Port {
method error (line 223) | pub fn error(ty: Type, err: ErrorGuaranteed) -> Port {
type PortKind (line 229) | pub enum PortKind {
type Transfer (line 240) | pub struct Transfer {
method unconditional (line 246) | pub fn unconditional(interface: InterfaceId) -> Transfer {
type Wire (line 251) | pub struct Wire {
type VirLocal (line 342) | pub struct VirLocal {
method new (line 352) | pub fn new(
FILE: vine/src/tools/doc.rs
function document (line 14) | pub fn document(compiler: &Compiler, path: &Path) -> Result<(), ()> {
type Documenter (line 22) | struct Documenter<'a> {
type Tree (line 26) | struct Tree<'a> {
function build_tree (line 38) | fn build_tree(&self, id: DefId) -> Tree<'a> {
function output_tree (line 105) | fn output_tree(&self, tree: &Tree, path: &Path, parent: Option<(&str, &s...
function source_link (line 156) | fn source_link(&self, tree: &Tree) -> String {
function write_header (line 168) | fn write_header(&self, tree: &Tree, str: &mut String) {
FILE: vine/src/tools/fmt.rs
type Formatter (line 16) | pub struct Formatter<'src> {
function fmt (line 21) | pub fn fmt(src: &str) -> Result<String, Diag> {
function fmt_item (line 38) | pub(crate) fn fmt_item(&self, item: &Item) -> Doc<'src> {
function fmt_vis (line 63) | pub(crate) fn fmt_vis(&self, vis: &Vis) -> Doc<'src> {
function _fmt_vis (line 67) | pub(crate) fn _fmt_vis(&self, vis: &Vis) -> Doc<'src> {
function fmt_block_like (line 75) | pub(crate) fn fmt_block_like(
function line_break_separated (line 94) | fn line_break_separated(
function get_line_break (line 115) | fn get_line_break(
function fmt_stmt (line 148) | pub(crate) fn fmt_stmt(&self, stmt: &Stmt) -> Doc<'src> {
function fmt_flex (line 163) | pub(crate) fn fmt_flex(&self, flex: Flex) -> Doc<'src> {
function fmt_impl (line 167) | pub(crate) fn fmt_impl(&self, impl_: &Impl) -> Doc<'src> {
function fmt_trait (line 177) | pub(crate) fn fmt_trait(&self, trait_: &Trait) -> Doc<'src> {
function fmt_expr (line 193) | pub(crate) fn fmt_expr(&self, expr: &Expr) -> Doc<'src> {
function fmt_pat (line 249) | pub(crate) fn fmt_pat(&self, pat: &Pat) -> Doc<'src> {
function fmt_ty (line 265) | pub(crate) fn fmt_ty(&self, ty: &Ty) -> Doc<'src> {
function fmt_arrow_ty (line 282) | pub(crate) fn fmt_arrow_ty(&self, ty: &Option<Ty>) -> Doc<'src> {
function fmt_verbatim (line 289) | pub(crate) fn fmt_verbatim(&self, span: Span) -> Doc<'src> {
FILE: vine/src/tools/fmt/doc.rs
constant MAX_WIDTH (line 5) | const MAX_WIDTH: usize = 100;
type Doc (line 8) | pub struct Doc<'src> {
function Doc (line 14) | pub fn Doc<'src>(doc: impl Into<Doc<'src>>) -> Doc<'src> {
constant EMPTY (line 19) | pub const EMPTY: Self = Doc { measure: Measure::EMPTY, kind: DocKind::St...
constant LINE (line 20) | pub const LINE: Self = Doc { measure: Measure::LINE, kind: DocKind::Line };
function collect (line 22) | fn collect(docs: impl IntoIterator<Item = Self>) -> Box<[Self]> {
function concat (line 26) | pub fn concat(docs: impl IntoIterator<Item = Self>) -> Self {
function concat_vec (line 30) | pub fn concat_vec(docs: Vec<Self>) -> Self {
function indent (line 34) | pub fn indent(docs: impl IntoIterator<Item = Self>) -> Self {
function indent_vec (line 38) | pub fn indent_vec(docs: Vec<Self>) -> Self {
function group (line 42) | pub fn group(docs: impl IntoIterator<Item = Self>) -> Self {
function lazy_group (line 46) | pub fn lazy_group(docs: impl IntoIterator<Item = Self>) -> Self {
function bare_group (line 50) | pub fn bare_group(docs: impl IntoIterator<Item = Self>) -> Self {
function interleave (line 54) | pub fn interleave(docs: impl IntoIterator<Item = Self>, sep: Self) -> Se...
function if_single (line 58) | pub fn if_single(str: &'src str) -> Self {
function if_multi (line 62) | pub fn if_multi(str: &'src str) -> Self {
function soft_line (line 66) | pub fn soft_line(str: &'src str) -> Self {
function paren (line 70) | pub fn paren(doc: Self) -> Self {
function delimited (line 74) | pub fn delimited(
function paren_comma (line 101) | pub fn paren_comma(docs: impl ExactSizeIterator<Item = Self>) -> Self {
function tuple (line 105) | pub fn tuple(docs: impl ExactSizeIterator<Item = Self>) -> Self {
function bracket_comma (line 109) | pub fn bracket_comma(docs: impl ExactSizeIterator<Item = Self>) -> Self {
function brace_comma (line 113) | pub fn brace_comma(docs: impl ExactSizeIterator<Item = Self>) -> Self {
function brace_comma_space (line 117) | pub fn brace_comma_space(docs: impl ExactSizeIterator<Item = Self>) -> S...
function brace_comma_multiline (line 121) | pub fn brace_comma_multiline(docs: impl ExactSizeIterator<Item = Self>) ...
function brace_multiline (line 125) | pub fn brace_multiline(docs: impl Iterator<Item = Self>) -> Self {
function from (line 136) | fn from(kind: DocKind<'src>) -> Self {
function from (line 142) | fn from(str: &'src str) -> Self {
function from (line 148) | fn from(str: String) -> Self {
function from (line 154) | fn from(value: Ident) -> Self {
type DocKind (line 160) | enum DocKind<'src> {
function measure (line 175) | fn measure(&self) -> Measure {
type Writer (line 194) | pub struct Writer {
method write_doc (line 201) | pub fn write_doc(&mut self, doc: &Doc, multi: bool) {
method write_all_maybe_indented (line 248) | fn write_all_maybe_indented(&mut self, docs: &[Doc], multi: bool) {
method write_all_indented (line 256) | fn write_all_indented(&mut self, docs: &[Doc], multi: bool) {
method write_all (line 262) | fn write_all(&mut self, docs: &[Doc], multi: bool) {
method indent (line 268) | fn indent(&mut self) {
method outdent (line 273) | fn outdent(&mut self) {
method newline (line 278) | pub(crate) fn newline(&mut self) {
method write_str (line 283) | fn write_str(&mut self, str: &str) {
method remaining (line 296) | fn remaining(&self) -> usize {
type Measure (line 302) | struct Measure {
constant EMPTY (line 309) | const EMPTY: Self = Measure { multi: false, width: 0, leading: 0 };
constant LINE (line 310) | const LINE: Self = Measure { multi: true, width: 0, leading: 0 };
method string (line 312) | fn string(str: &str) -> Self {
type Output (line 334) | type Output = Measure;
method add (line 336) | fn add(self, rhs: Measure) -> Self::Output {
FILE: vine/src/tools/repl.rs
type Repl (line 33) | pub struct Repl<'ctx, 'ivm, 'ext, 'comp> {
type ScopeEntry (line 44) | struct ScopeEntry<'ivm> {
function new (line 53) | pub fn new(
function exec (line 86) | pub fn exec(&mut self, input: &str) -> Result<(), ErrorGuaranteed> {
function run (line 113) | pub fn run(
function parse_input (line 312) | fn parse_input(&mut self, line: &str) -> Result<(Span, ReplCommand), Dia...
function print_scope (line 321) | pub fn print_scope(&mut self) {
FILE: vine/src/tools/repl/command.rs
type ReplCommand (line 11) | pub enum ReplCommand {
type ReplOptions (line 19) | pub struct ReplOptions {
method default (line 24) | fn default() -> Self {
type ReplOption (line 29) | pub enum ReplOption {
constant HELP (line 33) | pub const HELP: &str = "
function parse_repl_command (line 43) | pub(super) fn parse_repl_command(&mut self) -> Result<ReplCommand, Diag> {
function parse_bool (line 76) | fn parse_bool(&mut self) -> Result<bool, Diag> {
FILE: vine/src/tools/repl/show.rs
function show (line 23) | pub fn show(&mut self, ty: Type, port: &mut Port<'ivm>) -> String {
function _show (line 29) | fn _show(&mut self, ty: Type, port: Port<'ivm>) -> (Port<'ivm>, Option<S...
function read_string (line 99) | fn read_string(&mut self, tree: &Tree) -> Option<String> {
Copy disabled (too large)
Download .json
Condensed preview — 746 files, each showing path, character count, and a content snippet. Download the .json file for the full structured content (10,031K chars).
[
{
"path": ".gitattributes",
"chars": 29,
"preview": "\n*.vi linguist-language=rust\n"
},
{
"path": ".github/workflows/change-base.yml",
"chars": 402,
"preview": "name: Change Base\n\non:\n pull_request:\n types: [opened]\n branches: [main]\n\njobs:\n change-base:\n runs-on: ubunt"
},
{
"path": ".github/workflows/checks.yml",
"chars": 227,
"preview": "name: Checks\n\non:\n pull_request:\n merge_group:\n push:\n branches:\n - main\n\njobs:\n checks:\n runs-on: self-h"
},
{
"path": ".github/workflows/docs.yml",
"chars": 806,
"preview": "name: Docs\n\non:\n push:\n\npermissions:\n contents: read\n pages: write\n id-token: write\n\njobs:\n build:\n runs-on: sel"
},
{
"path": ".github/workflows/integration.yml",
"chars": 2182,
"preview": "name: Integration\n\non:\n workflow_dispatch:\n push:\n branches:\n - dev\n\njobs:\n integration-test:\n runs-on: se"
},
{
"path": ".github/workflows/issues.yml",
"chars": 847,
"preview": "name: Close linked issues on PR merge\n\non:\n pull_request:\n types: [closed]\n branches: [main, dev]\n\njobs:\n close-"
},
{
"path": ".gitignore",
"chars": 97,
"preview": ".DS_Store\ntarget\ntests/snaps/**/compiled.iv\ntests/snaps/**/timing.txt\n\n# Nix build outputs\nresult"
},
{
"path": ".vscode/settings.json",
"chars": 785,
"preview": "{\n \"[json]\": {\n \"editor.defaultFormatter\": \"dprint.dprint\"\n },\n \"[jsonc]\": {\n \"editor.defaultFormatter\": \"dprin"
},
{
"path": "Cargo.toml",
"chars": 82,
"preview": "[workspace]\nresolver = \"2\"\nmembers = [\"cli\", \"ivm\", \"ivy\", \"lsp\", \"util\", \"vine\"]\n"
},
{
"path": "LICENSE-APACHE",
"chars": 9723,
"preview": " Apache License\n Version 2.0, January 2004\n http"
},
{
"path": "LICENSE-MIT",
"chars": 1023,
"preview": "Permission is hereby granted, free of charge, to any\nperson obtaining a copy of this software and associated\ndocumentati"
},
{
"path": "README.md",
"chars": 789,
"preview": "<h1 align=\"center\">\n <img src=\"./docs/img/favicon-1024.png\" width=\"128\" align=\"center\">\n <p>The Vine Programming Langu"
},
{
"path": "cli/Cargo.toml",
"chars": 573,
"preview": "[package]\nname = \"vine-cli\"\nversion = \"0.0.0\"\nedition = \"2024\"\n\n[dependencies]\nanyhow = \"1.0.87\"\nclap = { version = \"4.5"
},
{
"path": "cli/cli.nix",
"chars": 1799,
"preview": "{\n pkgs,\n craneLib,\n}:\nlet\n self.internal.ivyConfig = {\n pname = \"ivy\";\n version = \"0.0.0\";\n src = pkgs.lib."
},
{
"path": "cli/src/bin/ivy.rs",
"chars": 99,
"preview": "use anyhow::Result;\nuse vine_cli::IvyCommand;\n\nfn main() -> Result<()> {\n IvyCommand::execute()\n}\n"
},
{
"path": "cli/src/bin/vine.rs",
"chars": 101,
"preview": "use anyhow::Result;\nuse vine_cli::VineCommand;\n\nfn main() -> Result<()> {\n VineCommand::execute()\n}\n"
},
{
"path": "cli/src/common.rs",
"chars": 4563,
"preview": "use std::{\n io::{self, Read, Write},\n process::exit,\n sync::{Mutex, MutexGuard},\n};\n\nuse clap::Args;\n\nuse ivm::{\n IV"
},
{
"path": "cli/src/ivy_cli.rs",
"chars": 3103,
"preview": "use std::{fs, io, path::PathBuf};\n\nuse anyhow::Result;\nuse clap::{Args, CommandFactory};\nuse clap_complete::generate;\nus"
},
{
"path": "cli/src/lib.rs",
"chars": 150,
"preview": "mod common;\nmod ivy_cli;\n#[cfg(feature = \"vine\")]\nmod vine_cli;\n\npub use common::*;\npub use ivy_cli::*;\n#[cfg(feature = "
},
{
"path": "cli/src/vine_cli.rs",
"chars": 16479,
"preview": "use std::{\n collections::HashMap,\n env,\n ffi::OsStr,\n fmt, fs,\n io::{self, IsTerminal, Read, Write, stderr, stdin, "
},
{
"path": "cspell.json",
"chars": 1302,
"preview": "{\n \"$schema\": \"https://raw.githubusercontent.com/streetsidesoftware/cspell/main/cspell.schema.json\",\n \"version\": \"0.2\""
},
{
"path": "docs/.gitignore",
"chars": 25,
"preview": "/deps\n/root\n*.pdf\n*.html\n"
},
{
"path": "docs/compiler/architecture.typ",
"chars": 2710,
"preview": "#import \"/lib.typ\": *\n\n= Architecture\n\nThe *cli* is the entrypoint to the compiler,\n and collects all of the compilatio"
},
{
"path": "docs/compiler/compiler.typ",
"chars": 172,
"preview": "#import \"/lib.typ\": *\n\n= The Vine Compiler\n\nAn introduction to the internals of the Vine compiler. Here be dragons!\n\n#le"
},
{
"path": "docs/compiler/sfg.typ",
"chars": 2758,
"preview": "#import \"/lib.typ\": *\n\n= Stacked Flow Graphs <sfg>\n\nMany compilers use Control Flow Graphs (CFGs) to represent the contr"
},
{
"path": "docs/docs.nix",
"chars": 2248,
"preview": "{\n typix,\n hyptyp,\n typsitter,\n flake-utils,\n pkgs,\n system,\n grammars,\n cli,\n}:\nlet\n self.packages.typsitter-l"
},
{
"path": "docs/docs.typ",
"chars": 812,
"preview": "#import \"lib.typ\": *\n\n= The Vine Programming Language\n\nVine is an experimental new programming language based on interac"
},
{
"path": "docs/features/conditions.typ",
"chars": 2764,
"preview": "#import \"/lib.typ\": *\n\n= Conditions <conditions>\n\nConditions are expressions which evaluate to booleans (the #ty[`Bool`]"
},
{
"path": "docs/features/control_flow/blocks.typ",
"chars": 628,
"preview": "#import \"/lib.typ\": *\n\n= Blocks\n\nControl flow is structured with _blocks_,\n delimited with curly braces #vi[`{}`],\n wh"
},
{
"path": "docs/features/control_flow/conditionals.typ",
"chars": 1991,
"preview": "#import \"/lib.typ\": *\n\n= Conditionals\n\n== `if`\n\nAn #vi[`if`] branches on a @conditions[condition]\n and executes its blo"
},
{
"path": "docs/features/control_flow/control_flow.typ",
"chars": 127,
"preview": "#import \"/lib.typ\": *\n\n= Control Flow <control-flow>\n\n#let children = (\n \"blocks.typ\",\n \"conditionals.typ\",\n \"loops.t"
},
{
"path": "docs/features/control_flow/loops.typ",
"chars": 1360,
"preview": "#import \"/lib.typ\": *\n\n= Loops\n\n== `while`\n\nThe #vi[`while`] loop repeatedly executes its block\n as long as its @condit"
},
{
"path": "docs/features/features.typ",
"chars": 347,
"preview": "#import \"/lib.typ\": *\n\n= Vine Language Features\n\n#let children = (\n \"usual.typ\",\n \"root.typ\",\n \"modules.typ\",\n \"vari"
},
{
"path": "docs/features/inverse.typ",
"chars": 7163,
"preview": "#import \"/lib.typ\": *\n\n= The Inverse <inverse>\n\n*Note*:\nThis page is *bad* and _should feel bad_.\nIt is left here for po"
},
{
"path": "docs/features/io.typ",
"chars": 1016,
"preview": "#import \"/lib.typ\": *\n\n= IO <io>\n\nAll IO in Vine is done by calling functions on an IO handle,\n passed in to #fn[`main`"
},
{
"path": "docs/features/methods.typ",
"chars": 1775,
"preview": "#import \"/lib.typ\": *\n\n= Methods\n\nAny function can be marked as a _method_ by writing a `.` before the name in the defin"
},
{
"path": "docs/features/modules.typ",
"chars": 2080,
"preview": "#import \"/lib.typ\": *\n\n= Modules\n\nVine programs are comrpised of _modules_.\nEvery Vine file is a module.\nModules consist"
},
{
"path": "docs/features/patterns.typ",
"chars": 2601,
"preview": "#import \"/lib.typ\": *\n\n= Patterns <patterns>\n\n_Patterns_ appear in:\n\n- #vi[`let`] bindings (#vi[`let pattern = ...`])\n- "
},
{
"path": "docs/features/references.typ",
"chars": 2450,
"preview": "#import \"/lib.typ\": *\n\n= References <references>\n\nA _reference_ is a value that represents a place.\n\nReferences can be c"
},
{
"path": "docs/features/root.typ",
"chars": 732,
"preview": "#import \"/lib.typ\": *\n\n= The Root Library\n\n@root[`#root`] is Vine's standard library.\nIt provides:\n- types fundamental t"
},
{
"path": "docs/features/traits/fork_drop.typ",
"chars": 3329,
"preview": "#import \"/lib.typ\": *\n\n= Fork and Drop <flex>\n\nEvery type in Vine has a _flexibility_,\n which is the combination of whe"
},
{
"path": "docs/features/traits/intro.typ",
"chars": 3650,
"preview": "#import \"/lib.typ\": *\n\n= Using Traits\n\nA _trait_ defines functionality that can be shared between types.\nFor example, on"
},
{
"path": "docs/features/traits/standard.typ",
"chars": 3019,
"preview": "#import \"/lib.typ\": *\n\n= Standard Traits\n\nThe standard library defines several traits, many of which control the behavio"
},
{
"path": "docs/features/traits/traits.typ",
"chars": 181,
"preview": "#import \"/lib.typ\": *\n\n= Traits <traits>\n\nA _trait_ defines functionality that can be shared between types.\n\n#let childr"
},
{
"path": "docs/features/types/composite.typ",
"chars": 616,
"preview": "#import \"/lib.typ\": *\n\n= Composite Types <composite>\n\nA composite type is a fixed-sized, heterogenous collection of valu"
},
{
"path": "docs/features/types/enums.typ",
"chars": 1604,
"preview": "#import \"/lib.typ\": *\n\n= Enums <enums>\n\nAn enum is a type with a fixed set of _variants_.\nAn enum value is one of those "
},
{
"path": "docs/features/types/primitives.typ",
"chars": 3057,
"preview": "#import \"/lib.typ\": *\n\n= Primitive Types <primitive-types>\n\n(Note: there is no implicit casting between numeric types.\n "
},
{
"path": "docs/features/types/standard.typ",
"chars": 3003,
"preview": "#import \"/lib.typ\": *\n\n= Standard Types <standard-types>\n\nThe standard library defines various commonly-used types.\n\n(In"
},
{
"path": "docs/features/types/structs.typ",
"chars": 2711,
"preview": "#import \"/lib.typ\": *\n\n= Structs <structs>\n\nA _struct_ creates a new type that wraps some _content_.\n\n```vi\n// define a "
},
{
"path": "docs/features/types/types.typ",
"chars": 556,
"preview": "#import \"/lib.typ\": *\n\n= Types\n\nVine is statically typed.\nEvery expression has a type, like #ty[`Bool`] or #ty[`List[N32"
},
{
"path": "docs/features/usual.typ",
"chars": 866,
"preview": "#import \"/lib.typ\": *\n\n= The Usual <usual>\n\nVine has the usual complement of standard programming language features, inc"
},
{
"path": "docs/features/values_spaces_places.typ",
"chars": 4040,
"preview": "#import \"/lib.typ\": *\n\n= Values, Spaces, and Places\n\nThe result of an expression in Vine has one of three _forms_:\n a v"
},
{
"path": "docs/features/variables.typ",
"chars": 1471,
"preview": "#import \"/lib.typ\": *\n\n= Variables <variables>\n\nThe primary way to declare new variables is with the #vi[`let`] statemen"
},
{
"path": "docs/img.typ",
"chars": 2451,
"preview": "\n#import \"/lib.typ\": hyptyp\n#import hyptyp: t\n#import t: link, meta\n\n#let resources = for img in (\n \"/logo.svg\",\n \"/lo"
},
{
"path": "docs/ivy_ivm/extrinsics.typ",
"chars": 3375,
"preview": "#import \"/lib.typ\": *\n\n= Extrinsics <extrinsics>\n\nExtrinsics are how programs running in the IVM interact with the outsi"
},
{
"path": "docs/ivy_ivm/interaction_system.typ",
"chars": 3029,
"preview": "#import \"/lib.typ\": *\n\n= Ivy's Interaction System <interaction-system>\n\nIvy's interaction system is based on the symmetr"
},
{
"path": "docs/ivy_ivm/ivm.typ",
"chars": 1809,
"preview": "#import \"/lib.typ\": *\n\n= IVM Overview <ivm>\n\nIVM is a performant interaction combinator runtime.\nIt is used to run Ivy p"
},
{
"path": "docs/ivy_ivm/ivy.typ",
"chars": 1147,
"preview": "#import \"/lib.typ\": *\n\n= Ivy Overview <ivy>\n\nAn Ivy program consists of a series of named global nets.\nThe name of a glo"
},
{
"path": "docs/ivy_ivm/ivy_ivm.typ",
"chars": 320,
"preview": "#import \"/lib.typ\": *\n\n= Ivy and the IVM\n\nVine compiles to @ivy[Ivy], a low-level interaction-combinator programming lan"
},
{
"path": "docs/ivy_ivm/statistics.typ",
"chars": 3125,
"preview": "#import \"/lib.typ\": *\n\n= Statistics <statistics>\n\nThe IVM collects various statistics during execution.\nThe Vine and Ivy"
},
{
"path": "docs/lib.typ",
"chars": 2788,
"preview": "\n#import \"deps/hyptyp/hyptyp.typ\"\n#import \"deps/typsitter/typsitter.typ\"\n\n#import hyptyp: t\n\n#let theme(theme, fg, fgl, "
},
{
"path": "docs/main.typ",
"chars": 2169,
"preview": "#import \"/lib.typ\": *\n#import hyptyp: t\n\n#import \"img.typ\"\n\n#include \"deps/typsitter-langs/langs.typ\"\n\n#show: typsitter."
},
{
"path": "docs/root.css",
"chars": 796,
"preview": "\n#sidebar, .children {\n li::before {\n content: \"·\";\n font-weight: 900;\n font-family: \"Atkinson Hyperlegible Mo"
},
{
"path": "docs/starting/hello_world.typ",
"chars": 1858,
"preview": "#import \"/lib.typ\": *\n\n= `Hello, world!` <hello-world>\n\nLet's run our first Vine program!\n\n```vi\n// hello_world.vi\n\npub "
},
{
"path": "docs/starting/installation.typ",
"chars": 402,
"preview": "#import \"/lib.typ\": *\n\n= Installation <installation>\n\nMake sure you have #link(\"https://www.rust-lang.org/tools/install\""
},
{
"path": "docs/starting/starting.typ",
"chars": 236,
"preview": "#import \"/lib.typ\": *\n\n= Getting Started\n\nLet's get started!\nOnce you've @installation[installed Vine],\n we'll take a l"
},
{
"path": "docs/theme.css",
"chars": 804,
"preview": "\n:root {\n --theme: light-dark(#169646, #46c676);\n\n --white: #d6dde0;\n --dawn: #bdc3c7;\n --dusk: #252830;\n --black: "
},
{
"path": "docs/tooling/cli.typ",
"chars": 1288,
"preview": "#import \"/lib.typ\": *\n\n= Using the CLI\n\n== Building <building>\n\nYou can build a Vine program with `vine build`,\n which "
},
{
"path": "docs/tooling/debug.typ",
"chars": 1301,
"preview": "#import \"/lib.typ\": *\n\n= Debug Mode <debug>\n\nVine programs can be run in debug mode by passing the `--debug` flag.\n\nIn d"
},
{
"path": "docs/tooling/editor.typ",
"chars": 1634,
"preview": "#import \"/lib.typ\": *\n\n= Editor Configuration <editor>\n\n== VSCode\n\nInstall the #link(\"https://marketplace.visualstudio.c"
},
{
"path": "docs/tooling/repl.typ",
"chars": 1650,
"preview": "#import \"/lib.typ\": *\n\n= The REPL <repl>\n\nVine has a\n #link(\"https://en.wikipedia.org/wiki/Read-eval-print_loop\")[REPL]"
},
{
"path": "docs/tooling/tooling.typ",
"chars": 112,
"preview": "#import \"/lib.typ\": *\n\n= Tooling\n\n#let children = (\n \"editor.typ\",\n \"cli.typ\",\n \"repl.typ\",\n \"debug.typ\",\n)\n"
},
{
"path": "dprint.json",
"chars": 1127,
"preview": "{\n \"indentWidth\": 2,\n \"lineWidth\": 100,\n \"markdown\": {\n \"textWrap\": \"always\",\n \"lineWidth\": 80,\n \"emphasisKi"
},
{
"path": "flake.nix",
"chars": 2384,
"preview": "{\n inputs = {\n nixpkgs.url = \"github:NixOS/nixpkgs/nixos-unstable\";\n flake-utils.url = \"github:numtide/flake-util"
},
{
"path": "ivm/Cargo.toml",
"chars": 114,
"preview": "[package]\nname = \"ivm\"\nversion = \"0.0.0\"\nedition = \"2024\"\n\n[dependencies]\n\n[lints.clippy]\nabsolute_paths = \"warn\"\n"
},
{
"path": "ivm/src/addr.rs",
"chars": 1588,
"preview": "use core::{\n fmt::{self, Debug},\n ptr,\n};\n\nuse crate::{\n global::Global,\n word::{AtomicWord, Word},\n};\n\n/// The addr"
},
{
"path": "ivm/src/allocator.rs",
"chars": 3379,
"preview": "use crate::{\n addr::Addr,\n heap::{Heap, Node},\n ivm::IVM,\n port::{Port, Tag},\n wire::Wire,\n word::Word,\n};\n\npub(cr"
},
{
"path": "ivm/src/ext.rs",
"chars": 11653,
"preview": "//! External values and functions, whose semantics live outside interaction\n//! combinators.\n\n#![allow(nonstandard_style"
},
{
"path": "ivm/src/flags.rs",
"chars": 408,
"preview": "/// Error flags set during interactions.\n#[derive(Clone, Copy, Default, PartialEq, Eq)]\npub struct Flags {\n /// A non-c"
},
{
"path": "ivm/src/global.rs",
"chars": 2064,
"preview": "use crate::instruction::Instructions;\n\n/// A global definition of a net.\n#[derive(Debug, Default)]\npub struct Global<'iv"
},
{
"path": "ivm/src/heap.rs",
"chars": 1487,
"preview": "use core::{alloc::Layout, mem::transmute, ptr, slice::SliceIndex};\nuse std::alloc::alloc;\n\nuse crate::word::AtomicWord;\n"
},
{
"path": "ivm/src/instruction.rs",
"chars": 5795,
"preview": "use core::fmt::{self, Debug};\n\nuse crate::{\n ext::OpaqueExtFn,\n ivm::IVM,\n port::{Port, Tag},\n};\n\n/// A list of instr"
},
{
"path": "ivm/src/interact.rs",
"chars": 6774,
"preview": "use crate::{\n ivm::IVM,\n port::{Port, PortRef, Tag},\n wire::Wire,\n};\n\nmacro_rules! sym {\n ($a: pat, $b: pat) => {\n "
},
{
"path": "ivm/src/ivm.rs",
"chars": 2723,
"preview": "use core::mem;\nuse std::time::Instant;\n\nuse crate::{\n allocator::Allocator,\n ext::{Extrinsics, OpaqueExtFn},\n flags::"
},
{
"path": "ivm/src/lib.rs",
"chars": 518,
"preview": "//! The Interaction Virtual Machine, an interaction combinator runtime.\n//!\n//! The [`IVM`] struct is the root of the AP"
},
{
"path": "ivm/src/parallel.rs",
"chars": 5829,
"preview": "use core::{mem, ptr};\nuse std::{\n sync::{Condvar, Mutex, OnceLock},\n thread::{self, Thread},\n time::Instant,\n};\n\nuse "
},
{
"path": "ivm/src/port.rs",
"chars": 8493,
"preview": "use crate::{\n addr::Addr,\n ext::{ExtFn, ExtVal},\n global::Global,\n wire::{Wire, WireRef},\n word::{NonZeroWord, Word"
},
{
"path": "ivm/src/stats.rs",
"chars": 6458,
"preview": "use core::{\n fmt::{self, Debug, Display, Write},\n ops::AddAssign,\n str,\n time::Duration,\n};\n\n/// Statistics about th"
},
{
"path": "ivm/src/wire.rs",
"chars": 2214,
"preview": "use core::{\n fmt::{self, Debug},\n marker::PhantomData,\n mem::transmute,\n ops::Deref,\n ptr,\n};\n\nuse crate::{\n addr:"
},
{
"path": "ivm/src/word.rs",
"chars": 3786,
"preview": "//! Zero-cost wrappers around `u64` and derivatives that properly preserve\n//! [provenance] information for miri.\n//!\n//"
},
{
"path": "ivy/Cargo.toml",
"chars": 220,
"preview": "[package]\nname = \"ivy\"\nversion = \"0.0.0\"\nedition = \"2024\"\n\n[dependencies]\nindexmap = \"2.2.6\"\nunicode-id-start = \"1.4.0\"\n"
},
{
"path": "ivy/examples/cat.iv",
"chars": 263,
"preview": "\n:: {\n x(io0 io2)\n io0 = @io_read_char(dup(char0 char1) io1)\n char0 = @n32_eq(0xffffffff is_eof)\n is_eof = ?(::b ::a"
},
{
"path": "ivy/examples/fib_repl.iv",
"chars": 1877,
"preview": "\n:: {\n x(io0 io1)\n ::main = fn(ref(io0 io1) _)\n}\n\n::main {\n fn(ref(io0 io3) _)\n io0 = @io_print_byte(62 @io_print_by"
},
{
"path": "ivy/examples/fizzbuzz.iv",
"chars": 1254,
"preview": "\n\n:: {\n x(io0 io1)\n ::loop = x(x(io0 io1) 1)\n}\n\n::end { 1_000_000 }\n\n::loop {\n x(x(io0 io3) dup(dup(n0 n1) dup(n2 n3)"
},
{
"path": "ivy/examples/hihi.iv",
"chars": 123,
"preview": "\n:: {\n x(io0 io2)\n dup(io0 io1) = @io_print_char(104 @io_print_char(105 @io_print_char(10 @io_flush(0 dup(io1 io2)))))"
},
{
"path": "ivy/src/ast.rs",
"chars": 3812,
"preview": "use std::{\n fmt::{self, Display},\n iter,\n ops::{Deref, DerefMut},\n};\n\nuse indexmap::IndexMap;\n\nuse vine_util::multi_i"
},
{
"path": "ivy/src/host/ext.rs",
"chars": 16707,
"preview": "use std::{\n fs::{File, OpenOptions},\n io::{self, Error, ErrorKind, Read, Write},\n ops::{Add, Div, Mul, Sub},\n};\n\nuse "
},
{
"path": "ivy/src/host/readback.rs",
"chars": 2937,
"preview": "use std::collections::{HashMap, hash_map::Entry};\n\nuse ivm::{\n IVM,\n addr::Addr,\n port::{Port, PortRef, Tag},\n wire:"
},
{
"path": "ivy/src/host/serialize.rs",
"chars": 11878,
"preview": "//! Conversion of Ivy [`Net`]s to IVM [`Global`]s.\n//!\n//! ## Soundness\n//!\n//! Doing this serialization soundly is a su"
},
{
"path": "ivy/src/host.rs",
"chars": 2681,
"preview": "use std::{borrow::Cow, collections::HashMap};\n\nuse indexmap::{\n IndexMap,\n map::{RawEntryApiV1, raw_entry_v1::RawEntry"
},
{
"path": "ivy/src/lexer.rs",
"chars": 2754,
"preview": "use std::fmt::Debug;\n\nuse vine_util::lexer::{Lex, LexerState, Token as TokenTrait};\n\nuse crate::parser::ParseError;\n\n#[d"
},
{
"path": "ivy/src/lib.rs",
"chars": 90,
"preview": "pub mod ast;\npub mod host;\npub mod lexer;\npub mod optimize;\npub mod parser;\npub mod repl;\n"
},
{
"path": "ivy/src/optimize/eta_reduce.rs",
"chars": 2481,
"preview": "use std::{\n collections::{HashMap, hash_map::Entry},\n mem::take,\n};\n\nuse crate::ast::{Net, Tree};\n\nimpl Net {\n /// Ap"
},
{
"path": "ivy/src/optimize/inline_globals.rs",
"chars": 1624,
"preview": "use std::collections::HashMap;\n\nuse crate::ast::{Net, Nets, Tree};\n\n/// Inline any globals defined to be single-node net"
},
{
"path": "ivy/src/optimize/inline_vars.rs",
"chars": 1279,
"preview": "use std::{\n collections::{HashMap, hash_map::Entry},\n mem::take,\n};\n\nuse crate::ast::{Net, Tree};\n\n#[derive(Debug, Def"
},
{
"path": "ivy/src/optimize/pre_reduce.rs",
"chars": 2333,
"preview": "use std::{\n collections::{HashMap, hash_map::Entry},\n mem::take,\n};\n\nuse ivm::{IVM, ext::Extrinsics, heap::Heap, port:"
},
{
"path": "ivy/src/optimize/prune.rs",
"chars": 987,
"preview": "use std::collections::HashSet;\n\nuse crate::ast::{Net, Nets, Tree};\n\n/// Prune unused global nets.\npub fn prune(nets: &mu"
},
{
"path": "ivy/src/optimize.rs",
"chars": 928,
"preview": "use crate::ast::Nets;\n\nmod eta_reduce;\nmod inline_globals;\nmod inline_vars;\nmod pre_reduce;\nmod prune;\n\nuse inline_globa"
},
{
"path": "ivy/src/parser.rs",
"chars": 4356,
"preview": "use vine_util::{\n lexer::{Lex, TokenSet},\n parser::{Parse, ParserState},\n};\n\nuse crate::{\n ast::{Net, Nets, Tree},\n "
},
{
"path": "ivy/src/repl.rs",
"chars": 3415,
"preview": "use std::fmt::{self, Display};\n\nuse indexmap::{IndexMap, map::Entry};\nuse ivm::{\n IVM,\n port::{Port, Tag},\n wire::Wir"
},
{
"path": "lsp/Cargo.toml",
"chars": 287,
"preview": "[package]\nname = \"vine-lsp\"\nversion = \"0.0.0\"\nedition = \"2024\"\n\n[dependencies]\nfutures = \"0.3.31\"\nglob = \"0.3.1\"\ntokio ="
},
{
"path": "lsp/client/.gitignore",
"chars": 18,
"preview": "node_modules\ndist\n"
},
{
"path": "lsp/client/.vscodeignore",
"chars": 34,
"preview": "src/*.ts\ntsconfig.json\n.gitignore\n"
},
{
"path": "lsp/client/README.md",
"chars": 72,
"preview": "Language support for the [Vine](https://vine.dev) programming language.\n"
},
{
"path": "lsp/client/package.json",
"chars": 2463,
"preview": "{\n \"name\": \"vine\",\n \"displayName\": \"Vine\",\n \"description\": \"Language support for the Vine programming language\",\n \"p"
},
{
"path": "lsp/client/src/extension.ts",
"chars": 6351,
"preview": "import * as vscode from \"vscode\";\nimport { LanguageClient } from \"vscode-languageclient/node\";\nimport { Language, Parser"
},
{
"path": "lsp/client/src/ivy-config.json",
"chars": 437,
"preview": "{\n \"comments\": {\n \"lineComment\": \"//\",\n \"blockComment\": [\"/*\", \"*/\"]\n },\n \"brackets\": [\n [\"{\", \"}\"],\n [\"("
},
{
"path": "lsp/client/src/ivy-grammar.json",
"chars": 1596,
"preview": "{\n \"name\": \"ivy\",\n \"patterns\": [\n { \"include\": \"#line-comment\" },\n { \"include\": \"#block-comment\" },\n { \"inclu"
},
{
"path": "lsp/client/src/vine-config.json",
"chars": 661,
"preview": "{\n \"comments\": {\n \"lineComment\": \"//\",\n \"blockComment\": [\"/*\", \"*/\"]\n },\n \"brackets\": [\n [\"{\", \"}\"],\n [\"["
},
{
"path": "lsp/client/src/vine-grammar.json",
"chars": 2390,
"preview": "{\n \"name\": \"vine\",\n \"patterns\": [\n { \"include\": \"#line-comment\" },\n { \"include\": \"#block-comment\" },\n { \"incl"
},
{
"path": "lsp/client/tsconfig.json",
"chars": 176,
"preview": "{\n \"compilerOptions\": {\n \"module\": \"commonjs\",\n \"target\": \"es2023\",\n \"lib\": [\"es2023\", \"dom\"],\n \"outDir\": \""
},
{
"path": "lsp/grammars.nix",
"chars": 1335,
"preview": "{\n pkgs,\n}:\nlet\n inherit (pkgs)\n lib\n stdenv\n stdenvNoCC\n tree-sitter\n nodejs_24\n nushell\n ;\n\n g"
},
{
"path": "lsp/src/lib.rs",
"chars": 15022,
"preview": "use std::{\n collections::{BTreeMap, HashMap},\n env::current_dir,\n fs,\n path::{Path, PathBuf},\n time::Instant,\n};\n\nu"
},
{
"path": "lsp/tree-sitter-ivy/.gitignore",
"chars": 71,
"preview": "node_modules/\nsrc/\n*.a\n*.so\n*.so.*\n*.dylib\n*.dll\n*.pc\n*.wasm\n*.obj\n*.o\n"
},
{
"path": "lsp/tree-sitter-ivy/grammar.js",
"chars": 2053,
"preview": "/// <reference types=\"tree-sitter-cli/dsl\" />\n// @ts-check\n\nmodule.exports = grammar({\n name: \"ivy\",\n\n word: $ => $.id"
},
{
"path": "lsp/tree-sitter-ivy/package.json",
"chars": 254,
"preview": "{\n \"name\": \"tree-sitter-ivy\",\n \"devDependencies\": {\n \"prebuildify\": \"^6.0.1\",\n \"tree-sitter-cli\": \"^0.25.3\",\n "
},
{
"path": "lsp/tree-sitter-ivy/queries/highlights.scm",
"chars": 270,
"preview": "\n[\n \"=\"\n \"#\"\n \"[\"\n \"]\"\n \"(\"\n \")\"\n \"{\"\n \"}\"\n (erase)\n] @punctuation\n\n[\n \"@\"\n \"?\"\n \"$\"\n] @operator\n\n(ext_fn (i"
},
{
"path": "lsp/tree-sitter-ivy/queries/textobjects.scm",
"chars": 197,
"preview": "\n(global_net (net) @function.inside) @function.around\n\n(line_comment (line_comment_content) @comment.inside) @comment.ar"
},
{
"path": "lsp/tree-sitter-ivy/test.nu",
"chars": 403,
"preview": "\ntree-sitter generate\n\nlet success = (\n ls\n ../../ivy/examples/*.iv\n | each {\n let path = $in.name\n let succe"
},
{
"path": "lsp/tree-sitter-ivy/tree-sitter.json",
"chars": 416,
"preview": "{\n \"$schema\": \"https://tree-sitter.github.io/tree-sitter/assets/schemas/config.schema.json\",\n \"grammars\": [\n {\n "
},
{
"path": "lsp/tree-sitter-vine/.gitignore",
"chars": 71,
"preview": "node_modules/\nsrc/\n*.a\n*.so\n*.so.*\n*.dylib\n*.dll\n*.pc\n*.wasm\n*.obj\n*.o\n"
},
{
"path": "lsp/tree-sitter-vine/grammar.js",
"chars": 16998,
"preview": "/// <reference types=\"tree-sitter-cli/dsl\" />\n// @ts-check\n\nconst delimited = (open, sep, close, inner) =>\n seq(\n .."
},
{
"path": "lsp/tree-sitter-vine/package.json",
"chars": 256,
"preview": "{\n \"name\": \"tree-sitter-vine\",\n \"devDependencies\": {\n \"prebuildify\": \"^6.0.1\",\n \"tree-sitter\": \"^0.25.0\",\n \"t"
},
{
"path": "lsp/tree-sitter-vine/queries/highlights.scm",
"chars": 1183,
"preview": "\n[\n \"pub\"\n \"mod\"\n \"use\"\n \"as\"\n \"fn\"\n \"struct\"\n \"enum\"\n \"type\"\n \"trait\"\n \"impl\"\n \"match\"\n \"let\"\n \"assert\"\n "
},
{
"path": "lsp/tree-sitter-vine/queries/injections.scm",
"chars": 69,
"preview": "\n((inline_ivy) @injection.content (#set! injection.language \"ivy\"))\n\n"
},
{
"path": "lsp/tree-sitter-vine/queries/textobjects.scm",
"chars": 1323,
"preview": "\n(item_fn (block) @function.inside) @function.around\n(stmt_let_fn (block) @function.inside) @function.around\n(expr_fn (b"
},
{
"path": "lsp/tree-sitter-vine/test.nu",
"chars": 485,
"preview": "\ntree-sitter generate\n\nlet success = (\n ls\n ../../root/**/*.vi\n ../../vine/examples/*.vi\n ../../tests/programs"
},
{
"path": "lsp/tree-sitter-vine/tree-sitter.json",
"chars": 470,
"preview": "{\n \"$schema\": \"https://tree-sitter.github.io/tree-sitter/assets/schemas/config.schema.json\",\n \"grammars\": [\n {\n "
},
{
"path": "root/Ext.vi",
"chars": 3625,
"preview": "\nuse derive::{Composite, Struct};\nuse ops::Cast;\nuse util::transmute;\n\n/// An extrinsic value logically representing a V"
},
{
"path": "root/IO/File.vi",
"chars": 6952,
"preview": "\nuse Ext::Unknown;\nuse ops::Cast;\nuse util::transmute;\n\npub type File;\n\npub mod File {\n pub impl : Show[File];\n pub im"
},
{
"path": "root/IO/IO.vi",
"chars": 4305,
"preview": "\nuse #root::Ext;\n\npub mod File;\n\n/// A special primitive type used to interact with the outside world.\n/// Values of thi"
},
{
"path": "root/data/Array.vi",
"chars": 15194,
"preview": "\nuse List::Stream;\nuse logical::Nullable;\nuse ops::{Cast, Index::{Index, IndexPlace, IndexSpace, IndexValue}};\nuse util:"
},
{
"path": "root/data/Heap.vi",
"chars": 5566,
"preview": "\nuse logical::Nullable;\nuse ops::{Cast, Concat, comparison::Ord};\nuse util::{duplicate, erase};\nuse data::Iterator::{Ite"
},
{
"path": "root/data/Iterator.vi",
"chars": 15189,
"preview": "\nuse ops::comparison::Ord;\nuse derive::Tuple;\nuse util::transmute;\n\npub trait[I] Iterator[T] {\n #[builtin = \"advance\"]\n"
},
{
"path": "root/data/List.vi",
"chars": 14044,
"preview": "\nuse data::Iterator::{Iterator, Collect, Iterate};\nuse ops::{Cast, Concat, Range::{Range, Bound}};\nuse util::{duplicate,"
},
{
"path": "root/data/Map.vi",
"chars": 5953,
"preview": "\nuse data::Iterator::{Iterator, Collect, Iterate};\nuse ops::{Cast, Concat, Index::{Index, IndexPlace, IndexSpace, IndexV"
},
{
"path": "root/data/Set.vi",
"chars": 10446,
"preview": "\nuse data::Iterator::{Iterator, Collect, Iterate};\nuse debug::Show;\nuse logical::Nullable;\nuse ops::{Cast, Concat};\nuse "
},
{
"path": "root/data/data.vi",
"chars": 118,
"preview": "\n/// Data structures.\nmod;\n\npub mod List;\npub mod Array;\n\npub mod Map;\npub mod Set;\n\npub mod Heap;\n\npub mod Iterator;\n"
},
{
"path": "root/debug/Show.vi",
"chars": 6109,
"preview": "\nuse ops::Cast;\nuse data::List as List_;\nuse derive::{Enum, IfConst, Object as Object_, Opaque, Struct, Tuple as Tuple_,"
},
{
"path": "root/debug/debug.vi",
"chars": 2980,
"preview": "\n/// Debugging-related utilities.\nmod;\n\nuse ops::{Cast, Fn};\nuse util::{duplicate, erase, eraser};\n\npub mod Show;\n\n/// W"
},
{
"path": "root/derive.vi",
"chars": 3643,
"preview": "\nuse ops::Cast;\n\n#[builtin = \"Tuple\"]\npub trait[] Tuple[Tuple, Init, Rest] {\n fn deconstruct(tuple: Tuple) -> (Init, Re"
},
{
"path": "root/logical/Bool.vi",
"chars": 1917,
"preview": "\nuse ops::{Cast, bitwise::{BitAnd, BitOr, BitXor, Not}};\nuse util::{duplicate, erase, transmute};\n\n#[builtin = \"Bool\"]\np"
},
{
"path": "root/logical/Default.vi",
"chars": 514,
"preview": "\nuse #root::derive::{Composite, Struct};\n\n#[builtin = \"Default\"]\npub trait[T] Default {\n const default: T;\n}\n\npub mod D"
},
{
"path": "root/logical/Nullable.vi",
"chars": 67,
"preview": "\n#[self_dual]\npub unsafe enum Nullable[T] {\n data(T),\n null(),\n}\n"
},
{
"path": "root/logical/Option.vi",
"chars": 1447,
"preview": "\n#[impl(Show, Eq, Ord)]\n#[builtin = \"Option\"]\npub enum* Option[T] {\n None(),\n Some(T),\n}\n\npub mod Option {\n pub impl "
},
{
"path": "root/logical/Result.vi",
"chars": 1426,
"preview": "\n#[impl(Show, Eq, Ord)]\n#[builtin = \"Result\"]\npub enum* Result[T, E] {\n Ok(T),\n Err(E),\n}\n\npub mod Result {\n pub fn ."
},
{
"path": "root/logical/logical.vi",
"chars": 82,
"preview": "\npub mod Bool;\npub mod Default;\npub mod Nullable;\npub mod Option;\npub mod Result;\n"
},
{
"path": "root/numeric/F32/F32.vi",
"chars": 4482,
"preview": "\nuse ops::{Cast, arithmetic::{Add, Div, Mul, Neg, Pos, Pow, Rem, Sub}, comparison::{Le, Lt}};\nuse util::{duplicate, eras"
},
{
"path": "root/numeric/F64/F64.vi",
"chars": 5444,
"preview": "\nuse ops::{Cast, arithmetic::{Add, Div, Mul, Neg, Pos, Pow, Rem, Sub}, comparison::{Eq, Le, Lt}};\n\n#[builtin = \"F64\"]\npu"
},
{
"path": "root/numeric/F64/common.vi",
"chars": 2409,
"preview": "\npub const ln2_hi: F64 = 6.93147180369123816490e-01[F64];\npub const ln2_lo: F64 = 1.90821492927058770002e-10[F64];\npub c"
},
{
"path": "root/numeric/F64/exp.vi",
"chars": 4121,
"preview": "\n// Adapted from https://go.dev/src/math/exp.go.\n//\n// ====================================================\n// Copyright"
},
{
"path": "root/numeric/F64/ln.vi",
"chars": 4073,
"preview": "\nuse common::{ln2_hi, ln2_lo};\n\n// Adapted from https://go.dev/src/math/log.go.\n//\n// =================================="
},
{
"path": "root/numeric/Float/Float.vi",
"chars": 631,
"preview": "\n// TODO: Change Mantissa to associated type once Vine supports them.\npub trait[F] Float[Mantissa] {\n const nan: F;\n c"
},
{
"path": "root/numeric/Float/parse.vi",
"chars": 5335,
"preview": "\nuse ops::Cast;\nuse ops::arithmetic::{Add, Neg, Sub};\nuse ops::bitwise::{BitAnd, Shl, Shr};\n\npub mod parse[\n F, Mantiss"
},
{
"path": "root/numeric/Float/to_string.vi",
"chars": 3572,
"preview": "\nuse ops::Cast;\nuse ops::bitwise::{BitOr, Shl};\n\npub impl to_string[\n F*, Mantissa;\n Float[F, Mantissa],\n Drop[Mantis"
},
{
"path": "root/numeric/I32.vi",
"chars": 4344,
"preview": "\nuse ops::{\n Cast,\n arithmetic::{Add, Div, Mul, Neg, Pos, Pow, Rem, Sub},\n bitwise::{BitAnd, BitOr, BitXor, Not, Shl,"
},
{
"path": "root/numeric/Int.vi",
"chars": 4999,
"preview": "\nuse ops::{Cast, arithmetic::{Add, Div, Mul, Neg, Pow, Rem, Sub}};\n\n#[impl(Default)]\npub struct* Int(Bool, Nat);\n\npub mo"
},
{
"path": "root/numeric/N32.vi",
"chars": 6582,
"preview": "\nuse ops::{\n Cast,\n arithmetic::{Add, Div, Mul, Neg, Pos, Pow, Rem, Sub},\n bitwise::{BitAnd, BitOr, BitXor, Not, Shl,"
},
{
"path": "root/numeric/N64.vi",
"chars": 7368,
"preview": "\nuse ops::{\n Cast,\n arithmetic::{Add, Div, Mul, Pow, Rem, Sub},\n bitwise::{BitAnd, BitOr, BitXor, Not, Shl, Shr},\n};\n"
},
{
"path": "root/numeric/Nat/Nat.vi",
"chars": 9167,
"preview": "\nuse ops::{\n Cast,\n arithmetic::{Add, Div, Mul, Pow, Rem, Sub},\n bitwise::{BitAnd, BitOr, BitXor, Shl, Shr},\n};\n\n/// "
},
{
"path": "root/numeric/Nat/div_rem.vi",
"chars": 3352,
"preview": "\n// Nat stored unnormalized (can have leading zero) and big endian\nstruct? BigEndianNat(List[N32]);\n\nmod BigEndianNat {\n"
},
{
"path": "root/numeric/numeric.vi",
"chars": 109,
"preview": "\npub mod N32;\npub mod N64;\npub mod Nat;\n\npub mod I32;\npub mod Int;\n\npub mod F32;\npub mod F64;\npub mod Float;\n"
},
{
"path": "root/ops/Index.vi",
"chars": 755,
"preview": "\n#[builtin = \"Index\"]\npub trait[T] Index[K, V] {}\n\n#[builtin = \"IndexValue\"]\npub trait[T] IndexValue[K, V] {\n fn .assum"
},
{
"path": "root/ops/Range.vi",
"chars": 2925,
"preview": "\nuse data::Iterator::{Iterator, Iterate};\n\npub trait[B] Bound[T] {\n fn .left_of(self: &B, value: &T) -> Bool;\n fn .rig"
},
{
"path": "root/ops/arithmetic.vi",
"chars": 854,
"preview": "\npub trait[A, B] Add[O] {\n #[builtin = \"add\"]\n fn add(a: A, b: B) -> O;\n}\n\npub trait[A, B] Sub[O] {\n #[builtin = \"sub"
},
{
"path": "root/ops/bitwise.vi",
"chars": 465,
"preview": "\npub trait[A, B] BitAnd[O] {\n #[builtin = \"and\"]\n fn bit_and(a: A, b: B) -> O;\n}\n\npub trait[A, B] BitOr[O] {\n #[built"
},
{
"path": "root/ops/comparison.vi",
"chars": 7102,
"preview": "\nuse derive::{Enum, Struct, Tuple, Variant};\nuse ops::arithmetic::Neg;\n\npub trait[T] Eq {\n #[builtin = \"eq\"]\n fn eq(a:"
},
{
"path": "root/ops/elementwise.vi",
"chars": 10535,
"preview": "\nuse arithmetic::{Add, Div, Mul, Neg, Pos, Pow, Rem, Sub};\nuse bitwise::{BitAnd, BitOr, BitXor, Not};\nuse derive::{Compo"
},
{
"path": "root/ops/flex.vi",
"chars": 3004,
"preview": "\nuse derive::{Composite, Enum, IfConst, Struct, Variant};\nuse util::{duplicate, erase, transmute};\n\n#[builtin = \"Fork\"]\n"
},
{
"path": "root/ops/ops.vi",
"chars": 744,
"preview": "\npub mod arithmetic;\npub mod bitwise;\npub mod comparison;\npub mod elementwise;\npub mod flex;\npub mod Index;\npub mod Rang"
},
{
"path": "root/prelude.vi",
"chars": 879,
"preview": "\n/// The prelude, which defines items that are in scope without needing to be\n/// explicitly imported.\n///\n/// The prelu"
},
{
"path": "root/rng/Pcg32.vi",
"chars": 1206,
"preview": "\n/// A PCG random number generator (XSH RR 64/32 (LCG) variant).\npub struct* Pcg32(N64, N64);\n\npub mod Pcg32 {\n /// A c"
},
{
"path": "root/rng/rng.vi",
"chars": 148,
"preview": "\n/// Pseudo-random number generation utilities.\n///\n/// Note that Vine programs are deterministic, so all RNGs require a"
},
{
"path": "root/root.vi",
"chars": 238,
"preview": "\n/// Vine's standard library.\nmod;\n\npub mod data;\npub mod debug;\npub mod derive;\npub mod Ext;\npub mod logical;\npub mod n"
},
{
"path": "root/unicode/Char.vi",
"chars": 2963,
"preview": "\nuse ops::{Cast, arithmetic::{Add, Sub}};\nuse util::{duplicate, erase, transmute};\n\n/// A Unicode scalar value, or \"char"
},
{
"path": "root/unicode/String.vi",
"chars": 4604,
"preview": "\nuse data::Iterator::{Iterator, Collect, Iterate};\nuse ops::{Cast, Concat};\n\n/// A Unicode string, represented as a list"
},
{
"path": "root/unicode/unicode.vi",
"chars": 31,
"preview": "\npub mod Char;\npub mod String;\n"
},
{
"path": "root/util.vi",
"chars": 1273,
"preview": "\nuse ops::Cast;\n\n/// Swap the values in two references.\n/// ```vi\n/// let a = 1;\n/// let b = 2;\n/// swap(&a, &b);\n/// a "
},
{
"path": "rust-toolchain.toml",
"chars": 135,
"preview": "[toolchain]\nprofile = \"minimal\"\nchannel = \"nightly-2025-11-11\"\ncomponents = [\"rustfmt\", \"clippy\", \"miri\", \"rust-src\", \"r"
},
{
"path": "rustfmt.toml",
"chars": 128,
"preview": "edition = \"2024\"\ntab_spaces = 2\nuse_small_heuristics = \"Max\"\nmax_width = 100\nwrap_comments = true\nimports_granularity = "
},
{
"path": "style.nix",
"chars": 1396,
"preview": "{\n pkgs,\n treefmt-nix,\n cli,\n}:\nlet\n dprintConfig = builtins.fromJSON (builtins.readFile ./dprint.json);\n treefmt ="
},
{
"path": "tests/aoc_2024/README.md",
"chars": 146,
"preview": "**Note**: these files are very badly written and should not be taken as example\nVine code. They are only here for the sa"
},
{
"path": "tests/aoc_2024/day_01.vi",
"chars": 970,
"preview": "\npub fn main(&io: &IO) {\n let input = io.full_input();\n\n let lines = input.split_trim(\"\\n\").map(fn* (line: String) {\n "
},
{
"path": "tests/aoc_2024/day_02.vi",
"chars": 1283,
"preview": "\npub fn main(&io: &IO) {\n let input = io.full_input();\n\n let lines = input.split_trim(\"\\n\");\n\n let safe_count = 0;\n "
},
{
"path": "tests/aoc_2024/day_03.vi",
"chars": 708,
"preview": "\npub fn main(&io: &IO) {\n let input = io.full_input();\n\n let part1 = get_muls(input);\n\n io.println(\"Part 1: {part1}\")"
},
{
"path": "tests/aoc_2024/day_04.vi",
"chars": 3921,
"preview": "\nuse #root::{data::Iterator::Fused, util::{erase, eraser}};\n\npub fn main(&io: &IO) {\n let lines = [];\n while io.read_l"
},
{
"path": "tests/aoc_2024/day_05.vi",
"chars": 2543,
"preview": "\nuse #root::{data::Array, ops::elementwise as _, util::move};\n\npub fn main(&io: &IO) {\n let masks = Array::new(100, ((0"
},
{
"path": "tests/aoc_2024/day_06.vi",
"chars": 1913,
"preview": "\nuse #root::{data::Array, ops::elementwise as _};\n\npub fn main(&io: &IO) {\n let input = io.full_input();\n\n let grid = "
},
{
"path": "tests/aoc_2024/day_07.vi",
"chars": 1189,
"preview": "\n\npub fn main(&io: &IO) {\n let part1 = 0[N64];\n let part2 = 0[N64];\n while io.read_line() is Some(line) {\n let (go"
},
{
"path": "tests/aoc_2024/day_08.vi",
"chars": 1362,
"preview": "\nuse #root::{data::Map, ops::elementwise as _};\n\npub fn main(&io: &IO) {\n let input = io.full_input();\n\n let antennas "
}
]
// ... and 546 more files (download for full content)
About this extraction
This page contains the full source code of the VineLang/vine GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 746 files (8.4 MB), approximately 2.2M tokens, and a symbol index with 1838 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.