Showing preview only (3,369K chars total). Download the full file or copy to clipboard to get everything.
Repository: eirproject/eir
Branch: master
Commit: a615a9d41563
Files: 339
Total size: 3.2 MB
Directory structure:
gitextract_fonefwfl/
├── .gitignore
├── .gitmodules
├── DOCS.md
├── LICENSE.md
├── README.md
├── ROADMAP.org
├── azure-pipelines.yml
├── ci/
│ ├── azure-clone-patch-otp.yml
│ ├── azure-install-dependencies.yml
│ ├── azure-install-rust.yml
│ └── azure-test.yml
├── deny.toml
├── libeir_diagnostics/
│ ├── Cargo.toml
│ └── src/
│ ├── codemap.rs
│ ├── filename.rs
│ ├── index.rs
│ ├── lib.rs
│ ├── source.rs
│ └── span.rs
├── libeir_frontend/
│ ├── Cargo.toml
│ ├── README.md
│ └── src/
│ ├── abstr_erlang.rs
│ ├── eir.rs
│ ├── erlang.rs
│ └── lib.rs
├── libeir_intern/
│ ├── Cargo.toml
│ └── src/
│ ├── arena.rs
│ ├── lib.rs
│ └── symbol.rs
├── libeir_interpreter/
│ ├── Cargo.toml
│ ├── README.md
│ └── src/
│ ├── erl_lib/
│ │ ├── erlang.rs
│ │ ├── file.rs
│ │ ├── lists.rs
│ │ ├── maps.rs
│ │ ├── math.rs
│ │ ├── mod.rs
│ │ └── os.rs
│ ├── erl_tests/
│ │ └── mod.rs
│ ├── lib.rs
│ ├── mailbox.rs
│ ├── module.rs
│ ├── pattern.rs
│ ├── process/
│ │ ├── match.rs
│ │ └── mod.rs
│ ├── receive.rs
│ ├── term.rs
│ ├── trace/
│ │ ├── dummy.rs
│ │ ├── mod.rs
│ │ └── trace.rs
│ └── vm.rs
├── libeir_ir/
│ ├── Cargo.toml
│ ├── build.rs
│ └── src/
│ ├── algo/
│ │ ├── equality.rs
│ │ ├── func_tree.rs
│ │ ├── live.rs
│ │ ├── mangle/
│ │ │ ├── datatypes.rs
│ │ │ ├── mod.rs
│ │ │ ├── receiver.rs
│ │ │ └── tests.rs
│ │ ├── mod.rs
│ │ ├── op_branches.rs
│ │ └── validate.rs
│ ├── binary.rs
│ ├── constant/
│ │ ├── atomic.rs
│ │ ├── float.rs
│ │ └── mod.rs
│ ├── dialect/
│ │ └── mod.rs
│ ├── function/
│ │ ├── builder/
│ │ │ ├── mod.rs
│ │ │ ├── op.rs
│ │ │ └── primop.rs
│ │ ├── format.rs
│ │ ├── location.rs
│ │ ├── mod.rs
│ │ ├── op.rs
│ │ ├── pool_container.rs
│ │ ├── primop.rs
│ │ ├── serialize.rs
│ │ └── value.rs
│ ├── graph/
│ │ ├── block_graph.rs
│ │ ├── control_flow_graph.rs
│ │ ├── live_block_graph.rs
│ │ └── mod.rs
│ ├── ir_construct_macro.rs
│ ├── lib.rs
│ ├── module.rs
│ ├── operation/
│ │ ├── binary_construct.rs
│ │ ├── case.rs
│ │ ├── mod.rs
│ │ └── receive.rs
│ ├── pattern/
│ │ ├── fmt.rs
│ │ └── mod.rs
│ ├── text/
│ │ ├── ast/
│ │ │ ├── mod.rs
│ │ │ └── raise.rs
│ │ ├── dot_printer.rs
│ │ ├── lower/
│ │ │ ├── location.rs
│ │ │ └── mod.rs
│ │ ├── mod.rs
│ │ ├── parse_dyn/
│ │ │ └── mod.rs
│ │ ├── parser/
│ │ │ ├── errors.rs
│ │ │ ├── grammar.lalrpop
│ │ │ ├── lexer.rs
│ │ │ └── mod.rs
│ │ ├── printer/
│ │ │ ├── constant.rs
│ │ │ ├── mod.rs
│ │ │ └── operation.rs
│ │ └── printer.old.rs
│ └── traits/
│ ├── mod.rs
│ ├── op_branches.rs
│ ├── parser.rs
│ └── printer.rs
├── libeir_lowerutils/
│ ├── Cargo.toml
│ └── src/
│ ├── lib.rs
│ └── tests.rs
├── libeir_passes/
│ ├── Cargo.toml
│ └── src/
│ ├── compile_pattern/
│ │ ├── erlang_pattern_provider.rs
│ │ ├── lower_cfg.rs
│ │ ├── mod.rs
│ │ └── tests.rs
│ ├── dummy_location.rs
│ ├── lib.rs
│ ├── naive_inline_closures/
│ │ ├── mod.rs
│ │ └── tests.rs
│ ├── simplify_cfg/
│ │ ├── analyze/
│ │ │ ├── call.rs
│ │ │ ├── if_bool.rs
│ │ │ ├── mod.rs
│ │ │ └── unpack_value_list.rs
│ │ ├── chain_graph/
│ │ │ ├── mod.rs
│ │ │ └── synthesis/
│ │ │ ├── compound.rs
│ │ │ ├── mod.rs
│ │ │ ├── simple.rs
│ │ │ ├── single.rs
│ │ │ └── terminating_target.rs
│ │ ├── mod.rs
│ │ ├── rewrite.rs
│ │ └── tests.rs
│ ├── util.rs
│ └── validate.rs
├── libeir_syntax_core/
│ ├── Cargo.toml
│ ├── build.rs
│ └── src/
│ ├── ast.rs
│ ├── lexer.rs
│ ├── lib.rs
│ ├── lower_hir.rs
│ └── parser/
│ ├── grammar.lalrpop
│ ├── grammar.rs
│ └── mod.rs
├── libeir_syntax_erl/
│ ├── .gitignore
│ ├── Cargo.toml
│ ├── build.rs
│ └── src/
│ ├── abstr/
│ │ ├── lower.rs
│ │ └── mod.rs
│ ├── evaluator.rs
│ ├── lexer/
│ │ ├── errors.rs
│ │ ├── lexer.rs
│ │ ├── mod.rs
│ │ └── token.rs
│ ├── lib.rs
│ ├── lower/
│ │ ├── errors.rs
│ │ ├── exception_handler_stack.rs
│ │ ├── expr/
│ │ │ ├── binary.rs
│ │ │ ├── binary_expr.rs
│ │ │ ├── case.rs
│ │ │ ├── catch.rs
│ │ │ ├── comprehension.rs
│ │ │ ├── literal.rs
│ │ │ ├── map.rs
│ │ │ ├── mod.rs
│ │ │ ├── receive.rs
│ │ │ └── record.rs
│ │ ├── mod.rs
│ │ ├── pattern/
│ │ │ ├── mod.rs
│ │ │ └── tree/
│ │ │ ├── from_expr.rs
│ │ │ ├── lower.rs
│ │ │ ├── merge.rs
│ │ │ ├── mod.rs
│ │ │ └── promote_values.rs
│ │ ├── scope.rs
│ │ └── tests.rs
│ ├── parser/
│ │ ├── ast/
│ │ │ ├── attributes.rs
│ │ │ ├── expr.rs
│ │ │ ├── functions.rs
│ │ │ ├── mod.rs
│ │ │ ├── module.rs
│ │ │ └── types.rs
│ │ ├── binary.rs
│ │ ├── errors.rs
│ │ ├── grammar.lalrpop
│ │ ├── macros.rs
│ │ └── mod.rs
│ ├── preprocessor/
│ │ ├── directive.rs
│ │ ├── directives.rs
│ │ ├── errors.rs
│ │ ├── macros.rs
│ │ ├── mod.rs
│ │ ├── preprocessor.rs
│ │ ├── token_reader.rs
│ │ ├── token_stream.rs
│ │ └── types.rs
│ └── util/
│ ├── binary/
│ │ ├── mod.rs
│ │ └── static.rs
│ ├── encoding.rs
│ ├── escape_stm.rs
│ ├── mod.rs
│ ├── string.rs
│ └── string_tokenizer.rs
├── libeir_tests/
│ ├── Cargo.toml
│ ├── shadowing.erl
│ └── src/
│ ├── control_flow/
│ │ ├── accumulate_list.rs
│ │ ├── fib.rs
│ │ ├── get_values.rs
│ │ ├── mod.rs
│ │ ├── nth_root.rs
│ │ └── shadowing.rs
│ ├── ct_runner.rs
│ ├── errors.rs
│ ├── lib.rs
│ ├── list_comprehensions.rs
│ ├── otp/
│ │ └── mod.rs
│ ├── patterns.rs
│ └── records.rs
├── otp_build/
│ ├── bs_match_SUITE.erl
│ ├── bs_match_SUITE.erl.patch
│ ├── bs_match_SUITE_patched.erl
│ ├── otp_build_core.patch
│ ├── patch_build_otp.sh
│ └── patch_tests.sh
├── test_data/
│ ├── Elixir.Enum.erl
│ ├── README.md
│ ├── application_controller.core
│ ├── basic_module.core
│ ├── basic_module.erl
│ ├── basic_regress/
│ │ ├── enum_aggregate.core
│ │ ├── function_capture_1.core
│ │ ├── line_annotation_fail_1.core
│ │ └── type_construction_fail_1.core
│ ├── compile.core
│ ├── compile_messages_per_file.core
│ ├── compile_stripped.core
│ ├── compile_stripped_small.core
│ ├── factorial.core
│ ├── factorial.erl
│ ├── function_capture.core
│ ├── function_capture.erl
│ ├── gen_server.core
│ ├── language_test.core
│ ├── language_test.erl
│ ├── long_strings.core
│ ├── long_strings.core.bak
│ ├── map_test.core
│ ├── map_test.erl
│ ├── maps.abstr
│ ├── maps.erl
│ ├── match.core
│ ├── match.erl
│ ├── match_SUITE.abstr
│ ├── match_SUITE.erl
│ ├── test.core
│ ├── test.erl
│ ├── testing.core
│ └── testing.erl
├── tools/
│ ├── Cargo.toml
│ └── src/
│ └── compile.rs
└── util/
├── any_map/
│ ├── Cargo.toml
│ └── src/
│ ├── any_any_map.rs
│ ├── any_map.rs
│ └── lib.rs
├── libeir_etf/
│ ├── Cargo.toml
│ ├── src/
│ │ ├── constants.rs
│ │ ├── decoder.rs
│ │ ├── encoder.rs
│ │ ├── lib.rs
│ │ ├── reader.rs
│ │ ├── term.rs
│ │ ├── test/
│ │ │ └── mod.rs
│ │ └── writer.rs
│ └── test_data/
│ ├── basic_list.etf
│ ├── generate.exs
│ ├── int_tuple.etf
│ ├── test_1.etf
│ └── test_2.etf
├── libeir_util_binary/
│ ├── Cargo.toml
│ └── src/
│ ├── bitvec.rs
│ ├── extend.rs
│ ├── impls.rs
│ ├── integer.rs
│ ├── lib.rs
│ └── slice.rs
├── libeir_util_datastructures/
│ ├── Cargo.toml
│ └── src/
│ ├── aux_hash_map.rs
│ ├── aux_traits/
│ │ ├── bforest_impl.rs
│ │ ├── entity_impl.rs
│ │ ├── mod.rs
│ │ └── std_impl/
│ │ └── mod.rs
│ ├── dedup_aux_primary_map.rs
│ ├── forest.rs
│ ├── hashmap_stack.rs
│ ├── lib.rs
│ └── pooled_entity_set.rs
├── libeir_util_dot_graph/
│ ├── Cargo.toml
│ └── src/
│ ├── lib.rs
│ └── tablegen.rs
├── libeir_util_number/
│ ├── Cargo.toml
│ └── src/
│ ├── bigint_to_float.rs
│ ├── binary.rs
│ ├── float.rs
│ ├── integer.rs
│ ├── lib.rs
│ └── number.rs
├── libeir_util_parse/
│ ├── Cargo.toml
│ └── src/
│ ├── errors.rs
│ ├── lib.rs
│ ├── parser.rs
│ ├── result.rs
│ ├── scanner.rs
│ ├── source.rs
│ └── util.rs
├── libeir_util_parse_listing/
│ ├── Cargo.toml
│ ├── build.rs
│ └── src/
│ ├── ast.rs
│ ├── grammar.lalrpop
│ ├── lib.rs
│ ├── parser.rs
│ └── token.rs
├── libeir_util_pattern_compiler/
│ ├── Cargo.toml
│ ├── README.md
│ └── src/
│ ├── cfg/
│ │ ├── generate_dot.rs
│ │ └── mod.rs
│ ├── lib.rs
│ ├── matrix.rs
│ ├── pattern.rs
│ └── simple_pattern/
│ ├── mod.rs
│ └── test.rs
├── libeir_util_prof/
│ ├── Cargo.toml
│ └── src/
│ └── lib.rs
├── meta_table/
│ ├── Cargo.toml
│ └── src/
│ └── lib.rs
└── scoped_cell/
├── Cargo.toml
└── src/
└── lib.rs
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
target/
**/*.rs.bk
Cargo.lock
*.dot
*.dot.pdf
*.core
*.eir
*.png
!test_data/**/*.core
test_data/**/.*.core
*.swp
compiler/src/parser/grammar.rs
trace.html
trace.json
*.ll
*.bc
*.so
*.ll.old
*.o
*.s
!gen_nif/src/target/
================================================
FILE: .gitmodules
================================================
[submodule "otp"]
path = otp
url = https://github.com/erlang/otp.git
================================================
FILE: DOCS.md
================================================
# Type system
There are two parallel type systems:
* Pessimistic types
* Optimistic types
Pessimistic types are what we can statically infer from the code itself. Using only this type system, the code would behave like it would in normal Erlang. As an example, we know that `erlang:+/2` returns a number, so this type check can be elided in code that follows it. Pessimistic types should only infer details from with the function itself.
Optimistic types are informed by annotations from the user. If the user annotates that a function `foo/1` should only receive a number as an input, we can optimize the code for this case. The compiler is allowed to optionally insert type assertions for supplied optimistic type hints.
## Type tree
It should be noted that everything here is under construction and subject to change. This especially applies to the pseudo-types (`mapclass`, `tupclass` and `contlist`).
* `any`
* `atom`
* `boolean`
* `number`
* `integer`
* `smallint`
* `bigint`
* `float`
* `pid`
* `reference`
* `map`
* `list`
* `tuple`
* `n-tuple`
* `nil`
* `mapclass`
* `contlist`
### Pseudo-types
#### The `mapclass` pseudo-type
`mapclass` is a special "pseudo-type". When the compiler infers or gets informed that a map will always adhere to a given type signature at a location, it can promote the given `map` into its pseudo-type. When these types leave the locations where their type can be inferred, they get transparently demoted into their normal types.
A normal use-case for `mapclass` would be Elixirs structs.
From the host language, these look completely identical to their non-pseudo counterparts.
#### The `contlist` pseudo-type
`contlist` stands for continuous list. When a `list` gets promoted into this pseudo-type, it will not be stored as a linked list, but rather as a (possibly chunked and linked?) array.
Not very well thought out yet, but it is to be expected that the cache locality of storing a list in a continuous block of memory could improve performance in some cases. I have a sneaking unconfirmed suspicion that this could be especially useful in places where a list is constructed recursively and then reversed.
### Type modifiers
# Intrinsics
The module that contains all these intrinsics functions is `eir_intrinsics`. All of these functions are directly handled by the compiler. Defining a `eir_intrinsics` module could be done for compatibility with the BEAM, but it will always be overridden in this project.
It should be noted that no intrinsics are dynamically callable.
## Types
* `type_tag(T)`
Returns the type tag of the type in the form of an atom.
* `atom`
* `float`
* `smallint`
* `bigint`
* `annotate_type(Variable, EirTypeSpec)`
Inserts an annotation that the given variable should be the given type spec.
The compiler might insert assertions if it decides so, but can also choose not to.
When annotating types, this should be used most often.
The second argument is required to be known at compile-time.
* `assert_type(Variable, EirTypeSpec)`
Same as above, but the compiler is required to insert assertions.
This can potentially result in a performance impact over `annotate_type`.
The second argument is required to be known at compile-time.
## Message passing
### Receiving
TODO: Finish updating
`receive_start` the start of a receive structure, must jump to a
block containing a single `receive_wait`.
No further `receive_start` or function termination is allowed
before control flow is passed through a `receive_finish` or exited
the structure through the timeout edge.
```
[eir_intrinsics:receive_start()]
|
v
----------[eir_intrinsics:receive_wait()]<--------
v | |
[Timeout ] | |
[Other control flow] | |
v |
-----[Match logic ]---------------------
| |
| ----->[eir_intrinsics:receive_finish()]
| [Other ]
v
[eir_intrinsics:receive_finish()]
[Other ]
```
```
#start:
...
%receive_context = ReceiveStart(%timeout, #receive_loop)
#receive_loop:
ReceiveWait(%receive_context, #match_body, #timeout_body)
#match_body:
%message = ReceiveGetMessage()
// Jump to #receive_loop if message does not match
// Jump to #message_1_match if a message matches
// Jump to #message_2_match if another message matches
#timeout_body:
...
#message_1_match:
ReceiveFinish(%receive_context)
...
#message_2_match:
ReceiveFinish(%receive_context)
...
```
ReceiveStart,
Central node of match loop of a receive structure.
Must be the only op in its basic block.
Jumps to edge 0 when a message has been received.
Jumps to edge 1 when a timeout has occured.
ReceiveWait,
This must be the first instruction on edge 0 from ReceiveWait.
Peeks at the message in the mailbox, not removed unless ReceiveFinish
is passed through on this iteration
ReceiveGetMessage,
When jumped to from edge 0 from a ReceiveWait, control flow either
needs to (eventually) return to ReceiveWait or needs to pass
through ReceiveFinish on its way out. Returning while inside a receive
structure is a hard error!
This will actually consume the message from the mailbox.
ReceiveFinish,
================================================
FILE: LICENSE.md
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2018 Paul Schoenfelder
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: README.md
================================================
# Eir Project
Erlang compiler and IR implemented in Rust
## Details
Current features:
* Unified Thorin based IR representation named Eir
* Erlang frontend
* Core frontend
* Pattern match compilation passes
* Basic optimization and cleanup passes
* Naive interpreter used for testing
The project is split into several crates:
* `libeir_ir` - Contains the core Eir IR data structures, validation, printing
* `libeir_syntax_erl` - Frontend for Erlang, lowers to Eir.
* `libeir_syntax_core` - Frontend for Core Erlang, lowers to Eir.
* `libeir_passes` - Compiler passes operating on Eir.
* `libeir_lowerutils` - Utilities for lowering Eir to SSA form.
* `libeir_interpreter` - Naive interpreter for Eir. Used to run OTP test suites.
* `libeir_intern` - Symbol interning. Used by most other crates.
* `libeir_diagnostics` - Source span handling and diagnostics printing.
* `libeir_util` - Kitchen sink of utilities used by other crates.
* `pattern-compiler` - A generic pattern matching tree compiler.
* `tools` - CLI tools used to work with the IR.
================================================
FILE: ROADMAP.org
================================================
* Roadmap
** 1. Cleanup
*** Includes fixing all tech dept created leading up to the conference
*** Setting up infrastructure for writing integration tests using the interpreter
**** Ease work for Luke, Paul, improve confidence in high levels of compiler and the runtime
** 2. Basic passes
*** Unified cleanup pass
**** Includes removal of call chains, tail call promotion, closure inlining in one pass.
*** Simple branch elimination pass
**** Removes superfluous branches
** 3. Lower utilities
*** Introduce a barebones more traditional IR (LIR)
**** No passes operate on this (at least for now), eases lowering to other IRs
** 4. Documentation
*** Write gitbook-like documentation for EIR
**** Critical for enabling others to work with the project efficiently
** 5. BEAM assembly target
*** Target BEAM assembly from LIR
**** Enables more easy testing of compiler
**** Comparing our optimization passes with the BEAM compiler
***** Proves our approach of using a Thorin-like IR is beneficial
** 6. Typing infrastructure
*** This is critical for doing good native codegen
================================================
FILE: azure-pipelines.yml
================================================
variables:
nightly: nightly-2020-08-15
RUSTFLAGS:
jobs:
# Test crates
- template: ci/azure-test.yml
parameters:
name: test_eir
displayName: Test Eir
rust: $(nightly)
cross: true
crates:
util/libeir_util_binary: []
util/libeir_util_datastructures: []
util/libeir_util_number: []
util/libeir_util_parse: []
util/libeir_util_parse_listing: []
util/libeir_util_pattern_compiler: []
libeir_intern: []
libeir_diagnostics: []
libeir_interpreter: []
libeir_ir: []
libeir_passes: []
libeir_lowerutils: []
libeir_syntax_erl: []
libeir_tests: []
================================================
FILE: ci/azure-clone-patch-otp.yml
================================================
steps:
- script: |
set -e
cd $(Build.SourcesDirectory)
git submodule update --init --recursive
cd otp_build
bash patch_tests.sh
displayName: Clone and patch OTP
================================================
FILE: ci/azure-install-dependencies.yml
================================================
steps:
# Windows only: Install m4
#- script: |
# choco install msys2
# refreshenv
# pacman -S --noconfirm m4
# displayName: Install dependencies (windows)
# condition: eq(variables['Agent.OS'], 'Windows_NT')
================================================
FILE: ci/azure-install-rust.yml
================================================
steps:
# Linux and macOS.
- script: |
set -e
curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain none
export PATH=$PATH:$HOME/.cargo/bin
rustup toolchain install $RUSTUP_TOOLCHAIN
rustup default $RUSTUP_TOOLCHAIN
echo "##vso[task.setvariable variable=PATH;]$PATH:$HOME/.cargo/bin"
env:
RUSTUP_TOOLCHAIN: ${{parameters.rust_version}}
displayName: "Install rust (*nix)"
condition: not(eq(variables['Agent.OS'], 'Windows_NT'))
# Windows.
- script: |
curl -sSf -o rustup-init.exe https://win.rustup.rs
rustup-init.exe -y --default-toolchain none
set PATH=%PATH%;%USERPROFILE%\.cargo\bin
rustup toolchain install %RUSTUP_TOOLCHAIN%
rustup default %RUSTUP_TOOLCHAIN%
echo "##vso[task.setvariable variable=PATH;]%PATH%;%USERPROFILE%\.cargo\bin"
env:
RUSTUP_TOOLCHAIN: ${{parameters.rust_version}}-gnu
displayName: "Install rust (windows)"
condition: eq(variables['Agent.OS'], 'Windows_NT')
# All platforms.
# Add components
- ${{ each component in parameters.components }}:
- script: rustup component add ${{ component }}
displayName: "Add rust component: ${{ component }}"
# Print versions
- script: |
rustup toolchain list
rustc -Vv
cargo -V
displayName: Query rust and cargo versions
================================================
FILE: ci/azure-test.yml
================================================
jobs:
- job: ${{ parameters.name }}
displayName: ${{ parameters.displayName }}
strategy:
matrix:
Linux:
vmImage: ubuntu-16.04
${{ if parameters.cross }}:
MacOs:
vmImage: macOS-10.13
Windows:
vmImage: vs2017-win2016
pool:
vmImage: $(vmImage)
steps:
- template: azure-install-rust.yml
parameters:
rust_version: ${{ parameters.rust }}
# - template: azure-install-dependencies.yml
- template: azure-clone-patch-otp.yml
- script: cargo build --tests
env:
CI: 'True'
displayName: cargo build --tests
- ${{ each crate in parameters.crates }}:
- script: cargo test
env:
CI: 'True'
displayName: ${{ crate.key }} - cargo test
workingDirectory: $(Build.SourcesDirectory)/${{ crate.key }}
================================================
FILE: deny.toml
================================================
[licenses]
# This section is considered when running `cargo deny check license`
# More documentation for the licenses section can be found here:
# https://github.com/EmbarkStudios/cargo-deny#the-licenses-section
# Uncomment the following line to change the lint level for unlicensed crates
# [possible values: "deny", "allow" or "warn"].
#unlicensed = "deny"
# Uncomment the following line to explictly allow certain licenses
# See https://spdx.org/licenses/ for list of possible licenses
# [possible values: any SPDX 3.7 short identifier (+ optional exception)].
allow = ["MIT", "Apache-2.0", "Apache-2.0 WITH LLVM-exception", "ISC", "BSD-3-Clause", "BSD-2-Clause", "CC0-1.0"]
# Uncomment the following line to explictly disallow certain licenses
# See https://spdx.org/licenses/ for list of possible licenses
# [possible values: any SPDX 3.7 short identifier (+ optional exception)].
#deny = []
# Uncomment the following line to change the lint level for licenses considered copyleft
# [possible values: "deny", "allow" or "warn"].
#copyleft = "warn"
# Uncomment the following line to approve or deny OSI-approved or FSF Free/Libre licenses
# [possible values: "both", "either", "osi-only", "fsf-only" or "neither"].
#allow-osi-fsf-free = "neither"
# Uncomment the following line to change the confidence threshold. The higher the value,
# the more closely the license text must be to the canonical license text of a valid
# SPDX license file.
# [possible values: any between 0.0 and 1.0].
#confidence-threshold = 0.8
[bans]
# This section is considered when running `cargo deny check ban`.
# More documentation about the 'bans' section can be found here:
# https://github.com/EmbarkStudios/cargo-deny#crate-bans-cargo-deny-check-ban
# Uncomment the following line to change what happens when multiple versions of the same
# crate are encountered
# [possible values: "deny", "warn" or "allow"].
#multiple-versions = "warn"
# Uncomment the following line to change the highlighting variant used to multiple versions
# of the same crate when creating a dotgraph of your crates dependencies
# [possible values: "lowest-version", "simplest-path" or "all"].
#highlight = "all"
# Uncomment the following line to allow specific crates.
#allow = []
# Uncomment the following line to deny specific crates.
#deny = []
# Uncomment the following line to skip specific crates.
#skip = []
# Uncomment the following line to skip specific crates (including different versions of the
# same crate down the dependency tree). By default, the depth is infinite, but you can also
# specify `depth = <integer>` to limit it.
#skip-tree = []
================================================
FILE: libeir_diagnostics/Cargo.toml
================================================
[package]
name = "libeir_diagnostics"
version = "0.1.0"
authors = ["Paul Schoenfelder <paulschoenfelder@gmail.com>", "Luke Imhoff <Kronic.Deth@gmail.com>"]
edition = "2018"
license = "MIT OR Apache-2.0"
[dependencies]
anyhow = "1.0"
thiserror = "1.0"
itertools = "0.8"
unicode-width = "0.1"
codespan = "0.9"
codespan-reporting = "0.9"
dashmap = "3.11"
[dev-dependencies]
pretty_assertions = "0.5"
================================================
FILE: libeir_diagnostics/src/codemap.rs
================================================
use std::ops::Range;
use std::path::PathBuf;
use std::sync::atomic::{AtomicU32, Ordering};
use std::sync::Arc;
use dashmap::DashMap;
use super::*;
#[derive(Debug)]
pub struct CodeMap {
files: DashMap<SourceId, Arc<SourceFile>>,
names: DashMap<FileName, SourceId>,
seen: DashMap<PathBuf, SourceId>,
next_file_id: AtomicU32,
}
impl CodeMap {
/// Creates an empty `CodeMap`.
pub fn new() -> Self {
Self {
files: DashMap::new(),
names: DashMap::new(),
seen: DashMap::new(),
next_file_id: AtomicU32::new(1),
}
}
/// Add a file to the map, returning the handle that can be used to
/// refer to it again.
pub fn add(&self, name: impl Into<FileName>, source: String) -> SourceId {
// De-duplicate real files on add; it _may_ be possible for concurrent
// adds to add the same file more than once, since we're working across
// two maps; but since DashMap uses read/write locks internally to lock
// buckets, the sequence of locks required here should prevent that from
// happening
//
// We don't de-duplicate virtual files, because the same name could be used
// for different content, and its unlikely that we'd be adding the same content
// over and over again with the same virtual file name
let name = name.into();
if let FileName::Real(ref path) = name {
let seen_ref = self
.seen
.entry(path.clone())
.or_insert_with(|| self.insert_file(name, source, None));
*seen_ref.value()
} else {
self.insert_file(name, source, None)
}
}
/// Add a file to the map with the given source span as a parent.
/// This will not deduplicate the file in the map.
pub fn add_child(
&self,
name: impl Into<FileName>,
source: String,
parent: SourceSpan,
) -> SourceId {
self.insert_file(name.into(), source, Some(parent))
}
fn insert_file(&self, name: FileName, source: String, parent: Option<SourceSpan>) -> SourceId {
let file_id = self.next_file_id();
let filename = name.clone();
self.files.insert(
file_id,
Arc::new(SourceFile::new(file_id, name.into(), source, parent)),
);
self.names.insert(filename, file_id);
file_id
}
/// Get the file corresponding to the given id.
pub fn get(&self, file_id: SourceId) -> Option<Arc<SourceFile>> {
if file_id == SourceId::UNKNOWN {
None
} else {
self.files.get(&file_id).map(|r| r.value().clone())
}
}
pub fn parent(&self, file_id: SourceId) -> Option<SourceSpan> {
self.get(file_id).and_then(|f| f.parent())
}
/// Get the file id corresponding to the given FileName
pub fn get_file_id(&self, filename: &FileName) -> Option<SourceId> {
self.names.get(filename).map(|id| *id)
}
/// Get the file corresponding to the given FileName
pub fn get_by_name(&self, filename: &FileName) -> Option<Arc<SourceFile>> {
self.get_file_id(filename).and_then(|id| self.get(id))
}
pub fn name(&self, file_id: SourceId) -> Option<FileName> {
self.get(file_id).map(|f| f.name().clone())
}
pub fn iter<'a>(&'a self) -> impl Iterator<Item = Arc<SourceFile>> + 'a {
self.files.iter().map(|r| r.value().clone())
}
pub fn line_span(
&self,
file_id: SourceId,
line_index: impl Into<LineIndex>,
) -> Option<Result<Span, LineIndexOutOfBoundsError>> {
let f = self.get(file_id)?;
Some(f.line_span(line_index.into()))
}
pub fn line_index(
&self,
file_id: SourceId,
byte_index: impl Into<ByteIndex>,
) -> Option<LineIndex> {
let f = self.get(file_id)?;
Some(f.line_index(byte_index.into()))
}
pub fn location(
&self,
file_id: SourceId,
byte_index: impl Into<ByteIndex>,
) -> Option<Result<Location, LocationError>> {
let f = self.get(file_id)?;
Some(f.location(byte_index.into()))
}
pub fn source_span(&self, file_id: SourceId) -> Option<SourceSpan> {
let f = self.get(file_id)?;
Some(f.source_span())
}
pub fn source_slice<'a>(
&'a self,
file_id: SourceId,
span: impl Into<Span>,
) -> Option<Result<&'a str, SpanOutOfBoundsError>> {
let f = self.get(file_id)?;
match f.source_slice(span.into()) {
Err(err) => Some(Err(err)),
Ok(slice) => unsafe { Some(Ok(std::mem::transmute::<&str, &'a str>(slice))) },
}
}
#[inline(always)]
fn next_file_id(&self) -> SourceId {
let id = self.next_file_id.fetch_add(1, Ordering::Relaxed);
SourceId::new(id)
}
}
impl Default for CodeMap {
fn default() -> Self {
Self::new()
}
}
impl<'a> Files<'a> for CodeMap {
type FileId = SourceId;
type Name = String;
type Source = &'a str;
fn name(&self, file_id: Self::FileId) -> Option<Self::Name> {
Some(format!("{}", self.get(file_id)?.name()))
}
fn source(&self, file_id: Self::FileId) -> Option<&'a str> {
use std::mem;
let f = self.get(file_id)?;
Some(unsafe { mem::transmute::<&str, &'a str>(f.source()) })
}
fn line_index(&self, file_id: Self::FileId, byte_index: usize) -> Option<usize> {
Some(self.line_index(file_id, byte_index as u32)?.to_usize())
}
fn line_range(&self, file_id: Self::FileId, line_index: usize) -> Option<Range<usize>> {
let span = self.line_span(file_id, line_index as u32)?.ok()?;
Some(span.start().to_usize()..span.end().to_usize())
}
}
================================================
FILE: libeir_diagnostics/src/filename.rs
================================================
//! Various source mapping utilities
use std::borrow::Cow;
use std::fmt;
use std::path::{Path, PathBuf};
#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum FileName {
/// A real file on disk
Real(PathBuf),
/// A synthetic file, eg. from the REPL
Virtual(Cow<'static, str>),
}
impl From<PathBuf> for FileName {
fn from(name: PathBuf) -> FileName {
FileName::real(name)
}
}
impl From<FileName> for PathBuf {
fn from(name: FileName) -> PathBuf {
match name {
FileName::Real(path) => path,
FileName::Virtual(Cow::Owned(owned)) => PathBuf::from(owned),
FileName::Virtual(Cow::Borrowed(borrowed)) => PathBuf::from(borrowed),
}
}
}
impl<'a> From<&'a FileName> for &'a Path {
fn from(name: &'a FileName) -> &'a Path {
match *name {
FileName::Real(ref path) => path,
FileName::Virtual(ref cow) => Path::new(cow.as_ref()),
}
}
}
impl<'a> From<&'a Path> for FileName {
fn from(name: &Path) -> FileName {
FileName::real(name)
}
}
impl From<String> for FileName {
fn from(name: String) -> FileName {
FileName::virtual_(name)
}
}
impl From<&'static str> for FileName {
fn from(name: &'static str) -> FileName {
FileName::virtual_(name)
}
}
impl AsRef<Path> for FileName {
fn as_ref(&self) -> &Path {
match *self {
FileName::Real(ref path) => path.as_ref(),
FileName::Virtual(ref cow) => Path::new(cow.as_ref()),
}
}
}
impl PartialEq<Path> for FileName {
fn eq(&self, other: &Path) -> bool {
self.as_ref() == other
}
}
impl PartialEq<PathBuf> for FileName {
fn eq(&self, other: &PathBuf) -> bool {
self.as_ref() == other.as_path()
}
}
impl FileName {
pub fn real<T: Into<PathBuf>>(name: T) -> FileName {
FileName::Real(name.into())
}
pub fn virtual_<T: Into<Cow<'static, str>>>(name: T) -> FileName {
FileName::Virtual(name.into())
}
pub fn to_string(&self) -> String {
match *self {
FileName::Real(ref path) => match path.to_str() {
None => path.to_string_lossy().into_owned(),
Some(s) => s.to_owned(),
},
FileName::Virtual(ref s) => s.clone().into_owned(),
}
}
}
impl fmt::Display for FileName {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match *self {
FileName::Real(ref path) => write!(fmt, "{}", path.display()),
FileName::Virtual(ref name) => write!(fmt, "<{}>", name),
}
}
}
================================================
FILE: libeir_diagnostics/src/index.rs
================================================
use std::num::NonZeroUsize;
use std::ops::{Add, AddAssign, Sub, SubAssign};
use codespan::{ByteIndex, ByteOffset, RawIndex, RawOffset};
use super::SourceId;
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SourceIndex(NonZeroUsize);
impl SourceIndex {
const INDEX_MASK: usize = u32::max_value() as usize;
const UNKNOWN_SRC_ID: usize = (SourceId::UNKNOWN_SOURCE_ID as usize) << 32;
pub const UNKNOWN: Self = Self(unsafe { NonZeroUsize::new_unchecked(Self::UNKNOWN_SRC_ID) });
#[inline]
pub fn new(source: SourceId, index: ByteIndex) -> Self {
let source = (source.get() as usize) << 32;
Self(NonZeroUsize::new(source | index.0 as usize).unwrap())
}
#[inline]
pub fn source_id(&self) -> SourceId {
let source_id_part = (self.0.get() >> 32) as u32;
if source_id_part == SourceId::UNKNOWN_SOURCE_ID {
SourceId::UNKNOWN
} else {
SourceId::new(source_id_part)
}
}
#[inline]
pub fn index(&self) -> ByteIndex {
ByteIndex((self.0.get() & Self::INDEX_MASK) as u32)
}
pub fn to_usize(&self) -> usize {
self.0.get()
}
}
impl Default for SourceIndex {
fn default() -> Self {
Self::UNKNOWN
}
}
impl Add<usize> for SourceIndex {
type Output = SourceIndex;
#[inline]
fn add(self, rhs: usize) -> Self {
if self == Self::UNKNOWN {
return Self::UNKNOWN;
}
let source = self.source_id();
let index = self.index();
let new_index = index.0 as RawOffset + rhs as RawOffset;
Self::new(source, ByteIndex(new_index as RawIndex))
}
}
impl Add<ByteOffset> for SourceIndex {
type Output = SourceIndex;
#[inline]
fn add(self, rhs: ByteOffset) -> Self {
if self == Self::UNKNOWN {
return Self::UNKNOWN;
}
let source = self.source_id();
let index = self.index();
let new_index = ByteIndex(index.0) + rhs;
Self::new(source, new_index)
}
}
impl AddAssign<usize> for SourceIndex {
#[inline]
fn add_assign(&mut self, rhs: usize) {
*self = *self + rhs;
}
}
impl AddAssign<ByteOffset> for SourceIndex {
#[inline]
fn add_assign(&mut self, rhs: ByteOffset) {
*self = *self + rhs;
}
}
impl Sub<usize> for SourceIndex {
type Output = SourceIndex;
#[inline]
fn sub(self, rhs: usize) -> Self {
if self == Self::UNKNOWN {
return Self::UNKNOWN;
}
let source = self.source_id();
let index = self.index();
let new_index = index.0 as RawOffset - rhs as RawOffset;
Self::new(source, ByteIndex(new_index as RawIndex))
}
}
impl SubAssign<usize> for SourceIndex {
#[inline]
fn sub_assign(&mut self, rhs: usize) {
*self = *self - rhs;
}
}
================================================
FILE: libeir_diagnostics/src/lib.rs
================================================
#![feature(crate_visibility_modifier)]
mod codemap;
mod filename;
mod index;
mod source;
mod span;
pub use codespan::{ByteIndex, ByteOffset};
pub use codespan::{ColumnIndex, ColumnNumber, ColumnOffset};
pub use codespan::{Index, Offset};
pub use codespan::{LineIndex, LineNumber, LineOffset};
pub use codespan::{LineIndexOutOfBoundsError, LocationError, SpanOutOfBoundsError};
pub use codespan::{Location, Span};
pub use codespan::{RawIndex, RawOffset};
pub use codespan_reporting::diagnostic::{LabelStyle, Severity};
pub use codespan_reporting::files::Files;
pub use codespan_reporting::term;
pub use self::codemap::CodeMap;
pub use self::filename::FileName;
pub use self::index::SourceIndex;
pub use self::source::{SourceFile, SourceId};
pub use self::span::SourceSpan;
pub type Diagnostic = codespan_reporting::diagnostic::Diagnostic<SourceId>;
pub type Label = codespan_reporting::diagnostic::Label<SourceId>;
pub trait ToDiagnostic {
fn to_diagnostic(&self) -> Diagnostic;
}
================================================
FILE: libeir_diagnostics/src/source.rs
================================================
use std::convert::Into;
use std::num::NonZeroU32;
use std::ops::Range;
use super::*;
/// A handle that points to a file in the database.
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SourceId(crate NonZeroU32);
impl SourceId {
crate const UNKNOWN_SOURCE_ID: u32 = u32::max_value();
pub const UNKNOWN: Self = Self(unsafe { NonZeroU32::new_unchecked(Self::UNKNOWN_SOURCE_ID) });
crate fn new(index: u32) -> Self {
assert!(index > 0);
assert!(index < Self::UNKNOWN_SOURCE_ID);
Self(NonZeroU32::new(index).unwrap())
}
#[inline]
crate fn get(self) -> u32 {
self.0.get()
}
}
/// The representation of a source file in the database.
#[derive(Debug, Clone)]
pub struct SourceFile {
id: SourceId,
name: FileName,
source: String,
line_starts: Vec<ByteIndex>,
parent: Option<SourceSpan>,
}
impl SourceFile {
crate fn new(id: SourceId, name: FileName, source: String, parent: Option<SourceSpan>) -> Self {
let line_starts = codespan_reporting::files::line_starts(source.as_str())
.map(|i| ByteIndex::from(i as u32))
.collect();
Self {
id,
name,
source,
line_starts,
parent,
}
}
pub fn name(&self) -> &FileName {
&self.name
}
pub fn id(&self) -> SourceId {
self.id
}
pub fn parent(&self) -> Option<SourceSpan> {
self.parent
}
pub fn line_start(
&self,
line_index: LineIndex,
) -> Result<ByteIndex, LineIndexOutOfBoundsError> {
use std::cmp::Ordering;
match line_index.cmp(&self.last_line_index()) {
Ordering::Less => Ok(self.line_starts[line_index.to_usize()]),
Ordering::Equal => Ok(self.source_span().end_index()),
Ordering::Greater => Err(LineIndexOutOfBoundsError {
given: line_index,
max: self.last_line_index(),
}),
}
}
pub fn last_line_index(&self) -> LineIndex {
LineIndex::from(self.line_starts.len() as RawIndex)
}
pub fn line_span(&self, line_index: LineIndex) -> Result<Span, LineIndexOutOfBoundsError> {
let line_start = self.line_start(line_index)?;
let next_line_start = self.line_start(line_index + LineOffset::from(1))?;
Ok(Span::new(line_start, next_line_start))
}
pub fn line_index(&self, byte_index: ByteIndex) -> LineIndex {
match self.line_starts.binary_search(&byte_index) {
// Found the start of a line
Ok(line) => LineIndex::from(line as u32),
Err(next_line) => LineIndex::from(next_line as u32 - 1),
}
}
pub fn location(&self, byte_index: ByteIndex) -> Result<Location, LocationError> {
let line_index = self.line_index(byte_index);
let line_start_index =
self.line_start(line_index)
.map_err(|_| LocationError::OutOfBounds {
given: byte_index,
span: self.source_span().as_span(),
})?;
let line_src = self
.source
.as_str()
.get(line_start_index.to_usize()..byte_index.to_usize())
.ok_or_else(|| {
let given = byte_index;
if given >= self.source_span().end_index() {
let span = self.source_span();
LocationError::OutOfBounds {
given,
span: span.as_span(),
}
} else {
LocationError::InvalidCharBoundary { given }
}
})?;
Ok(Location {
line: line_index,
column: ColumnIndex::from(line_src.chars().count() as u32),
})
}
#[inline(always)]
pub fn source(&self) -> &str {
self.source.as_str()
}
pub fn source_span(&self) -> SourceSpan {
SourceSpan {
source_id: self.id,
start: ByteIndex(0),
end: ByteIndex(self.source.len() as u32),
}
}
pub fn source_slice(
&self,
span: impl Into<Range<usize>>,
) -> Result<&str, SpanOutOfBoundsError> {
let span = span.into();
let start = span.start;
let end = span.end;
self.source().get(start..end).ok_or_else(|| {
let given = Span::new(start as u32, end as u32);
let span = Span::from_str(self.source());
SpanOutOfBoundsError { given, span }
})
}
}
================================================
FILE: libeir_diagnostics/src/span.rs
================================================
use std::ops::Range;
use codespan::{ByteIndex, ByteOffset, Span};
use super::{CodeMap, SourceId, SourceIndex};
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SourceSpan {
crate source_id: SourceId,
crate start: ByteIndex,
crate end: ByteIndex,
}
impl SourceSpan {
pub const UNKNOWN: Self = Self {
source_id: SourceId::UNKNOWN,
start: ByteIndex(0),
end: ByteIndex(0),
};
#[inline]
pub fn new(start: SourceIndex, end: SourceIndex) -> Self {
let source_id = start.source_id();
assert_eq!(
source_id,
end.source_id(),
"source spans cannot start and end in different files!"
);
let start = start.index();
let end = end.index();
Self {
source_id,
start,
end,
}
}
pub fn new_align<F>(
start: SourceIndex,
end: SourceIndex,
get_codemap: &dyn Fn(&mut dyn FnOnce(&CodeMap)),
) -> SourceSpan {
let start_source = start.source_id();
let end_source = end.source_id();
if start_source == end_source {
Self::new(start, end)
} else {
let mut result = None;
get_codemap(&mut |codemap: &CodeMap| {
let mut idx = start_source;
loop {
if let Some(parent) = codemap.parent(idx) {
if idx == end_source {
result = Some(Self::new(parent.start(), end));
return;
}
idx = parent.source_id();
} else {
break;
}
}
let mut idx = end_source;
loop {
if let Some(parent) = codemap.parent(idx) {
if idx == start_source {
result = Some(Self::new(start, parent.end()));
return;
}
idx = parent.source_id();
} else {
break;
}
}
});
result.expect("source spans cannot be aligned!")
}
}
#[inline(always)]
pub fn source_id(&self) -> SourceId {
self.source_id
}
#[inline(always)]
pub fn start(&self) -> SourceIndex {
SourceIndex::new(self.source_id, self.start)
}
#[inline(always)]
pub fn start_index(&self) -> ByteIndex {
self.start
}
pub fn shrink_front(mut self, offset: ByteOffset) -> Self {
self.start += offset;
self
}
#[inline(always)]
pub fn end(&self) -> SourceIndex {
SourceIndex::new(self.source_id, self.end)
}
#[inline(always)]
pub fn end_index(&self) -> ByteIndex {
self.end
}
pub fn as_span(&self) -> Span {
Span::new(self.start, self.end)
}
}
impl From<SourceSpan> for Range<usize> {
fn from(span: SourceSpan) -> Range<usize> {
span.start.into()..span.end.into()
}
}
impl From<SourceSpan> for Range<SourceIndex> {
fn from(span: SourceSpan) -> Range<SourceIndex> {
let start = SourceIndex::new(span.source_id, span.start);
let end = SourceIndex::new(span.source_id, span.end);
start..end
}
}
================================================
FILE: libeir_frontend/Cargo.toml
================================================
[package]
name = "libeir_frontend"
version = "0.1.0"
authors = ["Hans Elias B. Josephsen <me@hansihe.com>"]
edition = "2018"
license = "MIT OR Apache-2.0"
[dependencies]
libeir_ir = { path = "../libeir_ir" }
libeir_syntax_erl = { path = "../libeir_syntax_erl" }
libeir_util_parse = { path = "../util/libeir_util_parse" }
libeir_diagnostics = { path = "../libeir_diagnostics" }
libeir_util_parse_listing = { path = "../util/libeir_util_parse_listing" }
[features]
default = ["frontend_erlang", "frontend_abstr_erlang", "frontend_eir"]
frontend_erlang = []
frontend_abstr_erlang = []
frontend_eir = []
================================================
FILE: libeir_frontend/README.md
================================================
# libeir_frontend
Wrapper crate for all the different frontends in this project.
Currently includes:
* eir frontend
* erlang frontend
* abstract erlang frontend
================================================
FILE: libeir_frontend/src/abstr_erlang.rs
================================================
use std::path::Path;
use std::sync::Arc;
use libeir_diagnostics::*;
use libeir_ir::Module;
use libeir_syntax_erl::{lower_abstr, lower_module, LowerError};
use libeir_util_parse::{error_tee, Parse, Parser};
use libeir_util_parse_listing::{ast::Root, parser::ParseError};
use super::{Frontend, FrontendErrorReceiver};
pub enum Error {
Parse(ParseError),
Lower(LowerError),
}
impl ToDiagnostic for Error {
fn to_diagnostic(&self) -> Diagnostic {
match self {
Error::Parse(err) => err.to_diagnostic(),
Error::Lower(err) => err.to_diagnostic(),
}
}
}
impl From<ParseError> for Error {
fn from(err: ParseError) -> Error {
Error::Parse(err)
}
}
impl From<LowerError> for Error {
fn from(err: LowerError) -> Error {
Error::Lower(err)
}
}
pub struct AbstrErlangFrontend {
parser: Parser<()>,
}
impl AbstrErlangFrontend {
pub fn new(codemap: Arc<CodeMap>) -> Self {
Self {
parser: Parser::new((), codemap),
}
}
}
impl Frontend for AbstrErlangFrontend {
type Error = Error;
fn parse_source<'a>(
&self,
errors: &'a mut FrontendErrorReceiver<'a, Self::Error>,
source: Arc<SourceFile>,
) -> Result<Module, ()> {
error_tee(errors, |mut errors| {
let root = self
.parser
.parse::<Root>(&mut errors.make_into_adapter(), source)?;
let ast = lower_abstr(&root);
let eir = lower_module(
&mut errors.make_into_adapter(),
self.parser.codemap.clone(),
&ast,
)?;
Ok(eir)
})
}
fn parse_string<'a>(
&self,
errors: &'a mut FrontendErrorReceiver<'a, Self::Error>,
source: &str,
) -> Result<Module, ()> {
let id = self.parser.codemap.add("nofile", source.to_string());
let file = self.parser.codemap.get(id).unwrap();
self.parse_source(errors, file)
}
fn parse_file<'a>(
&self,
errors: &'a mut FrontendErrorReceiver<'a, Self::Error>,
path: &Path,
) -> Result<Module, ()> {
match std::fs::read_to_string(path) {
Err(err) => {
errors.error(<Root as Parse<Root>>::root_file_error(err, path.to_owned()).into());
Err(())
}
Ok(content) => {
let id = self.parser.codemap.add(path, content);
let file = self.parser.codemap.get(id).unwrap();
self.parse_source(errors, file)
}
}
}
}
================================================
FILE: libeir_frontend/src/eir.rs
================================================
use std::path::Path;
use std::sync::Arc;
use libeir_diagnostics::*;
use libeir_ir::{
text::{ast::Module as ModuleAst, parser::ParserError, LowerError},
Module,
};
use libeir_util_parse::{error_tee, Parse, Parser};
use super::{Frontend, FrontendErrorReceiver};
pub enum Error {
Parser(ParserError),
Lower(LowerError),
}
impl ToDiagnostic for Error {
fn to_diagnostic(&self) -> Diagnostic {
match self {
Error::Parser(err) => err.to_diagnostic(),
Error::Lower(err) => err.to_diagnostic(),
}
}
}
impl From<ParserError> for Error {
fn from(err: ParserError) -> Self {
Error::Parser(err)
}
}
impl From<LowerError> for Error {
fn from(err: LowerError) -> Self {
Error::Lower(err)
}
}
pub struct EirFrontend {
parser: Parser<()>,
}
impl EirFrontend {
pub fn new(codemap: Arc<CodeMap>) -> Self {
Self {
parser: Parser::new((), codemap),
}
}
}
impl Frontend for EirFrontend {
type Error = Error;
fn parse_source<'a>(
&self,
errors: &'a mut FrontendErrorReceiver<'a, Self::Error>,
source: Arc<SourceFile>,
) -> Result<Module, ()> {
error_tee(errors, |mut errors| {
let ast = self
.parser
.parse::<ModuleAst>(&mut errors.make_into_adapter(), source)?;
let eir = ast.lower(&mut errors.make_into_adapter())?;
Ok(eir)
})
}
fn parse_string<'a>(
&self,
errors: &'a mut FrontendErrorReceiver<'a, Self::Error>,
source: &str,
) -> Result<Module, ()> {
let id = self.parser.codemap.add("nofile", source.to_owned());
let file = self.parser.codemap.get(id).unwrap();
self.parse_source(errors, file)
}
fn parse_file<'a>(
&self,
errors: &'a mut FrontendErrorReceiver<'a, Self::Error>,
path: &Path,
) -> Result<Module, ()> {
match std::fs::read_to_string(path) {
Err(err) => {
errors.error(<ModuleAst as Parse<ModuleAst>>::root_file_error(err, path.to_owned()).into());
Err(())
}
Ok(content) => {
let id = self.parser.codemap.add(path, content);
let file = self.parser.codemap.get(id).unwrap();
self.parse_source(errors, file)
}
}
}
}
================================================
FILE: libeir_frontend/src/erlang.rs
================================================
use std::path::Path;
use std::sync::Arc;
use libeir_diagnostics::*;
use libeir_ir::Module;
use libeir_syntax_erl::{
ast::Module as ModuleAst, lower_module, LowerError, ParseConfig, ParserError,
};
use libeir_util_parse::{error_tee, Parse, Parser};
use super::{Frontend, FrontendErrorReceiver};
pub enum Error {
Parser(ParserError),
Lower(LowerError),
}
impl ToDiagnostic for Error {
fn to_diagnostic(&self) -> Diagnostic {
match self {
Error::Parser(err) => err.to_diagnostic(),
Error::Lower(err) => err.to_diagnostic(),
}
}
}
impl Into<Error> for ParserError {
fn into(self) -> Error {
Error::Parser(self)
}
}
impl Into<Error> for LowerError {
fn into(self) -> Error {
Error::Lower(self)
}
}
pub struct ErlangFrontend {
parser: Parser<ParseConfig>,
}
impl ErlangFrontend {
pub fn new(config: ParseConfig, codemap: Arc<CodeMap>) -> Self {
Self {
parser: Parser::new(config, codemap),
}
}
}
impl Frontend for ErlangFrontend {
type Error = Error;
fn parse_source<'a>(
&self,
errors: &'a mut FrontendErrorReceiver<'a, Self::Error>,
source: Arc<SourceFile>,
) -> Result<Module, ()> {
error_tee(errors, |mut errors| {
let ast = self
.parser
.parse::<ModuleAst>(&mut errors.make_into_adapter(), source)?;
let eir = lower_module(
&mut errors.make_into_adapter(),
self.parser.codemap.clone(),
&ast,
)?;
Ok(eir)
})
}
fn parse_string<'a>(
&self,
errors: &'a mut FrontendErrorReceiver<'a, Self::Error>,
source: &str,
) -> Result<Module, ()> {
let id = self.parser.codemap.add("nofile", source.to_owned());
let file = self.parser.codemap.get(id).unwrap();
self.parse_source(errors, file)
}
fn parse_file<'a>(
&self,
errors: &'a mut FrontendErrorReceiver<'a, Self::Error>,
path: &Path,
) -> Result<Module, ()> {
match std::fs::read_to_string(path) {
Err(err) => {
errors.error(<ModuleAst as Parse<ModuleAst>>::root_file_error(err, path.to_owned()).into());
Err(())
}
Ok(content) => {
let id = self.parser.codemap.add(path, content);
let file = self.parser.codemap.get(id).unwrap();
self.parse_source(errors, file)
}
}
}
}
================================================
FILE: libeir_frontend/src/lib.rs
================================================
#[cfg(feature = "frontend_abstr_erlang")]
pub mod abstr_erlang;
#[cfg(feature = "frontend_eir")]
pub mod eir;
#[cfg(feature = "frontend_erlang")]
pub mod erlang;
use std::path::Path;
use std::sync::Arc;
use libeir_diagnostics::{Diagnostic, SourceFile, ToDiagnostic};
use libeir_ir::Module;
use libeir_util_parse::ErrorReceiver;
pub type FrontendErrorReceiver<'a, E> = dyn ErrorReceiver<E = E, W = E> + 'a;
pub trait DynFrontend {
fn parse_source_dyn<'a>(
&self,
source: Arc<SourceFile>,
) -> (Result<Module, ()>, Vec<Diagnostic>);
fn parse_string_dyn<'a>(&self, source: &str) -> (Result<Module, ()>, Vec<Diagnostic>);
fn parse_file_dyn<'a>(&self, source: &Path) -> (Result<Module, ()>, Vec<Diagnostic>);
}
pub trait Frontend {
type Error;
fn parse_source<'a>(
&self,
errors: &'a mut FrontendErrorReceiver<'a, Self::Error>,
source: Arc<SourceFile>,
) -> Result<Module, ()>;
fn parse_string<'a>(
&self,
errors: &'a mut FrontendErrorReceiver<'a, Self::Error>,
source: &str,
) -> Result<Module, ()>;
fn parse_file<'a>(
&self,
errors: &'a mut FrontendErrorReceiver<'a, Self::Error>,
source: &Path,
) -> Result<Module, ()>;
}
impl<F, E> DynFrontend for F
where
F: Frontend<Error = E>,
E: ToDiagnostic,
{
fn parse_source_dyn<'a>(
&self,
source: Arc<SourceFile>,
) -> (Result<Module, ()>, Vec<Diagnostic>) {
let mut errors = libeir_util_parse::Errors::new();
let res = self.parse_source(&mut errors, source);
(res, errors.iter_diagnostics().collect())
}
fn parse_string_dyn<'a>(&self, source: &str) -> (Result<Module, ()>, Vec<Diagnostic>) {
let mut errors = libeir_util_parse::Errors::new();
let res = self.parse_string(&mut errors, source);
(res, errors.iter_diagnostics().collect())
}
fn parse_file_dyn<'a>(&self, source: &Path) -> (Result<Module, ()>, Vec<Diagnostic>) {
let mut errors = libeir_util_parse::Errors::new();
let res = self.parse_file(&mut errors, source);
(res, errors.iter_diagnostics().collect())
}
}
pub enum AnyFrontend {
#[cfg(feature = "frontend_erlang")]
Erlang(erlang::ErlangFrontend),
#[cfg(feature = "frontend_abstr_erlang")]
AbstrErlang(abstr_erlang::AbstrErlangFrontend),
#[cfg(feature = "frontend_eir")]
Eir(eir::EirFrontend),
}
impl DynFrontend for AnyFrontend {
fn parse_source_dyn<'a>(
&self,
source: Arc<SourceFile>,
) -> (Result<Module, ()>, Vec<Diagnostic>) {
match self {
#[cfg(feature = "frontend_erlang")]
AnyFrontend::Erlang(front) => front.parse_source_dyn(source),
#[cfg(feature = "frontend_abstr_erlang")]
AnyFrontend::AbstrErlang(front) => front.parse_source_dyn(source),
#[cfg(feature = "frontend_eir")]
AnyFrontend::Eir(front) => front.parse_source_dyn(source),
}
}
fn parse_string_dyn<'a>(&self, source: &str) -> (Result<Module, ()>, Vec<Diagnostic>) {
match self {
#[cfg(feature = "frontend_erlang")]
AnyFrontend::Erlang(front) => front.parse_string_dyn(source),
#[cfg(feature = "frontend_abstr_erlang")]
AnyFrontend::AbstrErlang(front) => front.parse_string_dyn(source),
#[cfg(feature = "frontend_eir")]
AnyFrontend::Eir(front) => front.parse_string_dyn(source),
}
}
fn parse_file_dyn<'a>(&self, source: &Path) -> (Result<Module, ()>, Vec<Diagnostic>) {
match self {
#[cfg(feature = "frontend_erlang")]
AnyFrontend::Erlang(front) => front.parse_file_dyn(source),
#[cfg(feature = "frontend_abstr_erlang")]
AnyFrontend::AbstrErlang(front) => front.parse_file_dyn(source),
#[cfg(feature = "frontend_eir")]
AnyFrontend::Eir(front) => front.parse_file_dyn(source),
}
}
}
impl From<erlang::ErlangFrontend> for AnyFrontend {
fn from(f: erlang::ErlangFrontend) -> Self {
AnyFrontend::Erlang(f)
}
}
impl From<abstr_erlang::AbstrErlangFrontend> for AnyFrontend {
fn from(f: abstr_erlang::AbstrErlangFrontend) -> Self {
AnyFrontend::AbstrErlang(f)
}
}
impl From<eir::EirFrontend> for AnyFrontend {
fn from(f: eir::EirFrontend) -> Self {
AnyFrontend::Eir(f)
}
}
================================================
FILE: libeir_intern/Cargo.toml
================================================
[package]
name = "libeir_intern"
version = "0.1.0"
authors = ["Hans Elias B. Josephsen <me@hansihe.com>"]
edition = "2018"
license = "MIT OR Apache-2.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
libeir_diagnostics = { path = "../libeir_diagnostics" }
rustc-hash = "1.0"
lazy_static = "1.2"
================================================
FILE: libeir_intern/src/arena.rs
================================================
#![allow(unused)]
//! NOTE: Modified version of impl in rustc
//!
//! The arena, a fast but limited type of allocator.
//!
//! Arenas are a type of allocator that destroy the objects within, all at
//! once, once the arena itself is destroyed. They do not support deallocation
//! of individual objects while the arena itself is still alive. The benefit
//! of an arena is very fast allocation; just a pointer bump.
//!
//! This crate implements `TypedArena`, a simple arena that can only hold
//! objects of a single type.
use core::cell::{Cell, RefCell};
use core::cmp;
use core::intrinsics;
use core::marker::{PhantomData, Send};
use core::mem;
use core::ptr;
use core::slice;
use alloc::raw_vec::RawVec;
use alloc::vec::Vec;
/// An arena that can hold objects of only one type.
pub struct TypedArena<T> {
/// A pointer to the next object to be allocated.
ptr: Cell<*mut T>,
/// A pointer to the end of the allocated area. When this pointer is
/// reached, a new chunk is allocated.
end: Cell<*mut T>,
/// A vector of arena chunks.
chunks: RefCell<Vec<TypedArenaChunk<T>>>,
/// Marker indicating that dropping the arena causes its owned
/// instances of `T` to be dropped.
_own: PhantomData<T>,
}
struct TypedArenaChunk<T> {
/// The raw storage for the arena chunk.
storage: RawVec<T>,
}
impl<T> TypedArenaChunk<T> {
#[inline]
unsafe fn new(capacity: usize) -> TypedArenaChunk<T> {
TypedArenaChunk {
storage: RawVec::with_capacity(capacity),
}
}
/// Destroys this arena chunk.
#[inline]
unsafe fn destroy(&mut self, len: usize) {
// The branch on needs_drop() is an -O1 performance optimization.
// Without the branch, dropping TypedArena<u8> takes linear time.
if mem::needs_drop::<T>() {
let mut start = self.start();
// Destroy all allocated objects.
for _ in 0..len {
ptr::drop_in_place(start);
start = start.offset(1);
}
}
}
// Returns a pointer to the first allocated object.
#[inline]
fn start(&self) -> *mut T {
self.storage.ptr()
}
// Returns a pointer to the end of the allocated space.
#[inline]
fn end(&self) -> *mut T {
unsafe {
if mem::size_of::<T>() == 0 {
// A pointer as large as possible for zero-sized elements.
!0 as *mut T
} else {
self.start().add(self.storage.capacity())
}
}
}
}
#[cfg(not(target_arch = "wasm32"))]
const PAGE: usize = 4 * 1024;
#[cfg(target_arch = "wasm32")]
const PAGE: usize = 64 * 1024;
impl<T> Default for TypedArena<T> {
/// Creates a new `TypedArena`.
fn default() -> TypedArena<T> {
TypedArena {
// We set both `ptr` and `end` to 0 so that the first call to
// alloc() will trigger a grow().
ptr: Cell::new(0 as *mut T),
end: Cell::new(0 as *mut T),
chunks: RefCell::new(Vec::new()),
_own: PhantomData,
}
}
}
impl<T> TypedArena<T> {
pub fn in_arena(&self, ptr: *const T) -> bool {
let ptr = ptr as *const T as *mut T;
self.chunks
.borrow()
.iter()
.any(|chunk| chunk.start() <= ptr && ptr < chunk.end())
}
/// Allocates an object in the `TypedArena`, returning a reference to it.
#[inline]
pub fn alloc(&self, object: T) -> &mut T {
if self.ptr == self.end {
self.grow(1)
}
unsafe {
if mem::size_of::<T>() == 0 {
self.ptr
.set(intrinsics::arith_offset(self.ptr.get() as *mut u8, 1) as *mut T);
let ptr = mem::align_of::<T>() as *mut T;
// Don't drop the object. This `write` is equivalent to `forget`.
ptr::write(ptr, object);
&mut *ptr
} else {
let ptr = self.ptr.get();
// Advance the pointer.
self.ptr.set(self.ptr.get().offset(1));
// Write into uninitialized memory.
ptr::write(ptr, object);
&mut *ptr
}
}
}
/// Allocates a slice of objects that are copied into the `TypedArena`, returning a mutable
/// reference to it. Will panic if passed a zero-sized types.
///
/// Panics:
///
/// - Zero-sized types
/// - Zero-length slices
#[inline]
pub fn alloc_slice(&self, slice: &[T]) -> &mut [T]
where
T: Copy,
{
assert!(mem::size_of::<T>() != 0);
assert!(slice.len() != 0);
let available_capacity_bytes = self.end.get() as usize - self.ptr.get() as usize;
let at_least_bytes = slice.len() * mem::size_of::<T>();
if available_capacity_bytes < at_least_bytes {
self.grow(slice.len());
}
unsafe {
let start_ptr = self.ptr.get();
let arena_slice = slice::from_raw_parts_mut(start_ptr, slice.len());
self.ptr.set(start_ptr.add(arena_slice.len()));
arena_slice.copy_from_slice(slice);
arena_slice
}
}
/// Grows the arena.
#[inline(never)]
#[cold]
fn grow(&self, n: usize) {
unsafe {
let mut chunks = self.chunks.borrow_mut();
let (chunk, mut new_capacity);
if let Some(last_chunk) = chunks.last_mut() {
let used_bytes = self.ptr.get() as usize - last_chunk.start() as usize;
let currently_used_cap = used_bytes / mem::size_of::<T>();
new_capacity = last_chunk.storage.capacity();
loop {
new_capacity = new_capacity.checked_mul(2).unwrap();
if new_capacity >= currently_used_cap + n {
break;
}
}
} else {
let elem_size = cmp::max(1, mem::size_of::<T>());
new_capacity = cmp::max(n, PAGE / elem_size);
}
chunk = TypedArenaChunk::<T>::new(new_capacity);
self.ptr.set(chunk.start());
self.end.set(chunk.end());
chunks.push(chunk);
}
}
/// Clears the arena. Deallocates all but the longest chunk which may be reused.
pub fn clear(&mut self) {
unsafe {
// Clear the last chunk, which is partially filled.
let mut chunks_borrow = self.chunks.borrow_mut();
if let Some(mut last_chunk) = chunks_borrow.last_mut() {
self.clear_last_chunk(&mut last_chunk);
let len = chunks_borrow.len();
// If `T` is ZST, code below has no effect.
for mut chunk in chunks_borrow.drain(..len - 1) {
let cap = chunk.storage.capacity();
chunk.destroy(cap);
}
}
}
}
// Drops the contents of the last chunk. The last chunk is partially empty, unlike all other
// chunks.
fn clear_last_chunk(&self, last_chunk: &mut TypedArenaChunk<T>) {
// Determine how much was filled.
let start = last_chunk.start() as usize;
// We obtain the value of the pointer to the first uninitialized element.
let end = self.ptr.get() as usize;
// We then calculate the number of elements to be dropped in the last chunk,
// which is the filled area's length.
let diff = if mem::size_of::<T>() == 0 {
// `T` is ZST. It can't have a drop flag, so the value here doesn't matter. We get
// the number of zero-sized values in the last and only chunk, just out of caution.
// Recall that `end` was incremented for each allocated value.
end - start
} else {
(end - start) / mem::size_of::<T>()
};
// Pass that to the `destroy` method.
unsafe {
last_chunk.destroy(diff);
}
// Reset the chunk.
self.ptr.set(last_chunk.start());
}
}
unsafe impl<#[may_dangle] T> Drop for TypedArena<T> {
fn drop(&mut self) {
unsafe {
// Determine how much was filled.
let mut chunks_borrow = self.chunks.borrow_mut();
if let Some(mut last_chunk) = chunks_borrow.pop() {
// Drop the contents of the last chunk.
self.clear_last_chunk(&mut last_chunk);
// The last chunk will be dropped. Destroy all other chunks.
for chunk in chunks_borrow.iter_mut() {
let cap = chunk.storage.capacity();
chunk.destroy(cap);
}
}
// RawVec handles deallocation of `last_chunk` and `self.chunks`.
}
}
}
unsafe impl<T: Send> Send for TypedArena<T> {}
pub struct DroplessArena {
/// A pointer to the next object to be allocated.
ptr: Cell<*mut u8>,
/// A pointer to the end of the allocated area. When this pointer is
/// reached, a new chunk is allocated.
end: Cell<*mut u8>,
/// A vector of arena chunks.
chunks: RefCell<Vec<TypedArenaChunk<u8>>>,
}
unsafe impl Send for DroplessArena {}
impl Default for DroplessArena {
#[inline]
fn default() -> DroplessArena {
DroplessArena {
ptr: Cell::new(0 as *mut u8),
end: Cell::new(0 as *mut u8),
chunks: Default::default(),
}
}
}
impl DroplessArena {
pub fn in_arena<T: ?Sized>(&self, ptr: *const T) -> bool {
let ptr = ptr as *const u8 as *mut u8;
self.chunks
.borrow()
.iter()
.any(|chunk| chunk.start() <= ptr && ptr < chunk.end())
}
#[inline]
fn align(&self, align: usize) {
let final_address = ((self.ptr.get() as usize) + align - 1) & !(align - 1);
self.ptr.set(final_address as *mut u8);
assert!(self.ptr <= self.end);
}
#[inline(never)]
#[cold]
fn grow(&self, needed_bytes: usize) {
unsafe {
let mut chunks = self.chunks.borrow_mut();
let (chunk, mut new_capacity);
if let Some(last_chunk) = chunks.last_mut() {
let used_bytes = self.ptr.get() as usize - last_chunk.start() as usize;
new_capacity = last_chunk.storage.capacity();
loop {
new_capacity = new_capacity.checked_mul(2).unwrap();
if new_capacity >= used_bytes + needed_bytes {
break;
}
}
} else {
new_capacity = cmp::max(needed_bytes, PAGE);
}
chunk = TypedArenaChunk::<u8>::new(new_capacity);
self.ptr.set(chunk.start());
self.end.set(chunk.end());
chunks.push(chunk);
}
}
#[inline]
pub unsafe fn alloc_raw(&self, bytes: usize, align: usize) -> *mut u8 {
assert!(bytes != 0);
self.align(align);
let future_end = intrinsics::arith_offset(self.ptr.get(), bytes as isize);
if (future_end as *mut u8) >= self.end.get() {
self.grow(bytes);
}
let ptr = self.ptr.get();
// Set the pointer past ourselves
self.ptr
.set(intrinsics::arith_offset(self.ptr.get(), bytes as isize) as *mut u8);
ptr
}
#[inline]
pub fn alloc_copy<T>(&self, object: T) -> &mut T {
assert!(!mem::needs_drop::<T>());
unsafe {
let mem = self.alloc_raw(mem::size_of::<T>(), mem::align_of::<T>()) as *mut T;
// Write into uninitialized memory.
ptr::write(mem, object);
&mut *mem
}
}
/// Allocates a slice of objects that are copied into the `DroplessArena`, returning a mutable
/// reference to it. Will panic if passed a zero-sized type.
///
/// Panics:
///
/// - Zero-sized types
/// - Zero-length slices
#[inline]
pub fn alloc_slice<T>(&self, slice: &[T]) -> &mut [T]
where
T: Copy,
{
assert!(!mem::needs_drop::<T>());
assert!(mem::size_of::<T>() != 0);
assert!(!slice.is_empty());
unsafe {
let mem = self.alloc_raw(slice.len() * mem::size_of::<T>(), mem::align_of::<T>())
as *mut _ as *mut T;
let arena_slice = slice::from_raw_parts_mut(mem, slice.len());
arena_slice.copy_from_slice(slice);
arena_slice
}
}
}
#[cfg(test)]
mod tests {
use super::TypedArena;
use alloc::boxed::Box;
use alloc::string::String;
use alloc::vec;
use alloc::vec::Vec;
use core::cell::Cell;
use core::sync::atomic::{AtomicUsize, Ordering};
use test::Bencher;
#[allow(dead_code)]
#[derive(Debug, Eq, PartialEq)]
struct Point {
x: i32,
y: i32,
z: i32,
}
#[test]
pub fn test_unused() {
let arena: TypedArena<Point> = TypedArena::default();
assert!(arena.chunks.borrow().is_empty());
}
#[test]
fn test_arena_alloc_nested() {
struct Inner {
value: u8,
}
struct Outer<'a> {
inner: &'a Inner,
}
enum EI<'e> {
I(Inner),
O(Outer<'e>),
}
struct Wrap<'a>(TypedArena<EI<'a>>);
impl<'a> Wrap<'a> {
fn alloc_inner<F: Fn() -> Inner>(&self, f: F) -> &Inner {
let r: &EI = self.0.alloc(EI::I(f()));
if let &EI::I(ref i) = r {
i
} else {
panic!("mismatch");
}
}
fn alloc_outer<F: Fn() -> Outer<'a>>(&self, f: F) -> &Outer {
let r: &EI = self.0.alloc(EI::O(f()));
if let &EI::O(ref o) = r {
o
} else {
panic!("mismatch");
}
}
}
let arena = Wrap(TypedArena::default());
let result = arena.alloc_outer(|| Outer {
inner: arena.alloc_inner(|| Inner { value: 10 }),
});
assert_eq!(result.inner.value, 10);
}
#[test]
pub fn test_copy() {
let arena = TypedArena::default();
for _ in 0..100000 {
arena.alloc(Point { x: 1, y: 2, z: 3 });
}
}
#[bench]
pub fn bench_copy(b: &mut Bencher) {
let arena = TypedArena::default();
b.iter(|| arena.alloc(Point { x: 1, y: 2, z: 3 }))
}
#[bench]
pub fn bench_copy_nonarena(b: &mut Bencher) {
b.iter(|| {
let _: Box<_> = Box::new(Point { x: 1, y: 2, z: 3 });
})
}
#[allow(dead_code)]
struct Noncopy {
string: String,
array: Vec<i32>,
}
#[test]
pub fn test_noncopy() {
let arena = TypedArena::default();
for _ in 0..100000 {
arena.alloc(Noncopy {
string: String::from("hello world"),
array: vec![1, 2, 3, 4, 5],
});
}
}
#[test]
pub fn test_typed_arena_zero_sized() {
let arena = TypedArena::default();
for _ in 0..100000 {
arena.alloc(());
}
}
#[test]
pub fn test_typed_arena_clear() {
let mut arena = TypedArena::default();
for _ in 0..10 {
arena.clear();
for _ in 0..10000 {
arena.alloc(Point { x: 1, y: 2, z: 3 });
}
}
}
#[bench]
pub fn bench_typed_arena_clear(b: &mut Bencher) {
let mut arena = TypedArena::default();
b.iter(|| {
arena.alloc(Point { x: 1, y: 2, z: 3 });
arena.clear();
})
}
// Drop tests
struct DropCounter<'a> {
count: &'a Cell<u32>,
}
impl<'a> Drop for DropCounter<'a> {
fn drop(&mut self) {
self.count.set(self.count.get() + 1);
}
}
#[test]
fn test_typed_arena_drop_count() {
let counter = Cell::new(0);
{
let arena: TypedArena<DropCounter> = TypedArena::default();
for _ in 0..100 {
// Allocate something with drop glue to make sure it doesn't leak.
arena.alloc(DropCounter { count: &counter });
}
};
assert_eq!(counter.get(), 100);
}
#[test]
fn test_typed_arena_drop_on_clear() {
let counter = Cell::new(0);
let mut arena: TypedArena<DropCounter> = TypedArena::default();
for i in 0..10 {
for _ in 0..100 {
// Allocate something with drop glue to make sure it doesn't leak.
arena.alloc(DropCounter { count: &counter });
}
arena.clear();
assert_eq!(counter.get(), i * 100 + 100);
}
}
static DROP_COUNTER: AtomicUsize = AtomicUsize::new(0);
struct SmallDroppable;
impl Drop for SmallDroppable {
fn drop(&mut self) {
DROP_COUNTER.fetch_add(1, Ordering::SeqCst);
}
}
#[test]
fn test_typed_arena_drop_small_count() {
DROP_COUNTER.store(0, Ordering::SeqCst);
{
let arena: TypedArena<SmallDroppable> = TypedArena::default();
for _ in 0..100 {
// Allocate something with drop glue to make sure it doesn't leak.
arena.alloc(SmallDroppable);
}
// dropping
};
assert_eq!(DROP_COUNTER.load(Ordering::SeqCst), 100);
}
#[bench]
pub fn bench_noncopy(b: &mut Bencher) {
let arena = TypedArena::default();
b.iter(|| {
arena.alloc(Noncopy {
string: String::from("hello world"),
array: vec![1, 2, 3, 4, 5],
})
})
}
#[bench]
pub fn bench_noncopy_nonarena(b: &mut Bencher) {
b.iter(|| {
let _: Box<_> = Box::new(Noncopy {
string: String::from("hello world"),
array: vec![1, 2, 3, 4, 5],
});
})
}
}
================================================
FILE: libeir_intern/src/lib.rs
================================================
#![feature(core_intrinsics)]
#![feature(dropck_eyepatch)]
#![feature(raw_vec_internals)]
#![feature(test)]
extern crate alloc;
#[cfg(any(test, bench))]
extern crate test;
pub mod arena;
pub mod symbol;
pub use symbol::{Ident, InternedString, LocalInternedString, Symbol};
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
}
================================================
FILE: libeir_intern/src/symbol.rs
================================================
//! An "interner" is a data structure that associates values with usize tags and
//! allows bidirectional lookup; i.e., given a value, one can easily find the
//! type, and vice versa.
#![allow(unused)]
use std::cell::RefCell;
use std::cmp::{Ord, Ordering, PartialEq, PartialOrd};
use std::fmt;
use std::hash::{Hash, Hasher};
use std::marker::PhantomData;
use std::str;
use std::sync::{Arc, RwLock};
use lazy_static::lazy_static;
use rustc_hash::FxHashMap;
use crate::arena::DroplessArena;
use libeir_diagnostics::SourceSpan;
lazy_static! {
/// A globally accessible symbol table
pub static ref SYMBOL_TABLE: SymbolTable = {
SymbolTable::new()
};
}
pub struct SymbolTable {
interner: RwLock<Interner>,
}
impl SymbolTable {
pub fn new() -> Self {
SymbolTable {
interner: RwLock::new(Interner::fresh()),
}
}
}
unsafe impl Sync for SymbolTable {}
#[derive(Copy, Clone, Eq)]
pub struct Ident {
pub name: Symbol,
pub span: SourceSpan,
}
impl Ident {
#[inline]
pub const fn new(name: Symbol, span: SourceSpan) -> Ident {
Ident { name, span }
}
#[inline]
pub const fn with_empty_span(name: Symbol) -> Ident {
Ident::new(name, SourceSpan::UNKNOWN)
}
/// Maps an interned string to an identifier with an empty syntax context.
pub fn from_interned_str(string: InternedString) -> Ident {
Ident::with_empty_span(string.as_symbol())
}
/// Maps a string to an identifier with an empty syntax context.
pub fn from_str(string: &str) -> Ident {
Ident::with_empty_span(Symbol::intern(string))
}
pub fn unquote_string(self) -> Ident {
Ident::new(Symbol::intern(self.as_str().trim_matches('"')), self.span)
}
pub fn unquote_atom(self) -> Ident {
Ident::new(Symbol::intern(self.as_str().trim_matches('\'')), self.span)
}
pub fn gensym(self) -> Ident {
Ident::new(self.name.gensymed(), self.span)
}
pub fn as_str(self) -> LocalInternedString {
self.name.as_str()
}
pub fn as_interned_str(self) -> InternedString {
self.name.as_interned_str()
}
}
impl PartialOrd for Ident {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.name.partial_cmp(&other.name)
}
}
impl PartialEq for Ident {
fn eq(&self, rhs: &Self) -> bool {
self.name == rhs.name
}
}
impl Hash for Ident {
fn hash<H: Hasher>(&self, state: &mut H) {
self.name.hash(state);
}
}
impl fmt::Debug for Ident {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Ident<{} {:?}>", self.name, self.span)
}
}
impl fmt::Display for Ident {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self.name, f)
}
}
#[derive(Debug, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SymbolIndex(u32);
impl Clone for SymbolIndex {
fn clone(&self) -> Self {
*self
}
}
impl From<SymbolIndex> for u32 {
#[inline]
fn from(v: SymbolIndex) -> u32 {
v.as_u32()
}
}
impl From<SymbolIndex> for usize {
#[inline]
fn from(v: SymbolIndex) -> usize {
v.as_usize()
}
}
impl SymbolIndex {
// shave off 256 indices at the end to allow space for packing these indices into enums
pub const MAX_AS_U32: u32 = 0xFFFF_FF00;
pub const MAX: SymbolIndex = SymbolIndex::new(0xFFFF_FF00);
#[inline]
const fn new(n: u32) -> Self {
// This will fail at const eval time unless `value <=
// max` is true (in which case we get the index 0).
// It will also fail at runtime, of course, but in a
// kind of wacky way.
let _ = ["out of range value used"][!(n <= Self::MAX_AS_U32) as usize];
SymbolIndex(n)
}
#[inline]
pub fn as_u32(self) -> u32 {
self.0
}
#[inline]
pub fn as_usize(self) -> usize {
self.0 as usize
}
}
/// A symbol is an interned or gensymed string.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Symbol(SymbolIndex);
impl Symbol {
const fn new(n: u32) -> Self {
Symbol(SymbolIndex::new(n))
}
/// Maps a string to its interned representation.
pub fn intern(string: &str) -> Self {
with_interner(|interner| interner.intern(string))
}
pub fn interned(self) -> Self {
with_interner(|interner| interner.interned(self))
}
/// Gensyms a new usize, using the current interner.
pub fn gensym(string: &str) -> Self {
with_interner(|interner| interner.gensym(string))
}
pub fn gensymed(self) -> Self {
with_interner(|interner| interner.gensymed(self))
}
pub fn as_str(self) -> LocalInternedString {
with_interner(|interner| unsafe {
LocalInternedString {
string: ::std::mem::transmute::<&str, &str>(interner.get(self)),
dummy: PhantomData,
}
})
}
pub fn as_interned_str(self) -> InternedString {
with_interner(|interner| InternedString {
symbol: interner.interned(self),
})
}
#[inline]
pub fn as_u32(self) -> u32 {
self.0.as_u32()
}
#[inline]
pub fn as_usize(self) -> usize {
self.0.as_usize()
}
}
impl fmt::Debug for Symbol {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let is_gensymed = with_interner(|interner| interner.is_gensymed(*self));
if is_gensymed {
write!(f, "{}({:?})", self, self.0)
} else {
write!(f, "{}({:?})", self, self.0)
}
}
}
impl fmt::Display for Symbol {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self.as_str(), f)
}
}
impl<T: ::std::ops::Deref<Target = str>> PartialEq<T> for Symbol {
fn eq(&self, other: &T) -> bool {
self.as_str() == other.deref()
}
}
// The `&'static str`s in this type actually point into the arena.
//
// Note that normal symbols are indexed upward from 0, and gensyms are indexed
// downward from SymbolIndex::MAX_AS_U32.
#[derive(Default)]
pub struct Interner {
arena: DroplessArena,
pub names: FxHashMap<&'static str, Symbol>,
pub strings: Vec<&'static str>,
gensyms: Vec<Symbol>,
}
impl Interner {
fn prefill(init: &[&str]) -> Self {
let mut this = Interner::default();
for &string in init {
if string == "" {
// We can't allocate empty strings in the arena, so handle this here.
let name = Symbol::new(this.strings.len() as u32);
this.names.insert("", name);
this.strings.push("");
} else {
this.intern(string);
}
}
this
}
pub fn intern(&mut self, string: &str) -> Symbol {
if let Some(&name) = self.names.get(string) {
return name;
}
let name = Symbol::new(self.strings.len() as u32);
// `from_utf8_unchecked` is safe since we just allocated a `&str` which is known to be
// UTF-8.
let string: &str =
unsafe { str::from_utf8_unchecked(self.arena.alloc_slice(string.as_bytes())) };
// It is safe to extend the arena allocation to `'static` because we only access
// these while the arena is still alive.
let string: &'static str = unsafe { &*(string as *const str) };
self.strings.push(string);
self.names.insert(string, name);
name
}
pub fn interned(&self, symbol: Symbol) -> Symbol {
if (symbol.0.as_usize()) < self.strings.len() {
symbol
} else {
self.interned(self.gensyms[(SymbolIndex::MAX_AS_U32 - symbol.0.as_u32()) as usize])
}
}
fn gensym(&mut self, string: &str) -> Symbol {
let symbol = self.intern(string);
self.gensymed(symbol)
}
fn gensymed(&mut self, symbol: Symbol) -> Symbol {
self.gensyms.push(symbol);
Symbol::new(SymbolIndex::MAX_AS_U32 - self.gensyms.len() as u32 + 1)
}
fn is_gensymed(&mut self, symbol: Symbol) -> bool {
symbol.0.as_usize() >= self.strings.len()
}
pub fn get(&self, symbol: Symbol) -> &str {
match self.strings.get(symbol.0.as_usize()) {
Some(string) => string,
None => self.get(self.gensyms[(SymbolIndex::MAX_AS_U32 - symbol.0.as_u32()) as usize]),
}
}
}
// In this macro, there is the requirement that the name (the number) must be monotonically
// increasing by one in the special identifiers, starting at 0; the same holds for the keywords,
// except starting from the next number instead of zero.
macro_rules! declare_atoms {(
$( ($index: expr, $konst: ident, $string: expr) )*
) => {
pub mod symbols {
use super::Symbol;
$(
#[allow(non_upper_case_globals)]
pub const $konst: Symbol = super::Symbol::new($index);
)*
/// Used *only* for testing that the declared atoms have no gaps
/// NOTE: The length must be static, so it must be changed when new
/// declared keywords are added to the list
pub(super) static DECLARED: [(Symbol, &'static str); 60] = [$(($konst, $string),)*];
}
impl Interner {
pub fn fresh() -> Self {
let interner = Interner::prefill(&[$($string,)*]);
interner
}
}
}}
// NOTE: When determining whether an Ident is a keyword or not, we compare against
// the ident table index, but if a hole is left in the table, then non-keyword idents
// will be interned with an id in the keyword range. It is important to ensure there are
// no holes, which means you have to adjust the indexes when adding a new keyword earlier
// in the table
declare_atoms! {
// We want true/false to correspond to 1/0 respectively for convenience
(0, False, "false")
(1, True, "true")
// Special reserved identifiers used internally, such as for error recovery
(2, Invalid, "")
// Keywords that are used in Erlang
(3, After, "after")
(4, Begin, "begin")
(5, Case, "case")
(6, Try, "try")
(7, Catch, "catch")
(8, End, "end")
(9, Fun, "fun")
(10, If, "if")
(11, Of, "of")
(12, Receive, "receive")
(13, When, "when")
(14, AndAlso, "andalso")
(15, OrElse, "orelse")
(16, Bnot, "bnot")
(17, Not, "not")
(18, Div, "div")
(19, Rem, "rem")
(20, Band, "band")
(21, And, "and")
(22, Bor, "bor")
(23, Bxor, "bxor")
(24, Bsl, "bsl")
(25, Bsr, "bsr")
(26, Or, "or")
(27, Xor, "xor")
// Not reserved words, but used in attributes or preprocessor directives
(28, Module, "module")
(29, Export, "export")
(30, Import, "import")
(31, Compile, "compile")
(32, Vsn, "vsn")
(33, OnLoad, "on_load")
(34, Behaviour, "behaviour")
(35, Spec, "spec")
(36, Callback, "callback")
(37, Include, "include")
(38, IncludeLib, "include_lib")
(39, Define, "define")
(40, Undef, "undef")
(41, Ifdef, "ifdef")
(42, Ifndef, "ifndef")
(43, Else, "else")
(44, Elif, "elif")
(45, Endif, "endif")
(46, Error, "error")
(47, Warning, "warning")
(48, File, "file")
// Common words
(49, ModuleInfo, "module_info")
(50, RecordInfo, "record_info")
(51, BehaviourInfo,"behaviour_info")
(52, Exports, "exports")
(53, Attributes, "attributes")
(54, Native, "native")
(55, Deprecated, "deprecated")
(56, ModuleCapital,"MODULE")
(57, ModuleStringCapital,"MODULE_STRING")
(58, Throw, "throw")
(59, Exit, "exit")
}
impl Symbol {
/// Returns `true` if the token is a keyword, reserved in all name positions
pub fn is_keyword(self) -> bool {
self > symbols::Invalid && self <= symbols::Xor
}
/// Returns `true` if the token is a reserved attribute name
pub fn is_reserved_attr(self) -> bool {
self >= symbols::Module && self <= symbols::Warning
}
/// Returns `true` if the token is a preprocessor directive name
pub fn is_preprocessor_directive(self) -> bool {
self >= symbols::Include && self <= symbols::Warning
}
}
impl Ident {
pub fn is_keyword(self) -> bool {
self.name.is_keyword()
}
pub fn is_reserved_attr(self) -> bool {
self.name.is_reserved_attr()
}
pub fn is_preprocessor_directive(self) -> bool {
self.name.is_preprocessor_directive()
}
}
// If an interner exists, return it. Otherwise, prepare a fresh one.
#[inline]
fn with_interner<T, F: FnOnce(&mut Interner) -> T>(f: F) -> T {
let mut r = SYMBOL_TABLE
.interner
.write()
.expect("unable to acquire write lock for symbol table");
f(&mut *r)
//GLOBALS.with(|globals| {
//f(&mut *globals.symbol_interner.lock().expect("symbol interner lock was held"))
//})
}
#[inline]
fn with_read_only_interner<T, F: FnOnce(&Interner) -> T>(f: F) -> T {
let r = SYMBOL_TABLE
.interner
.read()
.expect("unable to acquire read lock for symbol table");
f(&*r)
}
/// Represents a string stored in the interner. Because the interner outlives any thread
/// which uses this type, we can safely treat `string` which points to interner data,
/// as an immortal string, as long as this type never crosses between threads.
#[derive(Clone, Copy, Hash, PartialOrd, Eq, Ord)]
pub struct LocalInternedString {
string: &'static str,
/// This type cannot be sent across threads, this emulates the
/// behavior of !impl without the unsafe feature flag.
dummy: PhantomData<*const u8>,
}
impl LocalInternedString {
pub fn as_interned_str(self) -> InternedString {
InternedString {
symbol: Symbol::intern(self.string),
}
}
pub fn get(&self) -> &'static str {
self.string
}
}
impl<U: ?Sized> ::std::convert::AsRef<U> for LocalInternedString
where
str: ::std::convert::AsRef<U>,
{
fn as_ref(&self) -> &U {
self.string.as_ref()
}
}
impl<T: ::std::ops::Deref<Target = str>> ::std::cmp::PartialEq<T> for LocalInternedString {
fn eq(&self, other: &T) -> bool {
self.string == other.deref()
}
}
impl ::std::cmp::PartialEq<LocalInternedString> for str {
fn eq(&self, other: &LocalInternedString) -> bool {
self == other.string
}
}
impl<'a> ::std::cmp::PartialEq<LocalInternedString> for &'a str {
fn eq(&self, other: &LocalInternedString) -> bool {
*self == other.string
}
}
impl ::std::cmp::PartialEq<LocalInternedString> for String {
fn eq(&self, other: &LocalInternedString) -> bool {
self == other.string
}
}
impl<'a> ::std::cmp::PartialEq<LocalInternedString> for &'a String {
fn eq(&self, other: &LocalInternedString) -> bool {
*self == other.string
}
}
//impl !Send for LocalInternedString {}
//impl !Sync for LocalInternedString {}
impl ::std::ops::Deref for LocalInternedString {
type Target = str;
fn deref(&self) -> &str {
self.string
}
}
impl fmt::Debug for LocalInternedString {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(self.string, f)
}
}
impl fmt::Display for LocalInternedString {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(self.string, f)
}
}
/// Represents a string stored in the string interner.
#[derive(Clone, Copy, Eq)]
pub struct InternedString {
symbol: Symbol,
}
impl InternedString {
pub fn with<F: FnOnce(&str) -> R, R>(self, f: F) -> R {
let str = with_interner(|interner| interner.get(self.symbol) as *const str);
// This is safe because the interner keeps string alive until it is dropped.
// We can access it because we know the interner is still alive since we use a
// scoped thread local to access it, and it was alive at the beginning of this scope
unsafe { f(&*str) }
}
pub fn as_symbol(self) -> Symbol {
self.symbol
}
pub fn as_str(self) -> LocalInternedString {
self.symbol.as_str()
}
}
impl Hash for InternedString {
fn hash<H: Hasher>(&self, state: &mut H) {
self.with(|str| str.hash(state))
}
}
impl PartialOrd<InternedString> for InternedString {
fn partial_cmp(&self, other: &InternedString) -> Option<Ordering> {
if self.symbol == other.symbol {
return Some(Ordering::Equal);
}
self.with(|self_str| other.with(|other_str| self_str.partial_cmp(other_str)))
}
}
impl Ord for InternedString {
fn cmp(&self, other: &InternedString) -> Ordering {
if self.symbol == other.symbol {
return Ordering::Equal;
}
self.with(|self_str| other.with(|other_str| self_str.cmp(&other_str)))
}
}
impl<T: ::std::ops::Deref<Target = str>> PartialEq<T> for InternedString {
fn eq(&self, other: &T) -> bool {
self.with(|string| string == other.deref())
}
}
impl PartialEq<InternedString> for InternedString {
fn eq(&self, other: &InternedString) -> bool {
self.symbol == other.symbol
}
}
impl PartialEq<InternedString> for str {
fn eq(&self, other: &InternedString) -> bool {
other.with(|string| self == string)
}
}
impl<'a> PartialEq<InternedString> for &'a str {
fn eq(&self, other: &InternedString) -> bool {
other.with(|string| *self == string)
}
}
impl PartialEq<InternedString> for String {
fn eq(&self, other: &InternedString) -> bool {
other.with(|string| self == string)
}
}
impl<'a> PartialEq<InternedString> for &'a String {
fn eq(&self, other: &InternedString) -> bool {
other.with(|string| *self == string)
}
}
impl ::std::convert::From<InternedString> for String {
fn from(val: InternedString) -> String {
val.as_symbol().to_string()
}
}
impl fmt::Debug for InternedString {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.with(|str| fmt::Debug::fmt(&str, f))
}
}
impl fmt::Display for InternedString {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.with(|str| fmt::Display::fmt(&str, f))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn interner_tests() {
let mut i: Interner = Interner::default();
// first one is zero:
assert_eq!(i.intern("dog"), Symbol::new(0));
// re-use gets the same entry:
assert_eq!(i.intern("dog"), Symbol::new(0));
// different string gets a different #:
assert_eq!(i.intern("cat"), Symbol::new(1));
assert_eq!(i.intern("cat"), Symbol::new(1));
// dog is still at zero
assert_eq!(i.intern("dog"), Symbol::new(0));
assert_eq!(i.gensym("zebra"), Symbol::new(SymbolIndex::MAX_AS_U32));
// gensym of same string gets new number:
assert_eq!(i.gensym("zebra"), Symbol::new(SymbolIndex::MAX_AS_U32 - 1));
// gensym of *existing* string gets new number:
assert_eq!(i.gensym("dog"), Symbol::new(SymbolIndex::MAX_AS_U32 - 2));
}
#[test]
fn interned_keywords_no_gaps() {
let mut i = Interner::fresh();
// Should already be interned with matching indexes
for (sym, s) in symbols::DECLARED.iter() {
assert_eq!(i.intern(&s), *sym)
}
// Should create a new symbol resulting in an index equal to the last entry in the table
assert_eq!(i.intern("foo").as_u32(), (i.names.len() - 1) as u32);
}
#[test]
fn unquote_string() {
let i = Ident::from_str("\"after\"");
assert_eq!(i.unquote_string().name, symbols::After);
}
#[test]
fn unquote_atom() {
let i = Ident::from_str("'after'");
assert_eq!(i.unquote_atom().name, symbols::After);
}
}
================================================
FILE: libeir_interpreter/Cargo.toml
================================================
[package]
name = "libeir_interpreter"
version = "0.1.0"
authors = ["hansihe"]
edition = "2018"
license = "MIT OR Apache-2.0"
[features]
default = ["trace"]
trace = []
[dependencies]
num = "0.2"
num-traits = "0.2"
tempdir = "0.3"
lazy_static = "1.2"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
libeir_ir = { path = "../libeir_ir" }
libeir_intern = { path = "../libeir_intern" }
libeir_util_binary = { path = "../util/libeir_util_binary" }
libeir_util_number = { path = "../util/libeir_util_number" }
num-bigint = { git = "https://github.com/hansihe/num-bigint.git" }
pretty = "0.7"
#[dependencies.rug]
#version = "1.2"
#default-features = false
#features = ["integer", "float", "rand"]
================================================
FILE: libeir_interpreter/README.md
================================================
# libeir_interpreter
**This interpreter is really basic and unfinished. It is only meant to aid testing.**
================================================
FILE: libeir_interpreter/src/erl_lib/erlang.rs
================================================
use libeir_intern::Symbol;
use libeir_util_number::bigint_to_double;
use crate::module::{NativeModule, NativeReturn};
use crate::process::ProcessContext;
use crate::vm::VMState;
use crate::term::ListIteratorItem;
use crate::term::Term;
use crate::term::{ErlEq, ErlExactEq, ErlOrd};
use ::num_traits::Signed;
use std::rc::Rc;
fn abs(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
if args.len() != 1 {
panic!()
}
let a1 = &*args[0];
let ret = match a1 {
Term::Integer(ref int) => Term::Integer(int.clone().abs()),
Term::Float(flt) => Term::Float(flt.0.abs().into()),
_ => panic!(),
};
NativeReturn::Return { term: ret.into() }
}
fn add(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
// TODO: Verify semantics
if args.len() != 2 {
panic!();
}
let a1 = &*args[0];
let a2 = &*args[1];
match (a1, a2) {
(Term::Integer(ref i1), Term::Integer(ref i2)) => NativeReturn::Return {
term: Term::Integer(i1.clone() + i2).into(),
},
(Term::Integer(ref i1), Term::Float(f2)) => {
let f1 = bigint_to_double(i1);
NativeReturn::Return {
term: Term::Float((f1 + f2.0).into()).into(),
}
}
(Term::Float(f1), Term::Integer(ref i2)) => {
let f2 = bigint_to_double(i2);
NativeReturn::Return {
term: Term::Float((f1.0 + f2).into()).into(),
}
}
(Term::Float(f1), Term::Float(f2)) => NativeReturn::Return {
term: Term::Float((f1.0 + f2.0).into()).into(),
},
_ => NativeReturn::Throw {
typ: Term::new_atom("error").into(),
reason: Term::new_atom("badarith").into(),
},
}
}
fn sub(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
if args.len() != 2 {
panic!();
}
let a1 = &*args[0];
let a2 = &*args[1];
match (a1, a2) {
(Term::Integer(ref i1), Term::Integer(ref i2)) => NativeReturn::Return {
term: Term::Integer(i1.clone() - i2).into(),
},
(Term::Integer(ref int), Term::Float(ref flt)) => {
let flt_c = bigint_to_double(int);
NativeReturn::Return {
term: Term::Float((flt_c - flt.0).into()).into(),
}
}
(Term::Float(ref flt), Term::Integer(ref int)) => {
let flt_c = bigint_to_double(int);
NativeReturn::Return {
term: Term::Float((flt.0 - flt_c).into()).into(),
}
}
(Term::Float(flt1), Term::Float(flt2)) => NativeReturn::Return {
term: Term::Float((flt1.0 - flt2.0).into()).into(),
},
_ => NativeReturn::Throw {
typ: Term::new_atom("error").into(),
reason: Term::new_atom("badarith").into(),
},
}
}
fn invert(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
if args.len() != 1 {
panic!();
}
match &*args[0] {
Term::Integer(ref i1) => NativeReturn::Return {
term: Term::Integer(-i1.clone()).into(),
},
Term::Float(ref f1) => NativeReturn::Return {
term: Term::Float((-f1.0).into()).into(),
},
_ => unimplemented!(),
}
}
fn mul(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
if args.len() != 2 {
panic!();
}
let a1 = &*args[0];
let a2 = &*args[1];
match (a1, a2) {
(Term::Integer(ref i1), Term::Integer(ref i2)) => NativeReturn::Return {
term: Term::Integer(i1.clone() * i2).into(),
},
_ => unimplemented!(),
}
}
fn div(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
if args.len() != 2 {
panic!();
}
let a1 = match &*args[0] {
Term::Integer(i1) => bigint_to_double(i1),
Term::Float(flt) => flt.0,
_ => panic!(),
};
let a2 = match &*args[1] {
Term::Integer(i1) => bigint_to_double(i1),
Term::Float(flt) => flt.0,
_ => panic!(),
};
NativeReturn::Return {
term: Term::Float((a1 / a2).into()).into(),
}
}
fn is_list(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
if args.len() != 1 {
panic!();
}
let a1 = &*args[0];
match a1 {
Term::ListCell(_, _) => NativeReturn::Return {
term: Term::new_atom("true").into(),
},
Term::Nil => NativeReturn::Return {
term: Term::new_atom("true").into(),
},
_ => NativeReturn::Return {
term: Term::new_atom("false").into(),
},
}
}
fn is_atom(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
if args.len() != 1 {
panic!();
}
let a1 = &*args[0];
match a1 {
Term::Atom(_) => NativeReturn::Return {
term: Term::new_bool(true).into(),
},
_ => NativeReturn::Return {
term: Term::new_bool(false).into(),
},
}
}
fn is_integer(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
assert!(args.len() == 1);
let a1 = &*args[0];
match a1 {
Term::Integer(_) => NativeReturn::Return {
term: Term::new_bool(true).into(),
},
_ => NativeReturn::Return {
term: Term::new_bool(false).into(),
},
}
}
fn is_pid(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
assert!(args.len() == 1);
let a1 = &*args[0];
match a1 {
Term::Pid(_) => NativeReturn::Return {
term: Term::new_bool(true).into(),
},
_ => NativeReturn::Return {
term: Term::new_bool(false).into(),
},
}
}
fn is_tuple(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
assert!(args.len() == 1);
let a1 = &*args[0];
match a1 {
Term::Tuple(_) => NativeReturn::Return {
term: Term::new_bool(true).into(),
},
_ => NativeReturn::Return {
term: Term::new_bool(false).into(),
},
}
}
fn is_map(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
assert!(args.len() == 1);
let a1 = &*args[0];
match a1 {
Term::Map(_) => NativeReturn::Return {
term: Term::new_bool(true).into(),
},
_ => NativeReturn::Return {
term: Term::new_bool(false).into(),
},
}
}
//fn list_append(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
// // TODO: Validate semantics
// assert!(args.len() == 2);
// match (&*args[0], &*args[1]) {
// (Term::Nil, Term::Nil) => NativeReturn::Return { term: Term::Nil.into() },
// (Term::Nil, Term::List(_, _)) => NativeReturn::Return { term: args[1].clone() },
// (Term::List(_, ref tail), Term::Nil) if tail.erl_eq(&Term::Nil)
// => NativeReturn::Return { term: args[0].clone() },
// (Term::List(ref _f_head, ref _f_tail), Term::List(ref b_head, ref b_tail)) => {
// let (mut f_head_terms, f_tail_term) = args[0].as_inproper_list();
// if let Term::Nil = f_tail_term {
// f_head_terms.extend(b_head.iter().cloned());
// NativeReturn::Return { term: Term::List(f_head_terms, b_tail.clone()).into() }
// } else {
// NativeReturn::Throw
// }
// }
// _ => NativeReturn::Throw,
// }
//}
fn list_subtract(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
let (mut to_remove_vec, tail) = Term::as_inproper_list(&args[1]);
assert!(tail.erl_eq(&Term::Nil));
let mut out = Vec::new();
for item in Term::list_iter(&args[0]) {
match item {
ListIteratorItem::Elem(elem) => {
if let Some(idx) = to_remove_vec
.iter()
.enumerate()
.find(|(_, term)| elem.erl_eq(term))
.map(|(idx, _)| idx)
{
to_remove_vec.remove(idx);
} else {
out.push(elem);
}
}
ListIteratorItem::Tail(tail) => {
assert!(tail.erl_eq(&Term::Nil));
return NativeReturn::Return {
term: Term::slice_to_list(&out, tail.clone()),
};
}
}
}
unreachable!()
}
fn exact_eq(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
assert!(args.len() == 2);
NativeReturn::Return {
term: Term::new_bool(args[0].erl_exact_eq(&*args[1])).into(),
}
}
fn exact_not_eq(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
assert!(args.len() == 2);
NativeReturn::Return {
term: Term::new_bool(!args[0].erl_exact_eq(&*args[1])).into(),
}
}
fn and(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
assert!(args.len() == 2);
if let (Some(a1), Some(a2)) = (args[0].as_boolean(), args[1].as_boolean()) {
NativeReturn::Return {
term: Term::new_bool(a1 && a2).into(),
}
} else {
panic!()
}
}
fn or(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
assert!(args.len() == 2);
if let (Some(a1), Some(a2)) = (args[0].as_boolean(), args[1].as_boolean()) {
NativeReturn::Return {
term: Term::new_bool(a1 || a2).into(),
}
} else {
panic!()
}
}
fn tuple_size(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
assert!(args.len() == 1);
if let Term::Tuple(ref terms) = &*args[0] {
NativeReturn::Return {
term: Term::new_i64(terms.len() as i64).into(),
}
} else {
panic!()
}
}
fn is_function(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
assert!(args.len() == 1 || args.len() == 2);
let arity_ref = if args.len() == 2 {
if let Some(int) = args[1].as_i64() {
Some(int)
} else {
panic!()
}
} else {
None
};
if let Term::CapturedFunction { ident, .. } = &*args[0] {
let res = arity_ref.map(|a| a == ident.arity as i64).unwrap_or(true);
NativeReturn::Return {
term: Term::new_bool(res).into(),
}
} else if let Term::BoundLambda { ident, .. } = &*args[0] {
let res = arity_ref.map(|a| a == ident.arity as i64).unwrap_or(true);
NativeReturn::Return {
term: Term::new_bool(res).into(),
}
} else {
NativeReturn::Return {
term: Term::new_bool(false).into(),
}
}
}
//fn base_spawn(vm: &VMState, ident: &FunctionIdent, args: Vec<Term>) -> Pid {
// let new_pid = {
// let mut processes = vm.processes.borrow();
// Pid(processes.len())
// };
//
// let process = ProcessContext::new(new_pid);
//
// let orig_pid = crate::trace::get_pid();
// crate::trace::set_pid(new_pid);
// let frame = process.make_call_stackframe(
// vm,
// ident.module.clone(),
// ident.clone(),
// args
// );
// crate::trace::set_pid(orig_pid);
//
// let stack_i = process.stack.clone();
// let mut stack = stack_i.borrow_mut();
// stack.push(frame);
//
// {
// let mut processes = vm.processes.borrow_mut();
// processes.push(Rc::new(RefCell::new(process)));
// }
//
// {
// let mut mailboxes = vm.mailboxes.borrow_mut();
// mailboxes.insert(new_pid, ::mailbox::Mailbox::new());
// }
//
// new_pid
//}
//
//fn base_spawn_term(vm: &VMState, callable: &Term, mut args: Vec<Term>) -> Pid {
// match callable {
// Term::CapturedFunction { module, fun_name, arity } => {
// let ident = FunctionIdent {
// module: module.clone(),
// name: fun_name.clone(),
// arity: *arity,
// lambda: None,
// };
// base_spawn(vm, &ident, args)
// }
// Term::BoundLambda { module, fun_name, arity, lambda, bound_env } => {
// let ident = FunctionIdent {
// module: module.clone(),
// name: fun_name.clone(),
// arity: *arity,
// lambda: Some(*lambda),
// };
// args.insert(0, Term::LambdaEnv(bound_env.clone()));
// base_spawn(vm, &ident, args)
// },
// _ => panic!(),
// }
//}
//
//fn base_monitor(vm: &VMState, proc: &mut ProcessContext, other: Pid) -> Reference {
// let monitor_ref = vm.ref_gen.borrow_mut().next();
// let mut watches = vm.watches.borrow_mut();
//
// if !watches.contains_key(&other) {
// watches.insert(other, Vec::new());
// }
// let for_proc = watches.get_mut(&other).unwrap();
//
// for_proc.push((proc.pid, WatchType::Monitor(monitor_ref)));
//
// monitor_ref
//}
//
//fn spawn_1(vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
// assert!(args.len() == 1);
// let fun_term = &*args[0];
//
// let new_pid = base_spawn_term(vm, fun_term, vec![]);
// NativeReturn::Return { term: Term::Pid(new_pid) }
//}
//
//fn spawn_monitor_1(vm: &VMState, proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
// assert!(args.len() == 1);
// let fun_term = &*args[0];
//
// let new_pid = base_spawn_term(vm, fun_term, vec![]);
// let monitor_ref = base_monitor(vm, proc, new_pid);
//
// let term = Term::Tuple(vec![
// Term::Pid(new_pid),
// Term::Reference(monitor_ref),
// ]);
// NativeReturn::Return { term: term }
//}
//
//fn monitor_2(vm: &VMState, proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
// assert!(args.len() == 2);
// if args[0].erl_eq(&Term::new_atom("process")) {
// if let Term::Pid(pid) = args[1] {
// let monitor_ref = base_monitor(vm, proc, pid);
// NativeReturn::Return { term: Term::Reference(monitor_ref) }
// } else {
// NativeReturn::Throw
// }
// } else {
// unimplemented!()
// }
//}
fn not(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
assert!(args.len() == 1);
if let Some(b) = args[0].as_boolean() {
NativeReturn::Return {
term: Term::new_bool(!b).into(),
}
} else {
panic!()
}
}
fn is_binary(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
assert!(args.len() == 1);
let a1 = &*args[0];
match a1 {
Term::Binary(_) => NativeReturn::Return {
term: Term::new_bool(true).into(),
},
Term::BinarySlice { .. } => NativeReturn::Return {
term: Term::new_bool(true).into(),
},
_ => NativeReturn::Return {
term: Term::new_bool(false).into(),
},
}
}
fn atom_to_list(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
assert!(args.len() == 1);
let a1 = &*args[0];
match a1 {
Term::Atom(atom) => {
let chars: Vec<_> = atom
.as_str()
.chars()
.map(|c| Term::new_i64(c as i64).into())
.collect();
NativeReturn::Return {
term: Term::slice_to_list(&chars, Term::Nil.into()).into(),
}
}
_ => panic!(),
}
}
fn less_than_or_equal(
_vm: &VMState,
_proc: &mut ProcessContext,
args: &[Rc<Term>],
) -> NativeReturn {
assert!(args.len() == 2);
let a1 = &*args[0];
let a2 = &*args[1];
let ord = a1.erl_ord(a2);
NativeReturn::Return {
term: Term::new_bool(ord != std::cmp::Ordering::Greater).into(),
}
}
fn less_than(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
assert!(args.len() == 2);
let a1 = &*args[0];
let a2 = &*args[1];
let ord = a1.erl_ord(a2);
NativeReturn::Return {
term: Term::new_bool(ord == std::cmp::Ordering::Less).into(),
}
}
fn greater_than_or_equal(
_vm: &VMState,
_proc: &mut ProcessContext,
args: &[Rc<Term>],
) -> NativeReturn {
assert!(args.len() == 2);
let a1 = &*args[0];
let a2 = &*args[1];
let ord = a1.erl_ord(a2);
NativeReturn::Return {
term: Term::new_bool(ord != std::cmp::Ordering::Less).into(),
}
}
fn greater_than(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
assert!(args.len() == 2);
let a1 = &*args[0];
let a2 = &*args[1];
let ord = a1.erl_ord(a2);
NativeReturn::Return {
term: Term::new_bool(ord == std::cmp::Ordering::Greater).into(),
}
}
fn setelement(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
assert!(args.len() == 3);
let idx = if let Some(num) = args[0].as_usize() {
num
} else {
panic!()
};
let value = args[2].clone();
if let Term::Tuple(vals) = &*args[1] {
if idx == 0 || idx > vals.len() {
panic!()
} else {
let mut vals = vals.clone();
vals[idx - 1] = value;
NativeReturn::Return {
term: Term::Tuple(vals).into(),
}
}
} else {
panic!()
}
}
fn element(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
assert!(args.len() == 2);
let idx = if let Some(num) = args[0].as_usize() {
num
} else {
panic!()
};
if let Term::Tuple(vals) = &*args[1] {
if idx == 0 || idx > vals.len() {
panic!()
} else {
NativeReturn::Return {
term: vals[idx - 1].clone(),
}
}
} else {
panic!()
}
}
fn erl_self(_vm: &VMState, proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
assert!(args.len() == 0);
NativeReturn::Return {
term: Term::Pid(proc.pid).into(),
}
}
//fn process_flag(vm: &VMState, proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
// assert!(args.len() == 2);
// if args[0].erl_eq(&Term::new_atom("trap_exit")) {
// let mut mailboxes = vm.mailboxes.borrow_mut();
// let mailbox = &mut mailboxes.get_mut(&proc.pid).unwrap();
// let old_trap_exits = mailbox.get_trap_exits();
// mailbox.set_trap_exits(args[1].as_boolean().unwrap());
// NativeReturn::Return { term: Term::new_bool(old_trap_exits).into() }
// } else {
// unimplemented!()
// }
//}
fn put(_vm: &VMState, proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
assert!(args.len() == 2);
if let Some(entry) = proc.dict.iter_mut().find(|e| e.0.erl_exact_eq(&args[0])) {
let old = entry.1.clone();
entry.1 = args[1].clone();
NativeReturn::Return { term: old }
} else {
proc.dict.push((args[0].clone(), args[1].clone()));
NativeReturn::Return {
term: Term::new_atom("undefined").into(),
}
}
}
fn get(_vm: &VMState, proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
assert!(args.len() == 1);
if let Some(entry) = proc.dict.iter().find(|e| e.0.erl_exact_eq(&args[0])) {
NativeReturn::Return {
term: entry.1.clone(),
}
} else {
NativeReturn::Return {
term: Term::new_atom("undefined").into(),
}
}
}
fn erase(_vm: &VMState, proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
assert!(args.len() == 1);
let idx = proc
.dict
.iter()
.enumerate()
.find(|e| (e.1).0.erl_exact_eq(&args[0]))
.map(|(idx, _)| idx);
if let Some(entry) = idx {
let (_key, val) = proc.dict.remove(entry);
NativeReturn::Return { term: val }
} else {
NativeReturn::Return {
term: Term::new_atom("undefined").into(),
}
}
}
fn length(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
assert!(args.len() == 1);
let mut len = 0;
for item in Term::list_iter(&args[0]) {
match item {
ListIteratorItem::Elem(_) => {
len += 1;
}
ListIteratorItem::Tail(tail) => {
if tail.erl_eq(&Term::Nil) {
return NativeReturn::Return {
term: Term::new_i64(len as i64).into(),
};
} else {
return NativeReturn::Throw {
typ: Term::new_atom("error").into(),
reason: Term::new_atom("badarg").into(),
};
}
}
}
}
unreachable!()
}
fn hd(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
if args.len() != 1 {
panic!();
}
let a1 = &*args[0];
match a1 {
Term::ListCell(hd, _) => NativeReturn::Return { term: hd.clone() },
_ => NativeReturn::Throw {
typ: Term::new_atom("error").into(),
reason: Term::new_atom("badarg").into(),
},
}
}
fn tl(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
if args.len() != 1 {
panic!();
}
let a1 = &*args[0];
match a1 {
Term::ListCell(_, tl) => NativeReturn::Return { term: tl.clone() },
_ => NativeReturn::Throw {
typ: Term::new_atom("error").into(),
reason: Term::new_atom("badarg").into(),
},
}
}
fn map_size(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
assert!(args.len() == 1);
if let Some(map) = args[0].as_map() {
NativeReturn::Return {
term: Term::new_usize(map.len()).into(),
}
} else {
unimplemented!()
}
}
pub fn make_erlang() -> NativeModule {
let mut module = NativeModule::new(Symbol::intern("erlang"));
module.add_fun(Symbol::intern("+"), 2, Box::new(add));
module.add_fun(Symbol::intern("-"), 1, Box::new(invert));
module.add_fun(Symbol::intern("-"), 2, Box::new(sub));
module.add_fun(Symbol::intern("*"), 2, Box::new(mul));
module.add_fun(Symbol::intern("/"), 2, Box::new(div));
module.add_fun(Symbol::intern("abs"), 1, Box::new(abs));
//module.add_fun(Symbol::intern("++"), 2, Box::new(list_append));
module.add_fun(Symbol::intern("--"), 2, Box::new(list_subtract));
module.add_fun(Symbol::intern("=:="), 2, Box::new(exact_eq));
module.add_fun(Symbol::intern("=/="), 2, Box::new(exact_not_eq));
module.add_fun(Symbol::intern("=<"), 2, Box::new(less_than_or_equal));
module.add_fun(Symbol::intern("<"), 2, Box::new(less_than));
module.add_fun(Symbol::intern(">="), 2, Box::new(greater_than_or_equal));
module.add_fun(Symbol::intern(">"), 2, Box::new(greater_than));
module.add_fun(Symbol::intern("is_list"), 1, Box::new(is_list));
module.add_fun(Symbol::intern("is_atom"), 1, Box::new(is_atom));
module.add_fun(Symbol::intern("is_binary"), 1, Box::new(is_binary));
module.add_fun(Symbol::intern("is_integer"), 1, Box::new(is_integer));
module.add_fun(Symbol::intern("is_pid"), 1, Box::new(is_pid));
module.add_fun(Symbol::intern("is_tuple"), 1, Box::new(is_tuple));
module.add_fun(Symbol::intern("is_map"), 1, Box::new(is_map));
module.add_fun(Symbol::intern("and"), 2, Box::new(and));
module.add_fun(Symbol::intern("or"), 2, Box::new(or));
module.add_fun(Symbol::intern("tuple_size"), 1, Box::new(tuple_size));
module.add_fun(Symbol::intern("is_function"), 1, Box::new(is_function));
module.add_fun(Symbol::intern("is_function"), 2, Box::new(is_function));
//module.add_fun(Symbol::intern("spawn_monitor"), 1, Box::new(spawn_monitor_1));
module.add_fun(Symbol::intern("not"), 1, Box::new(not));
module.add_fun(Symbol::intern("atom_to_list"), 1, Box::new(atom_to_list));
module.add_fun(Symbol::intern("setelement"), 3, Box::new(setelement));
module.add_fun(Symbol::intern("element"), 2, Box::new(element));
module.add_fun(Symbol::intern("length"), 1, Box::new(length));
module.add_fun(Symbol::intern("self"), 0, Box::new(erl_self));
module.add_fun(Symbol::intern("put"), 2, Box::new(put));
module.add_fun(Symbol::intern("get"), 1, Box::new(get));
module.add_fun(Symbol::intern("erase"), 1, Box::new(erase));
module.add_fun(Symbol::intern("hd"), 1, Box::new(hd));
module.add_fun(Symbol::intern("tl"), 1, Box::new(tl));
module.add_fun(Symbol::intern("map_size"), 1, Box::new(map_size));
//module.add_fun(Symbol::intern("spawn"), 1, Box::new(spawn_1));
//module.add_fun(Symbol::intern("monitor"), 2, Box::new(monitor_2));
//module.add_fun(Symbol::intern("process_flag"), 2, Box::new(process_flag));
module
}
================================================
FILE: libeir_interpreter/src/erl_lib/file.rs
================================================
use ::module::NativeModule;
use ::vm::VMState;
use ::term::Term;
use ::process::{ CallReturn, ProcessContext };
fn delete(_vm: &VMState, _proc: &mut ProcessContext, args: &[Term]) -> CallReturn {
assert!(args.len() == 1);
// TODO
let n = vec![Term::new_atom("error"), Term::new_atom("enoent")];
CallReturn::Return { term: Term::Tuple(n) }
}
pub fn make_time() -> NativeModule {
let mut module = NativeModule::new("file".to_string());
module.add_fun("delete".to_string(), 1, Box::new(delete));
module
}
================================================
FILE: libeir_interpreter/src/erl_lib/lists.rs
================================================
use std::rc::Rc;
use crate::module::{NativeModule, NativeReturn};
use crate::process::ProcessContext;
use crate::term::{ErlEq, Term};
use crate::vm::VMState;
use libeir_intern::Symbol;
//fn member_list(item: &Term, list: &Term) -> NativeReturn {
// if let Term::Nil = list {
// NativeReturn::Return { term: Term::new_bool(false).into() }
// } else if let Term::List(ref head, ref tail) = list {
// for l_item in head {
// if item.erl_exact_eq(l_item) {
// return NativeReturn::Return { term: Term::new_bool(true).into() };
// }
// }
// member_list(item, tail)
// } else {
// NativeReturn::Throw
// }
//}
//
//fn member(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
// assert!(args.len() == 2);
// member_list(&args[0], &args[1])
//}
//
fn reverse_2(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
assert!(args.len() == 2);
let (mut head, tail) = Term::as_inproper_list(&args[0]);
assert!(tail.erl_eq(&Term::Nil));
head.reverse();
NativeReturn::Return {
term: Term::slice_to_list(&head, args[1].clone()),
}
}
fn reverse_1(vm: &VMState, proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
assert!(args.len() == 1);
reverse_2(vm, proc, &[args[0].clone(), Term::Nil.into()])
}
//fn keyfind(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
// assert!(args.len() == 3);
// let key = &*args[0];
// let pos = if let Some(int) = args[1].as_i64() {
// int
// } else {
// return NativeReturn::Throw;
// };
// let list_term = &*args[2];
// let (list, list_tail) = list_term.as_inproper_list();
// for term in list.iter() {
// if let Term::Tuple(values) = &**term {
// if let Some(val_term) = values.get(pos as usize) {
// if val_term.erl_eq(key) {
// return NativeReturn::Return { term: term.clone() };
// }
// }
// }
// }
// if let Term::Nil = list_tail {
// NativeReturn::Return { term: Term::new_bool(false).into() }
// } else {
// NativeReturn::Throw
// }
//}
pub fn make_lists() -> NativeModule {
let mut module = NativeModule::new(Symbol::intern("lists"));
//module.add_fun(Symbol::intern("member"), 2, Box::new(member));
module.add_fun(Symbol::intern("reverse"), 1, Box::new(reverse_1));
module.add_fun(Symbol::intern("reverse"), 2, Box::new(reverse_2));
//module.add_fun(Symbol::intern("keyfind"), 3, Box::new(keyfind));
module
}
================================================
FILE: libeir_interpreter/src/erl_lib/maps.rs
================================================
use libeir_intern::Symbol;
use crate::module::{NativeModule, NativeReturn};
use crate::process::ProcessContext;
use crate::vm::VMState;
use crate::term::{ListIteratorItem, MapTerm, Term};
use std::rc::Rc;
fn new_0(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
assert!(args.len() == 0);
NativeReturn::Return {
term: Term::Map(MapTerm::new()).into(),
}
}
fn from_list_1(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
assert!(args.len() == 1);
let mut map = MapTerm::new();
for elem in Term::list_iter(&args[0]) {
match elem {
ListIteratorItem::Elem(tup_term) => {
let tup = tup_term.as_tuple().unwrap();
assert!(tup.len() == 2);
map.insert(tup[0].clone(), tup[1].clone());
}
ListIteratorItem::Tail(term) => {
assert!(term.is_nil());
}
}
}
NativeReturn::Return {
term: Term::Map(map).into(),
}
}
pub fn make_maps() -> NativeModule {
let mut module = NativeModule::new(Symbol::intern("maps"));
module.add_fun(Symbol::intern("new"), 0, Box::new(new_0));
module.add_fun(Symbol::intern("from_list"), 1, Box::new(from_list_1));
module
}
================================================
FILE: libeir_interpreter/src/erl_lib/math.rs
================================================
use std::rc::Rc;
use crate::module::{NativeModule, NativeReturn};
use crate::process::ProcessContext;
use crate::term::Term;
use crate::vm::VMState;
use libeir_intern::Symbol;
use num_traits::{Pow, ToPrimitive};
fn pow(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> NativeReturn {
assert!(args.len() == 2);
let a1 = &*args[0];
let a2 = &*args[1];
let ret = match (a1, a2) {
(Term::Integer(ref i1), Term::Integer(ref i2)) => {
Term::Integer(i1.clone().pow(i2.to_u32().unwrap()))
}
//Term::Integer(num::pow::pow(i1.clone(), i2.to_usize().unwrap())),
_ => unimplemented!(),
};
NativeReturn::Return { term: ret.into() }
}
pub fn make_math() -> NativeModule {
let mut module = NativeModule::new(Symbol::intern("math"));
module.add_fun(Symbol::intern("pow"), 2, Box::new(pow));
module
}
================================================
FILE: libeir_interpreter/src/erl_lib/mod.rs
================================================
mod erlang;
pub use self::erlang::make_erlang;
//mod os;
//pub use self::os::make_os;
mod lists;
pub use self::lists::make_lists;
mod math;
pub use self::math::make_math;
//mod file;
//pub use self::file::make_time;
mod maps;
pub use self::maps::make_maps;
================================================
FILE: libeir_interpreter/src/erl_lib/os.rs
================================================
use ::vm::VMState;
use ::module::NativeModule;
use ::term::Term;
use ::process::{ CallReturn, ProcessContext };
fn getenv(_vm: &VMState, _proc: &mut ProcessContext, args: &[Term]) -> CallReturn {
if args.len() == 1 {
CallReturn::Return { term: Term::new_bool(false) }
} else {
CallReturn::Throw
}
}
fn os_type(_vm: &VMState, _proc: &mut ProcessContext, args: &[Term]) -> CallReturn {
assert!(args.len() == 0);
// TODO
let family = Term::new_atom("unix");
let name = Term::new_atom("linux");
CallReturn::Return { term: Term::Tuple(vec![family, name]) }
}
pub fn make_os() -> NativeModule {
let mut module = NativeModule::new("os".to_string());
module.add_fun("getenv".to_string(), 1, Box::new(getenv));
module.add_fun("type".to_string(), 0, Box::new(os_type));
module
}
================================================
FILE: libeir_interpreter/src/erl_tests/mod.rs
================================================
extern crate tempdir;
use ::std::io::{ Read, Write };
use ::{ VMState, Term };
use eir::Module;
use ::term::ErlEq;
fn erl_to_core(erlang_code: &str) -> String {
let temp = tempdir::TempDir::new("core_erlang_crate_tests").unwrap();
let temp_dir = temp.path();
println!("Compilation dir: {:?}", temp_dir);
{
let in_file_name = temp_dir.join("code.erl");
let mut in_file = ::std::fs::File::create(in_file_name).unwrap();
in_file.write_all(erlang_code.as_bytes()).unwrap();
}
let out = ::std::process::Command::new("erlc")
.arg("+to_core")
.arg("code.erl")
.current_dir(temp_dir.clone())
.output()
.expect("failed to execute erlc");
println!("{:?}", out);
assert!(out.status.success());
let out_file_name = temp_dir.join("code.core");
let mut out_file = ::std::fs::File::open(out_file_name).unwrap();
let mut out_core = String::new();
out_file.read_to_string(&mut out_core).unwrap();
println!("====== Core ======\n{}\n==================\n\n", out_core);
out_core
}
fn erl_to_ir(erlang_code: &str) -> Module {
let core = erl_to_core(erlang_code);
let parsed = ::core_erlang_compiler::parser::parse(&core).unwrap();
let ir = ::core_erlang_compiler::ir::from_parsed(&parsed.0);
//println!("Ir:\n{:?}", ir);
ir
}
fn ctx_from_erl(erlang_code: &str) -> VMState {
let module = erl_to_ir(erlang_code);
let mut ctx = VMState::new();
ctx.add_native_module(::erl_lib::make_erlang());
ctx.add_erlang_module(module);
ctx
}
const TEST_ERL_1: &str = r##"
-module(test).
-export([add/2, add_two/3, return_closure/1]).
add(A, B) ->
A + B.
add_two(A, B, C) ->
I = add(A, B),
add(I, C).
return_closure(I) ->
O = 1,
fun(A) ->
add(add(I, A), O)
end.
add_with_closure(A, B) ->
F = return_closure(A),
F(B).
matching([], []) ->
one;
matching([], _) ->
two;
matching(_, []) ->
three;
matching(A, B) ->
{A, B}.
"##;
#[test]
fn simple_add() {
let mut ctx = ctx_from_erl(TEST_ERL_1);
let args = vec![Term::new_i64(1), Term::new_i64(2)];
let result = ctx.call("test", "add", args);
assert!(result.unwrap_return().erl_eq(&Term::Integer(3.into())));
}
#[test]
fn simple_function_call() {
let mut ctx = ctx_from_erl(TEST_ERL_1);
let args = vec![Term::new_i64(1), Term::new_i64(2), Term::new_i64(3)];
let result = ctx.call("test", "add_two", args);
assert!(result.unwrap_return().erl_eq(&Term::Integer(6.into())));
}
#[test]
fn simple_lambda() {
let mut ctx = ctx_from_erl(TEST_ERL_1);
let args = vec![Term::new_i64(1), Term::new_i64(2)];
let result = ctx.call("test", "add_with_closure", args);
assert!(result.unwrap_return().erl_eq(&Term::Integer(4.into())));
}
#[test]
fn simple_pattern_match() {
let mut ctx = ctx_from_erl(TEST_ERL_1);
let args = vec![Term::new_i64(1), Term::new_i64(2)];
let result = ctx.call("test", "matching", args);
assert!(result.unwrap_return().erl_eq(&Term::Tuple(vec![
Term::new_i64(1),
Term::new_i64(2),
])));
let args = vec![Term::Nil, Term::Nil];
let result = ctx.call("test", "matching", args);
assert!(result.unwrap_return().erl_eq(&Term::new_atom("one")));
}
const FACTORIAL_ERL: &str = r##"
-module(test).
-export([factorial/1]).
factorial(0) -> 1;
factorial(N) -> N * factorial(N-1).
"##;
#[test]
fn factorial() {
let mut ctx = ctx_from_erl(FACTORIAL_ERL);
let args = vec![Term::new_i64(10)];
let result = ctx.call("test", "factorial", args);
println!("Res: {:?}", result);
}
//#[test]
fn long_strings() {
let mut ctx = VMState::new();
let mut f = ::std::fs::File::open("../test_data/long_strings.core")
.unwrap();
let mut core = String::new();
f.read_to_string(&mut core).unwrap();
println!("Parsing");
let parsed = ::core_erlang_compiler::parser::parse(&core).unwrap();
}
fn compile_core_file(path: &str) -> Module {
let mut f = ::std::fs::File::open(path)
.unwrap();
let mut core = String::new();
f.read_to_string(&mut core).unwrap();
let parsed = ::core_erlang_compiler::parser::parse(&core).unwrap();
::core_erlang_compiler::ir::from_parsed(&parsed.0)
}
#[test]
fn compiler() {
let result = std::panic::catch_unwind(|| {
let mut ctx = VMState::new();
ctx.add_native_module(::erl_lib::make_erlang());
ctx.add_native_module(::erl_lib::make_os());
ctx.add_native_module(::erl_lib::make_time());
ctx.add_erlang_module(compile_core_file(
"../otp/lib/compiler/ebin/compile.core"));
ctx.add_erlang_module(compile_core_file(
"../otp/lib/stdlib/ebin/proplists.core"));
//"/home/hansihe/proj/checkout/otp/lib/stdlib/ebin/proplists.core"));
ctx.add_erlang_module(compile_core_file(
"../otp/lib/stdlib/ebin/filename.core"));
//"/home/hansihe/proj/checkout/otp/lib/stdlib/ebin/filename.core"));
ctx.add_erlang_module(compile_core_file(
"../otp/lib/stdlib/ebin/epp.core"));
ctx.add_erlang_module(compile_core_file(
"../otp/lib/stdlib/ebin/lists.core"));
//"/home/hansihe/proj/checkout/otp/lib/stdlib/ebin/lists.core"));
ctx.add_nif_overlay(::erl_lib::make_lists());
let args = vec![Term::new_atom("foo.erl")];
ctx.call("compile", "file", args);
});
::trace::dump_trace("trace.json".to_string());
assert!(result.is_ok());
}
================================================
FILE: libeir_interpreter/src/lib.rs
================================================
//#![deny(warnings)]
//! LIR interpreter with zero consideration of performance.
//! Made as an experiment to narrow down relevant implementation
//! details.
mod term;
pub use term::{ErlEq, ErlExactEq, ErlOrd, Pid, Reference, Term, TermType};
pub mod erl_lib;
mod vm;
pub use vm::{VMState, WatchType};
mod process;
mod module;
//mod trace;
================================================
FILE: libeir_interpreter/src/mailbox.rs
================================================
use ::term::{ Term, Pid };
#[derive(Debug)]
pub struct Mailbox {
trap_exits: bool,
messages: Vec<(Pid, Term)>,
}
impl Mailbox {
pub fn new() -> Self {
Mailbox {
trap_exits: false,
messages: vec![],
}
}
pub fn get_trap_exits(&self) -> bool {
self.trap_exits
}
pub fn set_trap_exits(&mut self, val: bool) {
self.trap_exits = val;
}
}
================================================
FILE: libeir_interpreter/src/module.rs
================================================
use std::collections::HashMap;
use std::rc::Rc;
use crate::process::ProcessContext;
use crate::{Term, VMState};
use libeir_intern::Symbol;
use libeir_ir::{Function, FunctionIdent, LiveValues, Module};
pub enum NativeReturn {
Return { term: Rc<Term> },
Throw { typ: Rc<Term>, reason: Rc<Term> },
}
pub struct NativeModule {
pub name: Symbol,
pub functions: HashMap<
(Symbol, usize),
Box<dyn Fn(&VMState, &mut ProcessContext, &[Rc<Term>]) -> NativeReturn>,
>,
}
impl NativeModule {
pub fn new(name: Symbol) -> Self {
NativeModule {
name: name,
functions: HashMap::new(),
}
}
pub fn add_fun(
&mut self,
name: Symbol,
arity: usize,
fun: Box<dyn Fn(&VMState, &mut ProcessContext, &[Rc<Term>]) -> NativeReturn>,
) {
self.functions.insert((name, arity), fun);
}
pub fn has_fun(&self, ident: &FunctionIdent) -> bool {
self.functions.contains_key(&(ident.name.name, ident.arity))
}
}
pub struct ErlangFunction {
pub fun: Function,
pub live: LiveValues,
}
pub struct ErlangModule {
pub name: Symbol,
pub functions: HashMap<FunctionIdent, ErlangFunction>,
}
impl ErlangModule {
pub fn from_eir(module: Module) -> Self {
let functions = module
.index_iter()
.map(|idx| {
let fun_def = &module[idx];
let fun = fun_def.function();
let nfun = ErlangFunction {
live: fun.live_values(),
fun: fun.clone(),
};
(fun.ident().clone(), nfun)
})
.collect();
ErlangModule {
name: module.name().name,
functions,
}
}
}
pub enum ModuleType {
Erlang(ErlangModule, Option<NativeModule>),
Native(NativeModule),
}
================================================
FILE: libeir_interpreter/src/pattern.rs
================================================
use std::collections::HashMap;
use ::term::Term;
use eir::Clause;
use eir::pattern::PatternNode;
use eir::AtomicTerm;
use eir::SSAVariable;
#[derive(Debug, Copy, Clone)]
pub enum MatchState {
MatchClause(usize),
GuardWait(usize),
Finished,
}
impl MatchState {
fn clause_num(&self) -> usize {
match self {
MatchState::MatchClause(num) => *num,
MatchState::GuardWait(num) => *num,
_ => panic!(),
}
}
fn clause_num_mut(&mut self) -> &mut usize {
match self {
MatchState::MatchClause(num) => num,
_ => panic!(),
}
}
fn into_guard(&mut self) {
match *self {
MatchState::MatchClause(num) => *self = MatchState::GuardWait(num),
_ => unreachable!(),
}
}
fn into_body(&mut self) {
match *self {
MatchState::GuardWait(num) => *self = MatchState::MatchClause(num+1),
_ => unreachable!(),
}
}
fn into_finished(&mut self) {
*self = MatchState::Finished;
}
}
#[derive(Debug, Clone)]
pub struct CaseContext {
pub state: MatchState,
pub vars: Vec<Term>,
pub clauses: Vec<Clause>,
pub last_binds: Option<HashMap<SSAVariable, Term>>,
}
fn match_node(term: &Term, node: &PatternNode,
binds: &mut HashMap<SSAVariable, Term>) -> bool {
//println!(" MATCH_NODE: {:?} {:?}", term, node);
match (term, node) {
// Wildcard and purely recursive
(_, PatternNode::Wildcard) => true,
(_, PatternNode::Bind(ssa, i_node)) => {
binds.insert(
*ssa, //binds_ref.iter().find(|(k, _)| k == var_name).unwrap().1,
term.clone()
);
match_node(term, i_node, binds)
},
// Lists
(Term::List(ref t_head, ref t_tail),
PatternNode::List(ref p_head, ref p_tail)) => {
if t_head.len() < p_head.len() {
for (pat, term) in p_head.iter().zip(t_head.iter()) {
if !match_node(term, pat, binds) {
return false;
}
}
let n_p_head: Vec<_> = p_head.iter().skip(t_head.len())
.cloned().collect();
let n_pat = PatternNode::List(n_p_head, p_tail.clone());
return match_node(t_tail, &n_pat, binds);
} else if t_head.len() == p_head.len() {
for (pat, term) in p_head.iter().zip(t_head.iter()) {
if !match_node(term, pat, binds) {
return false;
}
}
return match_node(t_tail, p_tail, binds);
} else { // >
assert!(t_head.len() > p_head.len());
for (pat, term) in p_head.iter().zip(t_head.iter()) {
if !match_node(term, pat, binds) {
return false;
}
}
let head_rest: Vec<_> = t_head.iter().skip(p_head.len())
.cloned().collect();
let rest_term = Term::List(head_rest, t_tail.clone());
let a = match_node(&rest_term, p_tail, binds);
return a;
}
}
// List with empty head
(_, PatternNode::List(ref list, ref tail)) if list.len() == 0 =>
match_node(term, tail, binds),
// Nil ([])
(Term::Nil, PatternNode::Atomic(AtomicTerm::Nil)) => true,
(Term::Nil, _) => false,
(_, PatternNode::Atomic(AtomicTerm::Nil)) => false,
// Tuple
(Term::Tuple(t_entries), PatternNode::Tuple(p_entries)) => {
if t_entries.len() != p_entries.len() {
return false;
}
for (term, pat) in t_entries.iter().zip(p_entries) {
if !match_node(term, pat, binds) {
return false;
}
}
true
}
(_, PatternNode::Tuple(_)) => false,
// Atom
(Term::Atom(v1), PatternNode::Atomic(AtomicTerm::Atom(v2))) => v1 == v2,
(Term::Atom(_), _) => false,
(_, PatternNode::Atomic(AtomicTerm::Atom(_))) => false,
(Term::Integer(ref int),
PatternNode::Atomic(AtomicTerm::Integer(ref pat_int))) => {
println!(" Int pattern {} {}", int, pat_int);
int == pat_int
}
_ => {
::trace::warning("WARNING: Pattern matching incomplete".to_string());
println!(" Warning: Pattern matching incomplete");
false
},
}
}
impl CaseContext {
pub fn new(vars: Vec<Term>, clauses: Vec<Clause>) -> Self {
CaseContext {
state: MatchState::MatchClause(0),
vars: vars,
clauses: clauses,
last_binds: None,
}
}
pub fn do_body(&mut self) -> usize {
let (matched, values) = {
let clause = &self.clauses[self.state.clause_num()];
assert!(clause.patterns.len() == self.vars.len());
//println!("{:?}", clause);
//println!(" {:?}", self.vars);
let mut values: HashMap<SSAVariable, Term> = HashMap::new();
let matched = self.vars.iter()
.zip(&clause.patterns)
.enumerate()
.all(|(idx, (term, pattern))| {
let r = match_node(term, &pattern.node,
&mut values);
println!(" Pattern num: {} {}", idx, r);
r
});
(matched, values)
};
if matched {
let clause_num = self.state.clause_num();
self.state.into_guard();
self.last_binds = Some(values);
clause_num + 1
} else {
*self.state.clause_num_mut() += 1;
if self.state.clause_num() >= self.clauses.len() {
0
} else {
self.do_body()
}
}
//println!("PAT: {:?}", self.clauses[0]);
//println!("TERMS: {:?}", terms);
}
pub fn case_values(&self) -> HashMap<SSAVariable, Term> {
self.last_binds.as_ref().unwrap().clone()
}
pub fn guard_ok(&mut self) {
self.state.into_finished();
}
pub fn guard_fail(&mut self, clause_num: usize) {
assert!(clause_num == self.state.clause_num());
self.state.into_body();
}
}
================================================
FILE: libeir_interpreter/src/process/match.rs
================================================
use libeir_ir::{BasicType, BinaryEntrySpecifier, Block, Endianness, MatchKind};
use libeir_util_binary::BitCarrier;
use libeir_util_binary::{carrier_to_integer, BitSlice, BitVec, Endian};
use crate::module::ErlangFunction;
use crate::term::ErlExactEq;
use crate::Term;
use super::{CallExecutor, TermCall};
pub fn match_op(
exec: &mut CallExecutor,
fun: &ErlangFunction,
branches: &[MatchKind],
block: Block,
) -> TermCall {
let reads = fun.fun.block_reads(block);
let branches_elems = Term::as_value_list(&exec.make_term(fun, reads[0]));
let unpack_term = exec.make_term(fun, reads[1]);
for (idx, kind) in branches.iter().enumerate() {
let branch_args = Term::as_value_list(&exec.make_term(fun, reads[idx + 2]));
match kind {
MatchKind::Value => {
assert!(branch_args.len() == 1);
if unpack_term.erl_exact_eq(&*branch_args[0]) {
return TermCall {
fun: branches_elems[idx].clone(),
args: vec![],
};
}
}
MatchKind::ListCell => {
assert!(branch_args.len() == 0);
match &*unpack_term {
Term::ListCell(head, tail) => {
return TermCall {
fun: branches_elems[idx].clone(),
args: vec![head.clone(), tail.clone()],
};
}
_ => (),
}
}
MatchKind::Tuple(len) => {
assert!(branch_args.len() == 0);
match &*unpack_term {
Term::Tuple(elems) if elems.len() == *len => {
return TermCall {
fun: branches_elems[idx].clone(),
args: elems.clone(),
};
}
_ => (),
}
}
MatchKind::Type(BasicType::Map) => {
assert!(branch_args.len() == 0);
match &*unpack_term {
Term::Map(_) => {
return TermCall {
fun: branches_elems[idx].clone(),
args: vec![],
};
}
_ => (),
}
}
MatchKind::MapItem => {
assert!(branch_args.len() == 1);
match &*unpack_term {
Term::Map(map) => {
if let Some(v) = map.get(&branch_args[0]) {
return TermCall {
fun: branches_elems[idx].clone(),
args: vec![v.clone()],
};
}
}
_ => unreachable!(),
}
}
MatchKind::Binary(BinaryEntrySpecifier::Integer {
unit,
endianness,
signed,
}) => {
let size = branch_args[0].as_usize().unwrap();
let bit_len = (*unit as usize) * size;
let ret = match &*unpack_term {
Term::Binary(bin) => {
if (bin.len() * 8) < bit_len {
continue;
}
let int_slice = BitSlice::with_offset_length(&**bin, 0, bit_len);
let endian = match *endianness {
Endianness::Big => Endian::Big,
Endianness::Little => Endian::Little,
Endianness::Native => Endian::Big,
};
let int = carrier_to_integer(int_slice, *signed, endian);
TermCall {
fun: branches_elems[idx].clone(),
args: vec![
Term::Integer(int).into(),
Term::BinarySlice {
buf: bin.clone(),
bit_offset: bit_len,
bit_length: bin.bit_len() - bit_len,
}
.into(),
],
}
}
Term::BinarySlice {
buf,
bit_offset,
bit_length,
} => {
if *bit_length < bit_len {
continue;
}
let int_slice = BitSlice::with_offset_length(&**buf, *bit_offset, bit_len);
let endian = match *endianness {
Endianness::Big => Endian::Big,
Endianness::Little => Endian::Little,
Endianness::Native => Endian::Big,
};
let int = carrier_to_integer(int_slice, *signed, endian);
TermCall {
fun: branches_elems[idx].clone(),
args: vec![
Term::Integer(int).into(),
Term::BinarySlice {
buf: buf.clone(),
bit_offset: *bit_offset + bit_len,
bit_length: *bit_length - bit_len,
}
.into(),
],
}
}
_ => continue,
};
return ret;
}
MatchKind::Binary(BinaryEntrySpecifier::Bytes { unit }) => {
let size = branch_args[0].as_usize().unwrap_or(1);
let byte_len = (*unit as usize) * size;
match &*unpack_term {
Term::Binary(bin) => {
//if bin.bit_len() % 8 != 0 {
// continue;
//}
return TermCall {
fun: branches_elems[idx].clone(),
args: vec![
unpack_term.clone(),
Term::Binary(BitVec::new().into()).into(),
],
};
}
Term::BinarySlice { bit_length, .. } => {
//if *bit_length % 8 != 0 {
// continue;
//}
return TermCall {
fun: branches_elems[idx].clone(),
args: vec![
unpack_term.clone(),
Term::Binary(BitVec::new().into()).into(),
],
};
}
_ => (),
}
},
MatchKind::Wildcard => {
assert!(branch_args.len() == 0);
return TermCall {
fun: branches_elems[idx].clone(),
args: vec![],
};
}
kind => unimplemented!("{:?}", kind),
}
}
panic!()
}
================================================
FILE: libeir_interpreter/src/process/mod.rs
================================================
use std::any::TypeId;
use std::collections::HashMap;
use std::rc::Rc;
use num_traits::cast::ToPrimitive;
use libeir_intern::Ident;
use libeir_ir::constant::{AtomicTerm, Const, ConstKind};
use libeir_ir::operation::binary_construct::{
BinaryConstructFinish, BinaryConstructPush, BinaryConstructStart,
};
use libeir_ir::MapPutUpdate;
use libeir_ir::{BinOp, Block, FunctionIdent, LogicOp, OpKind, PrimOpKind, Value, ValueKind};
use libeir_ir::{BinaryEntrySpecifier, Endianness};
use libeir_util_binary::{integer_to_carrier, BitSlice, BitVec, Endian};
use crate::module::{ErlangFunction, ErlangModule, ModuleType, NativeModule, NativeReturn};
use crate::term::{ErlEq, MapTerm, Pid, Term};
use crate::vm::VMState;
mod r#match;
#[derive(Debug)]
pub struct TermCall {
pub fun: Rc<Term>,
pub args: Vec<Rc<Term>>,
}
pub enum Continuation {
Term(TermCall),
ReturnOk(Rc<Term>),
ReturnThrow(Rc<Term>, Rc<Term>, Rc<Term>),
}
pub struct CallExecutor {
binds: HashMap<Value, Rc<Term>>,
}
impl CallExecutor {
pub fn new() -> Self {
CallExecutor {
binds: HashMap::new(),
}
}
pub fn run(&mut self, vm: &VMState, proc: &mut ProcessContext, call: TermCall) -> Continuation {
self.binds.clear();
match &*call.fun {
Term::BoundLambda {
ident,
block,
environment,
} => {
let module = &vm.modules[&ident.module.name];
match module {
ModuleType::Erlang(erl, _overlay) => Continuation::Term(
self.run_erlang(vm, erl, ident, Some((*block, &*environment)), &call.args)
.unwrap(),
),
ModuleType::Native(_native) => unreachable!(),
}
}
Term::CapturedFunction { ident } => {
let module = &vm.modules[&ident.module.name];
println!("{}", ident);
match module {
ModuleType::Erlang(erl, overlay) => {
if let Some(native) = overlay {
if let Some(res) = self.run_native(vm, proc, native, ident, &call.args)
{
return Continuation::Term(res);
}
}
Continuation::Term(
self.run_erlang(vm, erl, ident, None, &call.args).unwrap(),
)
}
ModuleType::Native(native) => Continuation::Term(
if let Some(res) = self.run_native(vm, proc, native, ident, &call.args) {
res
} else {
panic!("Could not find native function {}", ident);
},
),
}
}
Term::ReturnOk => {
assert!(call.args.len() == 1);
Continuation::ReturnOk(call.args[0].clone())
}
Term::ReturnThrow => {
assert!(call.args.len() == 3);
Continuation::ReturnThrow(
call.args[0].clone(),
call.args[1].clone(),
call.args[2].clone(),
)
}
// TODO can't call term type, throw exception
_ => unimplemented!(),
}
}
pub fn run_native(
&mut self,
vm: &VMState,
proc: &mut ProcessContext,
native: &NativeModule,
ident: &FunctionIdent,
args: &[Rc<Term>],
) -> Option<TermCall> {
if let Some(n_fun) = native.functions.get(&(ident.name.name, ident.arity)) {
match n_fun(vm, proc, &args[2..]) {
NativeReturn::Return { term } => Some(TermCall {
fun: args[0].clone(),
args: vec![term],
}),
NativeReturn::Throw { typ, reason } => Some(TermCall {
fun: args[1].clone(),
args: vec![typ, reason, Term::Nil.into()],
}),
}
} else {
None
}
}
pub fn run_erlang(
&mut self,
vm: &VMState,
module: &ErlangModule,
ident: &FunctionIdent,
state: Option<(Block, &[Rc<Term>])>,
args: &[Rc<Term>],
) -> Option<TermCall> {
if let Some(fun) = module.functions.get(&ident) {
// Environment
let block = if let Some((block, env)) = state {
let live = &fun.live.live_at(block);
for (v, t) in live.iter().zip(env.iter()) {
self.binds.insert(v, t.clone());
}
assert!(live.iter().count() == env.len());
block
} else {
fun.fun.block_entry()
};
// Insert arguments
let block_arg_vals = fun.fun.block_args(block);
assert!(block_arg_vals.len() == args.len());
for (v, t) in block_arg_vals.iter().zip(args.iter()) {
self.binds.insert(*v, t.clone());
}
// Execute operation
Some(self.run_erlang_op(vm, fun, block))
} else {
None
}
}
fn make_const_term(&self, fun: &ErlangFunction, const_val: Const) -> Rc<Term> {
match fun.fun.cons().const_kind(const_val) {
ConstKind::Atomic(AtomicTerm::Atom(atom)) => Term::Atom(atom.0).into(),
ConstKind::Atomic(AtomicTerm::Int(int)) => Term::Integer(int.0.into()).into(),
ConstKind::Atomic(AtomicTerm::BigInt(int)) => Term::Integer(int.0.clone()).into(),
ConstKind::Atomic(AtomicTerm::Float(flt)) => Term::Float(flt.0.inner().into()).into(),
ConstKind::Atomic(AtomicTerm::Binary(bin)) => {
Term::Binary(Rc::new(bin.0.clone().into())).into()
}
ConstKind::Atomic(AtomicTerm::Nil) => Term::Nil.into(),
ConstKind::ListCell { head, tail } => Term::ListCell(
self.make_const_term(fun, *head),
self.make_const_term(fun, *tail),
)
.into(),
ConstKind::Tuple { entries } => {
let vec = entries
.as_slice(&fun.fun.cons().const_pool)
.iter()
.map(|e| self.make_const_term(fun, *e))
.collect::<Vec<_>>();
Term::Tuple(vec).into()
}
ConstKind::Map { keys, values } => {
assert!(
keys.len(&fun.fun.cons().const_pool) == values.len(&fun.fun.cons().const_pool)
);
let mut map = MapTerm::new();
for (key, val) in keys
.as_slice(&fun.fun.cons().const_pool)
.iter()
.zip(values.as_slice(&fun.fun.cons().const_pool).iter())
{
let key_v = self.make_const_term(fun, *key);
let val_v = self.make_const_term(fun, *val);
map.insert(key_v, val_v);
}
Term::Map(map).into()
}
}
}
fn make_term(&self, fun: &ErlangFunction, value: Value) -> Rc<Term> {
match fun.fun.value_kind(value) {
ValueKind::Block(block) => {
let live = &fun.live.live_at(block);
let mut env = Vec::new();
for v in live.iter() {
assert!(fun.fun.value_argument(v).is_some());
env.push(self.make_term(fun, v));
}
Term::BoundLambda {
ident: fun.fun.ident().clone(),
block,
environment: env,
}
.into()
}
ValueKind::Argument(_, _) => self.binds[&value].clone(),
ValueKind::Const(cons) => self.make_const_term(fun, cons),
ValueKind::PrimOp(prim) => {
let reads = fun.fun.primop_reads(prim);
match fun.fun.primop_kind(prim) {
PrimOpKind::ValueList => {
let terms: Vec<_> = reads.iter().map(|r| self.make_term(fun, *r)).collect();
Term::ValueList(terms).into()
}
PrimOpKind::Tuple => {
let terms: Vec<_> = reads.iter().map(|r| self.make_term(fun, *r)).collect();
Term::Tuple(terms).into()
}
PrimOpKind::ListCell => {
assert!(reads.len() == 2);
let head = self.make_term(fun, reads[0]);
let tail = self.make_term(fun, reads[1]);
Term::ListCell(head, tail).into()
}
PrimOpKind::BinOp(BinOp::Equal) => {
assert!(reads.len() == 2);
let lhs = self.make_term(fun, reads[0]);
let rhs = self.make_term(fun, reads[1]);
Term::new_bool(lhs.erl_eq(&*rhs)).into()
}
PrimOpKind::LogicOp(LogicOp::And) => {
let mut acc = true;
for read in reads.iter() {
let term = self.make_term(fun, *read);
let res = term.as_boolean().unwrap();
acc = acc & res;
}
Term::new_bool(acc).into()
}
PrimOpKind::LogicOp(LogicOp::Or) => {
let mut acc = false;
for read in reads.iter() {
let term = self.make_term(fun, *read);
let res = term.as_boolean().unwrap();
acc = acc | res;
}
Term::new_bool(acc).into()
}
PrimOpKind::CaptureFunction => {
let module = self.make_term(fun, reads[0]).as_atom().unwrap();
let name = self.make_term(fun, reads[1]).as_atom().unwrap();
let arity = self.make_term(fun, reads[2]).as_usize().unwrap();
let ident = FunctionIdent {
module: Ident::with_empty_span(module),
name: Ident::with_empty_span(name),
arity,
};
Term::CapturedFunction { ident }.into()
}
kind => unimplemented!("{:?}", kind),
}
}
}
}
pub fn run_erlang_op(&mut self, _vm: &VMState, fun: &ErlangFunction, block: Block) -> TermCall {
let reads = fun.fun.block_reads(block);
println!("OP: {:?}", fun.fun.block_kind(block).unwrap());
match fun.fun.block_kind(block).unwrap() {
OpKind::Call(_) => TermCall {
fun: self.make_term(fun, reads[0]),
args: reads
.iter()
.skip(1)
.map(|r| self.make_term(fun, *r))
.collect(),
},
OpKind::UnpackValueList(num) => {
assert!(reads.len() == 2);
let term = self.make_term(fun, reads[1]);
match &*term {
Term::ValueList(items) => {
assert!(items.len() == *num);
TermCall {
fun: self.make_term(fun, reads[0]),
args: items.clone(),
}
}
_ => TermCall {
fun: self.make_term(fun, reads[0]),
args: vec![term],
},
}
}
OpKind::IfBool => {
let call_n = if reads.len() == 4 {
let bool_term = self.make_term(fun, reads[3]);
match bool_term.as_boolean() {
Some(true) => 0,
Some(false) => 1,
None => 2,
}
} else if reads.len() == 3 {
let bool_term = self.make_term(fun, reads[2]);
match bool_term.as_boolean() {
Some(true) => 0,
Some(false) => 1,
None => unreachable!(),
}
} else {
unreachable!()
};
TermCall {
fun: self.make_term(fun, reads[call_n]),
args: vec![],
}
}
OpKind::TraceCaptureRaw => TermCall {
fun: self.make_term(fun, reads[0]),
args: vec![Term::Nil.into()],
},
OpKind::Match { branches } => self::r#match::match_op(self, fun, branches, block),
OpKind::Dyn(dyn_op) => {
let tid = dyn_op.type_id();
match () {
_ if tid == TypeId::of::<BinaryConstructStart>() => TermCall {
fun: self.make_term(fun, reads[0]),
args: vec![Term::Binary(Default::default()).into()],
},
_ if tid == TypeId::of::<BinaryConstructPush>() => {
let ok_cont = reads[0];
let err_cont = reads[1];
let bin_ref = reads[2];
let value = reads[3];
let size = reads.get(4);
let bin_push = dyn_op.downcast_ref::<BinaryConstructPush>().unwrap();
let specifier = bin_push.specifier;
let bin_term = self.make_term(fun, bin_ref);
let mut bin = match &*bin_term {
Term::Binary(bin) => (**bin).clone(),
Term::BinarySlice {
buf,
bit_offset,
bit_length,
} => {
let slice =
BitSlice::with_offset_length(&**buf, *bit_offset, *bit_length);
let mut new = BitVec::new();
new.push(slice);
new
}
_ => panic!(),
};
let val_term = self.make_term(fun, reads[3]);
assert!(reads.len() == 4 || reads.len() == 5);
let size_term = reads.get(4).map(|r| self.make_term(fun, *r));
match specifier {
BinaryEntrySpecifier::Integer {
signed: _,
unit,
endianness,
} => {
let size = size_term.unwrap().as_usize().unwrap();
let bit_size = unit as usize * size;
let endian = match endianness {
Endianness::Big => Endian::Big,
Endianness::Little => Endian::Little,
Endianness::Native => Endian::Big,
};
let val = val_term.as_integer().unwrap().clone();
let carrier = integer_to_carrier(val, bit_size, endian);
bin.push(carrier);
}
BinaryEntrySpecifier::Float {
endianness: Endianness::Big,
unit,
} => {
let size = size_term.unwrap().as_usize().unwrap();
let bit_size = unit as usize * size;
assert!(bit_size == 32 || bit_size == 64);
let num = match &*val_term {
Term::Float(flt) => flt.0,
Term::Integer(int) => {
let int_f = int.to_i64().unwrap();
int_f as f64
}
_ => panic!(),
};
match bit_size {
32 => bin.push(&num),
64 => bin.push(&num),
_ => unreachable!(),
}
}
BinaryEntrySpecifier::Bytes { unit: 1 } => {
let binary = val_term.as_binary().unwrap();
if let Some(size_term) = size_term {
dbg!(&size_term, &binary);
assert!(size_term.as_usize().unwrap() == binary.len());
}
bin.push(binary);
}
BinaryEntrySpecifier::Bits { unit: 1 } => {
let binary = val_term.as_binary().unwrap();
// TODO validate size
bin.push(binary);
}
k => unimplemented!("{:?}", k),
}
return TermCall {
fun: self.make_term(fun, ok_cont),
args: vec![Term::Binary(bin.into()).into()],
};
}
_ if tid == TypeId::of::<BinaryConstructFinish>() => {
TermCall {
fun: self.make_term(fun, reads[0]),
args: vec![self.make_term(fun, reads[1])],
}
},
_ => unimplemented!(),
}
}
//OpKind::BinaryPush { specifier } => {
// let bin_term = self.make_term(fun, reads[2]);
// let mut bin = match &*bin_term {
// Term::Binary(bin) => (**bin).clone(),
// Term::BinarySlice { buf, bit_offset, bit_length } => {
// let slice = BitSlice::with_offset_length(
// &**buf, *bit_offset, *bit_length);
// let mut new = BitVec::new();
// new.push(slice);
// new
// }
// _ => panic!(),
// };
// let val_term = self.make_term(fun, reads[3]);
// assert!(reads.len() == 4 || reads.len() == 5);
// let size_term = reads.get(4).map(|r| self.make_term(fun, *r));
// match specifier {
// BinaryEntrySpecifier::Integer {
// signed: _, unit, endianness } =>
// {
// let size = size_term.unwrap().as_usize().unwrap();
// let bit_size = *unit as usize * size;
// let endian = match *endianness {
// Endianness::Big => Endian::Big,
// Endianness::Little => Endian::Little,
// Endianness::Native => Endian::Big,
// };
// let val = val_term.as_integer().unwrap().clone();
// let carrier = integer_to_carrier(
// val, bit_size, endian);
// bin.push(carrier);
// }
// BinaryEntrySpecifier::Float {
// endianness: Endianness::Big, unit } =>
// {
// let size = size_term.unwrap().as_usize().unwrap();
// let bit_size = *unit as usize * size;
// assert!(bit_size == 32 || bit_size == 64);
// let num = match &*val_term {
// Term::Float(flt) => flt.0,
// Term::Integer(int) => {
// let int_f = int.to_i64().unwrap();
// int_f as f64
// }
// _ => panic!(),
// };
// match bit_size {
// 32 => bin.push(&num),
// 64 => bin.push(&num),
// _ => unreachable!(),
// }
// }
// BinaryEntrySpecifier::Bytes { unit: 1 } => {
// let binary = val_term.as_binary().unwrap();
// if let Some(size_term) = size_term {
// dbg!(&size_term, &binary);
// assert!(size_term.as_usize().unwrap() == binary.len());
// }
// bin.push(binary);
// }
// k => unimplemented!("{:?}", k),
// }
// return TermCall {
// fun: self.make_term(fun, reads[0]),
// args: vec![Term::Binary(bin.into()).into()],
// };
//}
OpKind::MapPut { action } => {
let map_term = self.make_term(fun, reads[2]);
println!("{:#?}", map_term);
let mut map = map_term.as_map().unwrap().clone();
let mut idx = 3;
for action in action.iter() {
let key = self.make_term(fun, reads[idx]);
let val = self.make_term(fun, reads[idx + 1]);
idx += 2;
let replaced = map.insert(key, val);
if *action == MapPutUpdate::Update {
assert!(replaced)
}
}
TermCall {
fun: self.make_term(fun, reads[0]),
args: vec![Term::Map(map).into()],
}
}
OpKind::Unreachable => {
println!("==== Reached OpKind::Unreachable! ====");
println!("Fun: {} Block: {}", fun.fun.ident(), block);
unreachable!();
}
kind => unimplemented!("{:?}", kind),
}
}
}
pub struct ProcessContext {
pub pid: Pid,
pub dict: Vec<(Rc<Term>, Rc<Term>)>,
}
impl ProcessContext {
pub fn new(pid: Pid) -> Self {
ProcessContext {
pid,
dict: Vec::new(),
}
}
}
================================================
FILE: libeir_interpreter/src/receive.rs
================================================
use ::term::Term;
#[derive(Debug)]
pub struct ReceiveContext {
}
impl ReceiveContext {
pub fn new(timeout: Term) -> Self {
// TODO: Timeout
ReceiveContext {
}
}
}
================================================
FILE: libeir_interpreter/src/term.rs
================================================
use std::cmp::{Ord, Ordering};
use std::collections::HashMap;
use std::hash::{Hash, Hasher};
use std::rc::Rc;
use libeir_intern::{LocalInternedString, Symbol};
use libeir_ir::{Block, FunctionIdent};
use libeir_util_binary::{BitSlice, BitVec};
use num_bigint::BigInt;
use num_traits::cast::ToPrimitive;
#[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
pub struct Pid(pub usize);
#[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
pub struct Reference(pub usize);
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum TermType {
Nil,
Integer,
Float,
Atom,
Tuple,
ListCell,
Map,
Pid,
Reference,
Binary,
BoundLambda,
CapturedFunction,
// Internal
ValueList,
ReturnOk,
ReturnThrow,
}
#[derive(Debug, Copy, Clone, PartialOrd)]
pub struct FloatTerm(pub f64);
impl PartialEq for FloatTerm {
fn eq(&self, other: &FloatTerm) -> bool {
self.0.to_bits() == other.0.to_bits()
}
}
impl Ord for FloatTerm {
fn cmp(&self, other: &FloatTerm) -> Ordering {
self.partial_cmp(other).unwrap()
}
}
impl Eq for FloatTerm {}
impl Hash for FloatTerm {
fn hash<T: Hasher>(&self, state: &mut T) {
self.0.to_bits().hash(state)
}
}
impl From<f64> for FloatTerm {
fn from(src: f64) -> Self {
FloatTerm(src)
}
}
#[derive(Debug, Clone)]
pub struct MapTerm {
map: HashMap<Rc<Term>, Rc<Term>>,
sorted: Vec<(Rc<Term>, Rc<Term>)>,
}
impl MapTerm {
pub fn new() -> MapTerm {
MapTerm {
map: HashMap::new(),
sorted: Vec::new(),
}
}
pub fn insert(&mut self, key: Rc<Term>, val: Rc<Term>) -> bool {
self.map.insert(key.clone(), val.clone());
match self.sorted.binary_search_by(|(k, _)| k.cmp(&key)) {
Ok(idx) => {
self.sorted[idx] = (key, val);
true
}
Err(idx) => {
self.sorted.insert(idx, (key, val));
false
}
}
}
pub fn get(&self, key: &Rc<Term>) -> Option<Rc<Term>> {
self.map.get(key).cloned()
}
pub fn len(&self) -> usize {
self.map.len()
}
}
impl PartialEq for MapTerm {
fn eq(&self, other: &MapTerm) -> bool {
self.sorted == other.sorted
}
}
impl Eq for MapTerm {}
impl PartialOrd for MapTerm {
fn partial_cmp(&self, other: &MapTerm) -> Option<Ordering> {
self.sorted.partial_cmp(&other.sorted)
}
}
impl Ord for MapTerm {
fn cmp(&self, other: &MapTerm) -> Ordering {
self.partial_cmp(other).unwrap()
}
}
impl Hash for MapTerm {
fn hash<H: Hasher>(&self, state: &mut H) {
self.sorted.hash(state)
}
}
#[derive(Debug, Clone)]
pub enum Term {
Nil,
Integer(BigInt),
Float(FloatTerm),
Atom(Symbol),
Tuple(Vec<Rc<Term>>),
ListCell(Rc<Term>, Rc<Term>),
Map(MapTerm),
Pid(Pid),
Reference(Reference),
Binary(Rc<BitVec>),
BinarySlice {
buf: Rc<BitVec>,
bit_offset: usize,
bit_length: usize,
},
BoundLambda {
ident: FunctionIdent,
block: Block,
environment: Vec<Rc<Term>>,
},
CapturedFunction {
ident: FunctionIdent,
},
// Internal
ValueList(Vec<Rc<Term>>),
ReturnOk,
ReturnThrow,
}
impl Term {
fn order_idx(&self) -> usize {
// number < atom < reference < fun < port < pid
// < tuple < map < nil < list < bit string
match self {
Term::Integer(_) => 1,
Term::Float(_) => 1,
Term::Atom(_) => 2,
Term::Reference(_) => 3,
Term::BoundLambda { .. } => 4,
Term::CapturedFunction { .. } => 4,
//Term::Port(_) => 5,
Term::Pid(_) => 6,
Term::Tuple(_) => 7,
Term::Map(_) => 8,
Term::Nil => 9,
Term::ListCell(_, _) => 10,
Term::Binary(_) => 11,
Term::BinarySlice { .. } => 11,
_ => panic!(),
}
}
}
impl Eq for Term {}
impl PartialEq for Term {
fn eq(&self, other: &Self) -> bool {
use Term::*;
match (self, other) {
(Nil, Nil) => true,
(Integer(l), Integer(r)) => l == r,
(Float(l), Float(r)) => l == r,
(Atom(l), Atom(r)) => l == r,
(Tuple(l), Tuple(r)) => l == r,
(ListCell(lh, lt), ListCell(rh, rt)) => lh == rh && lt == rt,
(Map(l), Map(r)) => l == r,
(Pid(l), Pid(r)) => l == r,
(Reference(l), Reference(r)) => l == r,
(Binary(l), Binary(r)) => l == r,
(
Binary(l),
BinarySlice {
buf,
bit_offset,
bit_length,
},
) => {
let rs = BitSlice::with_offset_length(&**buf, *bit_offset, *bit_length);
&**l == &rs
}
(
BinarySlice {
buf,
bit_offset,
bit_length,
},
Binary(r),
) => {
let ls = BitSlice::with_offset_length(&**buf, *bit_offset, *bit_length);
&ls == &**r
}
(
BinarySlice {
buf: lb,
bit_offset: lo,
bit_length: ll,
},
BinarySlice {
buf: rb,
bit_offset: ro,
bit_length: rl,
},
) => {
let ls = BitSlice::with_offset_length(&**lb, *lo, *ll);
let rs = BitSlice::with_offset_length(&**rb, *ro, *rl);
&ls == &rs
}
(
BoundLambda {
ident: li,
block: lb,
environment: le,
},
BoundLambda {
ident: ri,
block: rb,
environment: re,
},
) => li == ri && lb == rb && le == re,
(CapturedFunction { ident: li }, CapturedFunction { ident: ri }) => li == ri,
(ValueList(l), ValueList(r)) => l == r,
(ReturnOk, ReturnOk) => true,
(ReturnThrow, ReturnThrow) => true,
_ => false,
}
}
}
impl Ord for Term {
fn cmp(&self, other: &Self) -> Ordering {
self.partial_cmp(other).unwrap()
}
}
impl PartialOrd for Term {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
use Term::*;
match (self, other) {
(Nil, Nil) => Some(Ordering::Equal),
(Integer(l), Integer(r)) => l.partial_cmp(r),
(Float(l), Float(r)) => l.partial_cmp(r),
(Atom(l), Atom(r)) => l.partial_cmp(r),
(Tuple(l), Tuple(r)) => l.partial_cmp(r),
(ListCell(lh, lt), ListCell(rh, rt)) => match lh.partial_cmp(rh) {
Some(Ordering::Equal) | None => lt.partial_cmp(rt),
non_eq => non_eq,
},
(Map(l), Map(r)) => l.partial_cmp(r),
(Pid(l), Pid(r)) => l.partial_cmp(r),
(Reference(l), Reference(r)) => l.partial_cmp(r),
(Binary(l), Binary(r)) => l.partial_cmp(r),
(
Binary(l),
BinarySlice {
buf,
bit_offset,
bit_length,
},
) => {
let rs = BitSlice::with_offset_length(&**buf, *bit_offset, *bit_length);
(&**l).partial_cmp(&rs)
}
(
BinarySlice {
buf,
bit_offset,
bit_length,
},
Binary(r),
) => {
let ls = BitSlice::with_offset_length(&**buf, *bit_offset, *bit_length);
ls.partial_cmp(&**r)
}
(
BinarySlice {
buf: lb,
bit_offset: lo,
bit_length: ll,
},
BinarySlice {
buf: rb,
bit_offset: ro,
bit_length: rl,
},
) => {
let ls = BitSlice::with_offset_length(&**lb, *lo, *ll);
let rs = BitSlice::with_offset_length(&**rb, *ro, *rl);
ls.partial_cmp(&rs)
}
(
BoundLambda {
ident: li,
block: lb,
environment: le,
},
BoundLambda {
ident: ri,
block: rb,
environment: re,
},
) => match li.partial_cmp(ri) {
Some(Ordering::Equal) | None => match lb.partial_cmp(rb) {
Some(Ordering::Equal) | None => le.partial_cmp(re),
non_eq => non_eq,
},
non_eq => non_eq,
},
(CapturedFunction { ident: li }, CapturedFunction { ident: ri }) => li.partial_cmp(ri),
(ValueList(l), ValueList(r)) => l.partial_cmp(r),
(ReturnOk, ReturnOk) => Some(Ordering::Equal),
(ReturnThrow, ReturnThrow) => Some(Ordering::Equal),
(l, r) => l.order_idx().partial_cmp(&r.order_idx()),
}
}
}
impl Hash for Term {
fn hash<H: Hasher>(&self, state: &mut H) {
use Term::*;
self.get_type().hash(state);
match self {
Nil => (),
Integer(i) => i.hash(state),
Float(f) => f.hash(state),
Atom(a) => a.hash(state),
Tuple(t) => t.hash(state),
ListCell(h, t) => {
h.hash(state);
t.hash(state);
}
Map(t) => t.hash(state),
Pid(t) => t.hash(state),
Reference(t) => t.hash(state),
Binary(t) => t.hash(state),
BinarySlice {
buf,
bit_offset,
bit_length,
} => {
let ls = BitSlice::with_offset_length(&**buf, *bit_offset, *bit_length);
ls.hash(state);
}
BoundLambda {
ident,
block,
environment,
} => {
ident.hash(state);
block.hash(state);
environment.hash(state);
}
CapturedFunction { ident } => ident.hash(state),
ValueList(i) => i.hash(state),
ReturnOk => (),
ReturnThrow => (),
}
}
}
impl From<i64> for Term {
fn from(num: i64) -> Self {
Term::Integer(num.into())
}
}
pub enum ListIteratorItem {
Elem(Rc<Term>),
Tail(Rc<Term>),
}
pub struct ListTermIterator {
term: Option<Rc<Term>>,
}
impl Iterator for ListTermIterator {
type Item = ListIteratorItem;
fn next(&mut self) -> Option<ListIteratorItem> {
if let Some(term) = self.term.take() {
match &*term {
Term::ListCell(head, tail) => {
self.term = Some(tail.clone());
Some(ListIteratorItem::Elem(head.clone()))
}
_ => {
self.term = None;
Some(ListIteratorItem::Tail(term.clone()))
}
}
} else {
None
}
}
}
impl Term {
pub fn new_i64(num: i64) -> Self {
Term::Integer(num.into())
}
pub fn new_usize(num: usize) -> Self {
Term::Integer(num.into())
}
pub fn new_atom(string: &str) -> Self {
Term::Atom(Symbol::intern(string))
}
pub fn new_bool(val: bool) -> Self {
if val {
Term::new_atom("true")
} else {
Term::new_atom("false")
}
}
pub fn slice_to_list(head: &[Rc<Term>], tail: Rc<Term>) -> Rc<Term> {
let mut acc = tail;
for term in head.iter().rev() {
acc = Term::ListCell(term.clone(), acc).into();
}
acc
}
fn extend_erl_string(&self, buf: &mut String) -> bool {
match self {
Term::Integer(val) => {
buf.push(val.to_u8().unwrap() as char);
true
}
Term::ListCell(_head, _tail) => {
unimplemented!()
//for item in head {
// if !item.extend_erl_string(buf) {
// return false;
// }
//}
//return tail.extend_erl_string(buf);
}
Term::Nil => true,
_ => false,
}
}
pub fn get_erl_string(&self) -> Option<String> {
let mut buf = String::new();
if self.extend_erl_string(&mut buf) {
Some(buf)
} else {
None
}
}
pub fn atom_str<'a>(&'a self) -> LocalInternedString {
if let Term::Atom(ref atom) = *self {
atom.as_str()
} else {
panic!();
}
}
pub fn is_nil(&self) -> bool {
match self {
Term::Nil => true,
_ => false,
}
}
pub fn get_type(&self) -> TermType {
match self {
Term::Binary(_) => TermType::Binary,
Term::BinarySlice { .. } => TermType::Binary,
Term::Nil => TermType::Nil,
Term::Pid(_) => TermType::Pid,
Term::Reference(_) => TermType::Reference,
Term::Integer(_) => TermType::Integer,
Term::Float(_) => TermType::Float,
Term::Atom(_) => TermType::Atom,
Term::Tuple(_) => TermType::Tuple,
Term::ListCell(_, _) => TermType::ListCell,
Term::Map(_) => TermType::Map,
Term::BoundLambda { .. } => TermType::BoundLambda,
Term::CapturedFunction { .. } => TermType::CapturedFunction,
Term::ValueList(_) => TermType::ValueList,
Term::ReturnOk => TermType::ReturnOk,
Term::ReturnThrow => TermType::ReturnThrow,
}
}
pub fn as_boolean(&self) -> Option<bool> {
if let Term::Atom(ref val) = self {
let is_truthy = *val == Symbol::intern("true");
let is_falsey = *val == Symbol::intern("false");
if is_truthy ^ is_falsey {
Some(is_truthy)
} else {
None
}
} else {
None
}
}
pub fn as_i64(&self) -> Option<i64> {
if let Term::Integer(ref bigint) = self {
Some(bigint.to_i64().unwrap())
} else {
None
}
}
pub fn as_usize(&self) -> Option<usize> {
if let Term::Integer(ref bigint) = self {
Some(bigint.to_usize().unwrap())
} else {
None
}
}
pub fn as_integer(&self) -> Option<&BigInt> {
if let Term::Integer(ref bigint) = self {
Some(bigint)
} else {
None
}
}
pub fn as_atom(&self) -> Option<Symbol> {
if let Term::Atom(ref atom) = self {
Some(atom.clone())
} else {
None
}
}
pub fn as_tuple(&self) -> Option<&[Rc<Term>]> {
if let Term::Tuple(tup) = self {
Some(tup)
} else {
None
}
}
pub fn as_binary(&self) -> Option<&BitVec> {
if let Term::Binary(bin) = self {
Some(bin)
} else {
None
}
}
pub fn as_map(&self) -> Option<&MapTerm> {
if let Term::Map(bin) = self {
Some(bin)
} else {
None
}
}
pub fn list_iter(term: &Rc<Term>) -> ListTermIterator {
ListTermIterator {
term: Some(term.clone()),
}
}
//fn join_list(&self, list: &mut Vec<Rc<Term>>) -> Term {
// match self {
// Term::ListCell(head, tail) => {
// list.extend(head.iter().cloned());
// tail.join_list(list)
// }
// _ => self.clone()
// }
//}
pub fn as_inproper_list(term: &Rc<Term>) -> (Vec<Rc<Term>>, Rc<Term>) {
let mut list = Vec::new();
for item
gitextract_fonefwfl/
├── .gitignore
├── .gitmodules
├── DOCS.md
├── LICENSE.md
├── README.md
├── ROADMAP.org
├── azure-pipelines.yml
├── ci/
│ ├── azure-clone-patch-otp.yml
│ ├── azure-install-dependencies.yml
│ ├── azure-install-rust.yml
│ └── azure-test.yml
├── deny.toml
├── libeir_diagnostics/
│ ├── Cargo.toml
│ └── src/
│ ├── codemap.rs
│ ├── filename.rs
│ ├── index.rs
│ ├── lib.rs
│ ├── source.rs
│ └── span.rs
├── libeir_frontend/
│ ├── Cargo.toml
│ ├── README.md
│ └── src/
│ ├── abstr_erlang.rs
│ ├── eir.rs
│ ├── erlang.rs
│ └── lib.rs
├── libeir_intern/
│ ├── Cargo.toml
│ └── src/
│ ├── arena.rs
│ ├── lib.rs
│ └── symbol.rs
├── libeir_interpreter/
│ ├── Cargo.toml
│ ├── README.md
│ └── src/
│ ├── erl_lib/
│ │ ├── erlang.rs
│ │ ├── file.rs
│ │ ├── lists.rs
│ │ ├── maps.rs
│ │ ├── math.rs
│ │ ├── mod.rs
│ │ └── os.rs
│ ├── erl_tests/
│ │ └── mod.rs
│ ├── lib.rs
│ ├── mailbox.rs
│ ├── module.rs
│ ├── pattern.rs
│ ├── process/
│ │ ├── match.rs
│ │ └── mod.rs
│ ├── receive.rs
│ ├── term.rs
│ ├── trace/
│ │ ├── dummy.rs
│ │ ├── mod.rs
│ │ └── trace.rs
│ └── vm.rs
├── libeir_ir/
│ ├── Cargo.toml
│ ├── build.rs
│ └── src/
│ ├── algo/
│ │ ├── equality.rs
│ │ ├── func_tree.rs
│ │ ├── live.rs
│ │ ├── mangle/
│ │ │ ├── datatypes.rs
│ │ │ ├── mod.rs
│ │ │ ├── receiver.rs
│ │ │ └── tests.rs
│ │ ├── mod.rs
│ │ ├── op_branches.rs
│ │ └── validate.rs
│ ├── binary.rs
│ ├── constant/
│ │ ├── atomic.rs
│ │ ├── float.rs
│ │ └── mod.rs
│ ├── dialect/
│ │ └── mod.rs
│ ├── function/
│ │ ├── builder/
│ │ │ ├── mod.rs
│ │ │ ├── op.rs
│ │ │ └── primop.rs
│ │ ├── format.rs
│ │ ├── location.rs
│ │ ├── mod.rs
│ │ ├── op.rs
│ │ ├── pool_container.rs
│ │ ├── primop.rs
│ │ ├── serialize.rs
│ │ └── value.rs
│ ├── graph/
│ │ ├── block_graph.rs
│ │ ├── control_flow_graph.rs
│ │ ├── live_block_graph.rs
│ │ └── mod.rs
│ ├── ir_construct_macro.rs
│ ├── lib.rs
│ ├── module.rs
│ ├── operation/
│ │ ├── binary_construct.rs
│ │ ├── case.rs
│ │ ├── mod.rs
│ │ └── receive.rs
│ ├── pattern/
│ │ ├── fmt.rs
│ │ └── mod.rs
│ ├── text/
│ │ ├── ast/
│ │ │ ├── mod.rs
│ │ │ └── raise.rs
│ │ ├── dot_printer.rs
│ │ ├── lower/
│ │ │ ├── location.rs
│ │ │ └── mod.rs
│ │ ├── mod.rs
│ │ ├── parse_dyn/
│ │ │ └── mod.rs
│ │ ├── parser/
│ │ │ ├── errors.rs
│ │ │ ├── grammar.lalrpop
│ │ │ ├── lexer.rs
│ │ │ └── mod.rs
│ │ ├── printer/
│ │ │ ├── constant.rs
│ │ │ ├── mod.rs
│ │ │ └── operation.rs
│ │ └── printer.old.rs
│ └── traits/
│ ├── mod.rs
│ ├── op_branches.rs
│ ├── parser.rs
│ └── printer.rs
├── libeir_lowerutils/
│ ├── Cargo.toml
│ └── src/
│ ├── lib.rs
│ └── tests.rs
├── libeir_passes/
│ ├── Cargo.toml
│ └── src/
│ ├── compile_pattern/
│ │ ├── erlang_pattern_provider.rs
│ │ ├── lower_cfg.rs
│ │ ├── mod.rs
│ │ └── tests.rs
│ ├── dummy_location.rs
│ ├── lib.rs
│ ├── naive_inline_closures/
│ │ ├── mod.rs
│ │ └── tests.rs
│ ├── simplify_cfg/
│ │ ├── analyze/
│ │ │ ├── call.rs
│ │ │ ├── if_bool.rs
│ │ │ ├── mod.rs
│ │ │ └── unpack_value_list.rs
│ │ ├── chain_graph/
│ │ │ ├── mod.rs
│ │ │ └── synthesis/
│ │ │ ├── compound.rs
│ │ │ ├── mod.rs
│ │ │ ├── simple.rs
│ │ │ ├── single.rs
│ │ │ └── terminating_target.rs
│ │ ├── mod.rs
│ │ ├── rewrite.rs
│ │ └── tests.rs
│ ├── util.rs
│ └── validate.rs
├── libeir_syntax_core/
│ ├── Cargo.toml
│ ├── build.rs
│ └── src/
│ ├── ast.rs
│ ├── lexer.rs
│ ├── lib.rs
│ ├── lower_hir.rs
│ └── parser/
│ ├── grammar.lalrpop
│ ├── grammar.rs
│ └── mod.rs
├── libeir_syntax_erl/
│ ├── .gitignore
│ ├── Cargo.toml
│ ├── build.rs
│ └── src/
│ ├── abstr/
│ │ ├── lower.rs
│ │ └── mod.rs
│ ├── evaluator.rs
│ ├── lexer/
│ │ ├── errors.rs
│ │ ├── lexer.rs
│ │ ├── mod.rs
│ │ └── token.rs
│ ├── lib.rs
│ ├── lower/
│ │ ├── errors.rs
│ │ ├── exception_handler_stack.rs
│ │ ├── expr/
│ │ │ ├── binary.rs
│ │ │ ├── binary_expr.rs
│ │ │ ├── case.rs
│ │ │ ├── catch.rs
│ │ │ ├── comprehension.rs
│ │ │ ├── literal.rs
│ │ │ ├── map.rs
│ │ │ ├── mod.rs
│ │ │ ├── receive.rs
│ │ │ └── record.rs
│ │ ├── mod.rs
│ │ ├── pattern/
│ │ │ ├── mod.rs
│ │ │ └── tree/
│ │ │ ├── from_expr.rs
│ │ │ ├── lower.rs
│ │ │ ├── merge.rs
│ │ │ ├── mod.rs
│ │ │ └── promote_values.rs
│ │ ├── scope.rs
│ │ └── tests.rs
│ ├── parser/
│ │ ├── ast/
│ │ │ ├── attributes.rs
│ │ │ ├── expr.rs
│ │ │ ├── functions.rs
│ │ │ ├── mod.rs
│ │ │ ├── module.rs
│ │ │ └── types.rs
│ │ ├── binary.rs
│ │ ├── errors.rs
│ │ ├── grammar.lalrpop
│ │ ├── macros.rs
│ │ └── mod.rs
│ ├── preprocessor/
│ │ ├── directive.rs
│ │ ├── directives.rs
│ │ ├── errors.rs
│ │ ├── macros.rs
│ │ ├── mod.rs
│ │ ├── preprocessor.rs
│ │ ├── token_reader.rs
│ │ ├── token_stream.rs
│ │ └── types.rs
│ └── util/
│ ├── binary/
│ │ ├── mod.rs
│ │ └── static.rs
│ ├── encoding.rs
│ ├── escape_stm.rs
│ ├── mod.rs
│ ├── string.rs
│ └── string_tokenizer.rs
├── libeir_tests/
│ ├── Cargo.toml
│ ├── shadowing.erl
│ └── src/
│ ├── control_flow/
│ │ ├── accumulate_list.rs
│ │ ├── fib.rs
│ │ ├── get_values.rs
│ │ ├── mod.rs
│ │ ├── nth_root.rs
│ │ └── shadowing.rs
│ ├── ct_runner.rs
│ ├── errors.rs
│ ├── lib.rs
│ ├── list_comprehensions.rs
│ ├── otp/
│ │ └── mod.rs
│ ├── patterns.rs
│ └── records.rs
├── otp_build/
│ ├── bs_match_SUITE.erl
│ ├── bs_match_SUITE.erl.patch
│ ├── bs_match_SUITE_patched.erl
│ ├── otp_build_core.patch
│ ├── patch_build_otp.sh
│ └── patch_tests.sh
├── test_data/
│ ├── Elixir.Enum.erl
│ ├── README.md
│ ├── application_controller.core
│ ├── basic_module.core
│ ├── basic_module.erl
│ ├── basic_regress/
│ │ ├── enum_aggregate.core
│ │ ├── function_capture_1.core
│ │ ├── line_annotation_fail_1.core
│ │ └── type_construction_fail_1.core
│ ├── compile.core
│ ├── compile_messages_per_file.core
│ ├── compile_stripped.core
│ ├── compile_stripped_small.core
│ ├── factorial.core
│ ├── factorial.erl
│ ├── function_capture.core
│ ├── function_capture.erl
│ ├── gen_server.core
│ ├── language_test.core
│ ├── language_test.erl
│ ├── long_strings.core
│ ├── long_strings.core.bak
│ ├── map_test.core
│ ├── map_test.erl
│ ├── maps.abstr
│ ├── maps.erl
│ ├── match.core
│ ├── match.erl
│ ├── match_SUITE.abstr
│ ├── match_SUITE.erl
│ ├── test.core
│ ├── test.erl
│ ├── testing.core
│ └── testing.erl
├── tools/
│ ├── Cargo.toml
│ └── src/
│ └── compile.rs
└── util/
├── any_map/
│ ├── Cargo.toml
│ └── src/
│ ├── any_any_map.rs
│ ├── any_map.rs
│ └── lib.rs
├── libeir_etf/
│ ├── Cargo.toml
│ ├── src/
│ │ ├── constants.rs
│ │ ├── decoder.rs
│ │ ├── encoder.rs
│ │ ├── lib.rs
│ │ ├── reader.rs
│ │ ├── term.rs
│ │ ├── test/
│ │ │ └── mod.rs
│ │ └── writer.rs
│ └── test_data/
│ ├── basic_list.etf
│ ├── generate.exs
│ ├── int_tuple.etf
│ ├── test_1.etf
│ └── test_2.etf
├── libeir_util_binary/
│ ├── Cargo.toml
│ └── src/
│ ├── bitvec.rs
│ ├── extend.rs
│ ├── impls.rs
│ ├── integer.rs
│ ├── lib.rs
│ └── slice.rs
├── libeir_util_datastructures/
│ ├── Cargo.toml
│ └── src/
│ ├── aux_hash_map.rs
│ ├── aux_traits/
│ │ ├── bforest_impl.rs
│ │ ├── entity_impl.rs
│ │ ├── mod.rs
│ │ └── std_impl/
│ │ └── mod.rs
│ ├── dedup_aux_primary_map.rs
│ ├── forest.rs
│ ├── hashmap_stack.rs
│ ├── lib.rs
│ └── pooled_entity_set.rs
├── libeir_util_dot_graph/
│ ├── Cargo.toml
│ └── src/
│ ├── lib.rs
│ └── tablegen.rs
├── libeir_util_number/
│ ├── Cargo.toml
│ └── src/
│ ├── bigint_to_float.rs
│ ├── binary.rs
│ ├── float.rs
│ ├── integer.rs
│ ├── lib.rs
│ └── number.rs
├── libeir_util_parse/
│ ├── Cargo.toml
│ └── src/
│ ├── errors.rs
│ ├── lib.rs
│ ├── parser.rs
│ ├── result.rs
│ ├── scanner.rs
│ ├── source.rs
│ └── util.rs
├── libeir_util_parse_listing/
│ ├── Cargo.toml
│ ├── build.rs
│ └── src/
│ ├── ast.rs
│ ├── grammar.lalrpop
│ ├── lib.rs
│ ├── parser.rs
│ └── token.rs
├── libeir_util_pattern_compiler/
│ ├── Cargo.toml
│ ├── README.md
│ └── src/
│ ├── cfg/
│ │ ├── generate_dot.rs
│ │ └── mod.rs
│ ├── lib.rs
│ ├── matrix.rs
│ ├── pattern.rs
│ └── simple_pattern/
│ ├── mod.rs
│ └── test.rs
├── libeir_util_prof/
│ ├── Cargo.toml
│ └── src/
│ └── lib.rs
├── meta_table/
│ ├── Cargo.toml
│ └── src/
│ └── lib.rs
└── scoped_cell/
├── Cargo.toml
└── src/
└── lib.rs
Showing preview only (296K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (3985 symbols across 229 files)
FILE: libeir_diagnostics/src/codemap.rs
type CodeMap (line 11) | pub struct CodeMap {
method new (line 19) | pub fn new() -> Self {
method add (line 30) | pub fn add(&self, name: impl Into<FileName>, source: String) -> Source...
method add_child (line 54) | pub fn add_child(
method insert_file (line 63) | fn insert_file(&self, name: FileName, source: String, parent: Option<S...
method get (line 75) | pub fn get(&self, file_id: SourceId) -> Option<Arc<SourceFile>> {
method parent (line 83) | pub fn parent(&self, file_id: SourceId) -> Option<SourceSpan> {
method get_file_id (line 88) | pub fn get_file_id(&self, filename: &FileName) -> Option<SourceId> {
method get_by_name (line 93) | pub fn get_by_name(&self, filename: &FileName) -> Option<Arc<SourceFil...
method name (line 97) | pub fn name(&self, file_id: SourceId) -> Option<FileName> {
method iter (line 101) | pub fn iter<'a>(&'a self) -> impl Iterator<Item = Arc<SourceFile>> + 'a {
method line_span (line 105) | pub fn line_span(
method line_index (line 114) | pub fn line_index(
method location (line 123) | pub fn location(
method source_span (line 132) | pub fn source_span(&self, file_id: SourceId) -> Option<SourceSpan> {
method source_slice (line 137) | pub fn source_slice<'a>(
method next_file_id (line 150) | fn next_file_id(&self) -> SourceId {
type FileId (line 161) | type FileId = SourceId;
type Name (line 162) | type Name = String;
type Source (line 163) | type Source = &'a str;
method name (line 165) | fn name(&self, file_id: Self::FileId) -> Option<Self::Name> {
method source (line 169) | fn source(&self, file_id: Self::FileId) -> Option<&'a str> {
method line_index (line 176) | fn line_index(&self, file_id: Self::FileId, byte_index: usize) -> Opti...
method line_range (line 180) | fn line_range(&self, file_id: Self::FileId, line_index: usize) -> Opti...
method default (line 156) | fn default() -> Self {
FILE: libeir_diagnostics/src/filename.rs
type FileName (line 8) | pub enum FileName {
method from (line 16) | fn from(name: PathBuf) -> FileName {
method from (line 41) | fn from(name: &Path) -> FileName {
method from (line 47) | fn from(name: String) -> FileName {
method from (line 53) | fn from(name: &'static str) -> FileName {
method as_ref (line 59) | fn as_ref(&self) -> &Path {
method eq (line 68) | fn eq(&self, other: &Path) -> bool {
method eq (line 74) | fn eq(&self, other: &PathBuf) -> bool {
method real (line 80) | pub fn real<T: Into<PathBuf>>(name: T) -> FileName {
method virtual_ (line 84) | pub fn virtual_<T: Into<Cow<'static, str>>>(name: T) -> FileName {
method to_string (line 88) | pub fn to_string(&self) -> String {
method fmt (line 100) | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
method from (line 22) | fn from(name: FileName) -> PathBuf {
function from (line 32) | fn from(name: &'a FileName) -> &'a Path {
FILE: libeir_diagnostics/src/index.rs
type SourceIndex (line 9) | pub struct SourceIndex(NonZeroUsize);
constant INDEX_MASK (line 11) | const INDEX_MASK: usize = u32::max_value() as usize;
constant UNKNOWN_SRC_ID (line 13) | const UNKNOWN_SRC_ID: usize = (SourceId::UNKNOWN_SOURCE_ID as usize) <...
constant UNKNOWN (line 15) | pub const UNKNOWN: Self = Self(unsafe { NonZeroUsize::new_unchecked(Se...
method new (line 18) | pub fn new(source: SourceId, index: ByteIndex) -> Self {
method source_id (line 25) | pub fn source_id(&self) -> SourceId {
method index (line 35) | pub fn index(&self) -> ByteIndex {
method to_usize (line 39) | pub fn to_usize(&self) -> usize {
type Output (line 50) | type Output = SourceIndex;
method add (line 53) | fn add(self, rhs: usize) -> Self {
type Output (line 65) | type Output = SourceIndex;
method add (line 68) | fn add(self, rhs: ByteOffset) -> Self {
method add_assign (line 81) | fn add_assign(&mut self, rhs: usize) {
method add_assign (line 88) | fn add_assign(&mut self, rhs: ByteOffset) {
type Output (line 94) | type Output = SourceIndex;
method sub (line 97) | fn sub(self, rhs: usize) -> Self {
method sub_assign (line 110) | fn sub_assign(&mut self, rhs: usize) {
method default (line 44) | fn default() -> Self {
FILE: libeir_diagnostics/src/lib.rs
type Diagnostic (line 27) | pub type Diagnostic = codespan_reporting::diagnostic::Diagnostic<SourceId>;
type Label (line 28) | pub type Label = codespan_reporting::diagnostic::Label<SourceId>;
type ToDiagnostic (line 30) | pub trait ToDiagnostic {
method to_diagnostic (line 31) | fn to_diagnostic(&self) -> Diagnostic;
FILE: libeir_diagnostics/src/source.rs
type SourceId (line 9) | pub struct SourceId(crate NonZeroU32);
constant UNKNOWN_SOURCE_ID (line 11) | crate const UNKNOWN_SOURCE_ID: u32 = u32::max_value();
constant UNKNOWN (line 13) | pub const UNKNOWN: Self = Self(unsafe { NonZeroU32::new_unchecked(Self...
method new (line 15) | crate fn new(index: u32) -> Self {
method get (line 22) | crate fn get(self) -> u32 {
type SourceFile (line 29) | pub struct SourceFile {
method new (line 37) | crate fn new(id: SourceId, name: FileName, source: String, parent: Opt...
method name (line 51) | pub fn name(&self) -> &FileName {
method id (line 55) | pub fn id(&self) -> SourceId {
method parent (line 59) | pub fn parent(&self) -> Option<SourceSpan> {
method line_start (line 63) | pub fn line_start(
method last_line_index (line 79) | pub fn last_line_index(&self) -> LineIndex {
method line_span (line 83) | pub fn line_span(&self, line_index: LineIndex) -> Result<Span, LineInd...
method line_index (line 90) | pub fn line_index(&self, byte_index: ByteIndex) -> LineIndex {
method location (line 98) | pub fn location(&self, byte_index: ByteIndex) -> Result<Location, Loca...
method source (line 130) | pub fn source(&self) -> &str {
method source_span (line 134) | pub fn source_span(&self) -> SourceSpan {
method source_slice (line 142) | pub fn source_slice(
FILE: libeir_diagnostics/src/span.rs
type SourceSpan (line 8) | pub struct SourceSpan {
constant UNKNOWN (line 14) | pub const UNKNOWN: Self = Self {
method new (line 21) | pub fn new(start: SourceIndex, end: SourceIndex) -> Self {
method new_align (line 38) | pub fn new_align<F>(
method source_id (line 82) | pub fn source_id(&self) -> SourceId {
method start (line 87) | pub fn start(&self) -> SourceIndex {
method start_index (line 92) | pub fn start_index(&self) -> ByteIndex {
method shrink_front (line 96) | pub fn shrink_front(mut self, offset: ByteOffset) -> Self {
method end (line 102) | pub fn end(&self) -> SourceIndex {
method end_index (line 107) | pub fn end_index(&self) -> ByteIndex {
method as_span (line 111) | pub fn as_span(&self) -> Span {
function from (line 117) | fn from(span: SourceSpan) -> Range<usize> {
function from (line 123) | fn from(span: SourceSpan) -> Range<SourceIndex> {
FILE: libeir_frontend/src/abstr_erlang.rs
type Error (line 12) | pub enum Error {
method from (line 25) | fn from(err: ParseError) -> Error {
method from (line 30) | fn from(err: LowerError) -> Error {
method to_diagnostic (line 17) | fn to_diagnostic(&self) -> Diagnostic {
type AbstrErlangFrontend (line 35) | pub struct AbstrErlangFrontend {
method new (line 39) | pub fn new(codemap: Arc<CodeMap>) -> Self {
type Error (line 46) | type Error = Error;
method parse_source (line 48) | fn parse_source<'a>(
method parse_string (line 67) | fn parse_string<'a>(
method parse_file (line 77) | fn parse_file<'a>(
FILE: libeir_frontend/src/eir.rs
type Error (line 13) | pub enum Error {
method from (line 26) | fn from(err: ParserError) -> Self {
method from (line 31) | fn from(err: LowerError) -> Self {
method to_diagnostic (line 18) | fn to_diagnostic(&self) -> Diagnostic {
type EirFrontend (line 36) | pub struct EirFrontend {
method new (line 40) | pub fn new(codemap: Arc<CodeMap>) -> Self {
type Error (line 47) | type Error = Error;
method parse_source (line 49) | fn parse_source<'a>(
method parse_string (line 63) | fn parse_string<'a>(
method parse_file (line 73) | fn parse_file<'a>(
FILE: libeir_frontend/src/erlang.rs
type Error (line 13) | pub enum Error {
method to_diagnostic (line 18) | fn to_diagnostic(&self) -> Diagnostic {
method into (line 26) | fn into(self) -> Error {
method into (line 31) | fn into(self) -> Error {
type ErlangFrontend (line 36) | pub struct ErlangFrontend {
method new (line 41) | pub fn new(config: ParseConfig, codemap: Arc<CodeMap>) -> Self {
type Error (line 49) | type Error = Error;
method parse_source (line 51) | fn parse_source<'a>(
method parse_string (line 69) | fn parse_string<'a>(
method parse_file (line 79) | fn parse_file<'a>(
FILE: libeir_frontend/src/lib.rs
type FrontendErrorReceiver (line 15) | pub type FrontendErrorReceiver<'a, E> = dyn ErrorReceiver<E = E, W = E> ...
type DynFrontend (line 17) | pub trait DynFrontend {
method parse_source_dyn (line 18) | fn parse_source_dyn<'a>(
method parse_string_dyn (line 23) | fn parse_string_dyn<'a>(&self, source: &str) -> (Result<Module, ()>, V...
method parse_file_dyn (line 25) | fn parse_file_dyn<'a>(&self, source: &Path) -> (Result<Module, ()>, Ve...
method parse_source_dyn (line 55) | fn parse_source_dyn<'a>(
method parse_string_dyn (line 64) | fn parse_string_dyn<'a>(&self, source: &str) -> (Result<Module, ()>, V...
method parse_file_dyn (line 70) | fn parse_file_dyn<'a>(&self, source: &Path) -> (Result<Module, ()>, Ve...
method parse_source_dyn (line 86) | fn parse_source_dyn<'a>(
method parse_string_dyn (line 100) | fn parse_string_dyn<'a>(&self, source: &str) -> (Result<Module, ()>, V...
method parse_file_dyn (line 111) | fn parse_file_dyn<'a>(&self, source: &Path) -> (Result<Module, ()>, Ve...
type Frontend (line 28) | pub trait Frontend {
method parse_source (line 31) | fn parse_source<'a>(
method parse_string (line 37) | fn parse_string<'a>(
method parse_file (line 43) | fn parse_file<'a>(
type AnyFrontend (line 77) | pub enum AnyFrontend {
method from (line 123) | fn from(f: erlang::ErlangFrontend) -> Self {
method from (line 128) | fn from(f: abstr_erlang::AbstrErlangFrontend) -> Self {
method from (line 133) | fn from(f: eir::EirFrontend) -> Self {
FILE: libeir_intern/src/arena.rs
type TypedArena (line 25) | pub struct TypedArena<T> {
type TypedArenaChunk (line 41) | struct TypedArenaChunk<T> {
function new (line 48) | unsafe fn new(capacity: usize) -> TypedArenaChunk<T> {
function destroy (line 56) | unsafe fn destroy(&mut self, len: usize) {
function start (line 71) | fn start(&self) -> *mut T {
function end (line 77) | fn end(&self) -> *mut T {
constant PAGE (line 90) | const PAGE: usize = 4 * 1024;
constant PAGE (line 93) | const PAGE: usize = 64 * 1024;
method default (line 97) | fn default() -> TypedArena<T> {
function in_arena (line 110) | pub fn in_arena(&self, ptr: *const T) -> bool {
function alloc (line 120) | pub fn alloc(&self, object: T) -> &mut T {
function alloc_slice (line 152) | pub fn alloc_slice(&self, slice: &[T]) -> &mut [T]
function grow (line 177) | fn grow(&self, n: usize) {
function clear (line 203) | pub fn clear(&mut self) {
function clear_last_chunk (line 221) | fn clear_last_chunk(&self, last_chunk: &mut TypedArenaChunk<T>) {
method drop (line 246) | fn drop(&mut self) {
type DroplessArena (line 266) | pub struct DroplessArena {
method in_arena (line 292) | pub fn in_arena<T: ?Sized>(&self, ptr: *const T) -> bool {
method align (line 302) | fn align(&self, align: usize) {
method grow (line 310) | fn grow(&self, needed_bytes: usize) {
method alloc_raw (line 334) | pub unsafe fn alloc_raw(&self, bytes: usize, align: usize) -> *mut u8 {
method alloc_copy (line 353) | pub fn alloc_copy<T>(&self, object: T) -> &mut T {
method alloc_slice (line 373) | pub fn alloc_slice<T>(&self, slice: &[T]) -> &mut [T]
method default (line 282) | fn default() -> DroplessArena {
type Point (line 405) | struct Point {
function test_unused (line 412) | pub fn test_unused() {
function test_arena_alloc_nested (line 418) | fn test_arena_alloc_nested() {
function test_copy (line 461) | pub fn test_copy() {
function bench_copy (line 469) | pub fn bench_copy(b: &mut Bencher) {
function bench_copy_nonarena (line 475) | pub fn bench_copy_nonarena(b: &mut Bencher) {
type Noncopy (line 482) | struct Noncopy {
function test_noncopy (line 488) | pub fn test_noncopy() {
function test_typed_arena_zero_sized (line 499) | pub fn test_typed_arena_zero_sized() {
function test_typed_arena_clear (line 507) | pub fn test_typed_arena_clear() {
function bench_typed_arena_clear (line 518) | pub fn bench_typed_arena_clear(b: &mut Bencher) {
type DropCounter (line 528) | struct DropCounter<'a> {
method drop (line 533) | fn drop(&mut self) {
function test_typed_arena_drop_count (line 539) | fn test_typed_arena_drop_count() {
function test_typed_arena_drop_on_clear (line 552) | fn test_typed_arena_drop_on_clear() {
type SmallDroppable (line 567) | struct SmallDroppable;
method drop (line 570) | fn drop(&mut self) {
function test_typed_arena_drop_small_count (line 576) | fn test_typed_arena_drop_small_count() {
function bench_noncopy (line 590) | pub fn bench_noncopy(b: &mut Bencher) {
function bench_noncopy_nonarena (line 601) | pub fn bench_noncopy_nonarena(b: &mut Bencher) {
FILE: libeir_intern/src/lib.rs
function it_works (line 19) | fn it_works() {
FILE: libeir_intern/src/symbol.rs
type SymbolTable (line 27) | pub struct SymbolTable {
method new (line 31) | pub fn new() -> Self {
type Ident (line 40) | pub struct Ident {
method new (line 47) | pub const fn new(name: Symbol, span: SourceSpan) -> Ident {
method with_empty_span (line 52) | pub const fn with_empty_span(name: Symbol) -> Ident {
method from_interned_str (line 57) | pub fn from_interned_str(string: InternedString) -> Ident {
method from_str (line 62) | pub fn from_str(string: &str) -> Ident {
method unquote_string (line 66) | pub fn unquote_string(self) -> Ident {
method unquote_atom (line 70) | pub fn unquote_atom(self) -> Ident {
method gensym (line 74) | pub fn gensym(self) -> Ident {
method as_str (line 78) | pub fn as_str(self) -> LocalInternedString {
method as_interned_str (line 82) | pub fn as_interned_str(self) -> InternedString {
method fmt (line 106) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
method fmt (line 112) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
method is_keyword (line 435) | pub fn is_keyword(self) -> bool {
method is_reserved_attr (line 439) | pub fn is_reserved_attr(self) -> bool {
method is_preprocessor_directive (line 443) | pub fn is_preprocessor_directive(self) -> bool {
method partial_cmp (line 88) | fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
method eq (line 94) | fn eq(&self, rhs: &Self) -> bool {
method hash (line 100) | fn hash<H: Hasher>(&self, state: &mut H) {
type SymbolIndex (line 118) | pub struct SymbolIndex(u32);
constant MAX_AS_U32 (line 138) | pub const MAX_AS_U32: u32 = 0xFFFF_FF00;
constant MAX (line 140) | pub const MAX: SymbolIndex = SymbolIndex::new(0xFFFF_FF00);
method new (line 143) | const fn new(n: u32) -> Self {
method as_u32 (line 154) | pub fn as_u32(self) -> u32 {
method as_usize (line 159) | pub fn as_usize(self) -> usize {
method clone (line 120) | fn clone(&self) -> Self {
function from (line 126) | fn from(v: SymbolIndex) -> u32 {
function from (line 132) | fn from(v: SymbolIndex) -> usize {
type Symbol (line 166) | pub struct Symbol(SymbolIndex);
method new (line 169) | const fn new(n: u32) -> Self {
method intern (line 174) | pub fn intern(string: &str) -> Self {
method interned (line 178) | pub fn interned(self) -> Self {
method gensym (line 183) | pub fn gensym(string: &str) -> Self {
method gensymed (line 187) | pub fn gensymed(self) -> Self {
method as_str (line 191) | pub fn as_str(self) -> LocalInternedString {
method as_interned_str (line 200) | pub fn as_interned_str(self) -> InternedString {
method as_u32 (line 207) | pub fn as_u32(self) -> u32 {
method as_usize (line 212) | pub fn as_usize(self) -> usize {
method fmt (line 218) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
method fmt (line 229) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
method eq (line 235) | fn eq(&self, other: &T) -> bool {
method is_keyword (line 419) | pub fn is_keyword(self) -> bool {
method is_reserved_attr (line 424) | pub fn is_reserved_attr(self) -> bool {
method is_preprocessor_directive (line 429) | pub fn is_preprocessor_directive(self) -> bool {
type Interner (line 245) | pub struct Interner {
method prefill (line 253) | fn prefill(init: &[&str]) -> Self {
method intern (line 268) | pub fn intern(&mut self, string: &str) -> Symbol {
method interned (line 287) | pub fn interned(&self, symbol: Symbol) -> Symbol {
method gensym (line 295) | fn gensym(&mut self, string: &str) -> Symbol {
method gensymed (line 300) | fn gensymed(&mut self, symbol: Symbol) -> Symbol {
method is_gensymed (line 305) | fn is_gensymed(&mut self, symbol: Symbol) -> bool {
method get (line 309) | pub fn get(&self, symbol: Symbol) -> &str {
function with_interner (line 450) | fn with_interner<T, F: FnOnce(&mut Interner) -> T>(f: F) -> T {
function with_read_only_interner (line 462) | fn with_read_only_interner<T, F: FnOnce(&Interner) -> T>(f: F) -> T {
type LocalInternedString (line 474) | pub struct LocalInternedString {
method as_interned_str (line 482) | pub fn as_interned_str(self) -> InternedString {
method get (line 488) | pub fn get(&self) -> &'static str {
method as_ref (line 497) | fn as_ref(&self) -> &U {
method eq (line 503) | fn eq(&self, other: &T) -> bool {
type Target (line 536) | type Target = str;
method deref (line 537) | fn deref(&self) -> &str {
method fmt (line 543) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
method fmt (line 549) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
function eq (line 509) | fn eq(&self, other: &LocalInternedString) -> bool {
function eq (line 515) | fn eq(&self, other: &LocalInternedString) -> bool {
method eq (line 521) | fn eq(&self, other: &LocalInternedString) -> bool {
function eq (line 527) | fn eq(&self, other: &LocalInternedString) -> bool {
type InternedString (line 556) | pub struct InternedString {
method with (line 561) | pub fn with<F: FnOnce(&str) -> R, R>(self, f: F) -> R {
method as_symbol (line 569) | pub fn as_symbol(self) -> Symbol {
method as_str (line 573) | pub fn as_str(self) -> LocalInternedString {
method partial_cmp (line 585) | fn partial_cmp(&self, other: &InternedString) -> Option<Ordering> {
method eq (line 603) | fn eq(&self, other: &T) -> bool {
method eq (line 609) | fn eq(&self, other: &InternedString) -> bool {
method fmt (line 645) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
method fmt (line 651) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
method hash (line 579) | fn hash<H: Hasher>(&self, state: &mut H) {
method cmp (line 594) | fn cmp(&self, other: &InternedString) -> Ordering {
function eq (line 615) | fn eq(&self, other: &InternedString) -> bool {
function eq (line 621) | fn eq(&self, other: &InternedString) -> bool {
method eq (line 627) | fn eq(&self, other: &InternedString) -> bool {
function eq (line 633) | fn eq(&self, other: &InternedString) -> bool {
method from (line 639) | fn from(val: InternedString) -> String {
function interner_tests (line 661) | fn interner_tests() {
function interned_keywords_no_gaps (line 680) | fn interned_keywords_no_gaps() {
function unquote_string (line 691) | fn unquote_string() {
function unquote_atom (line 697) | fn unquote_atom() {
FILE: libeir_interpreter/src/erl_lib/erlang.rs
function abs (line 16) | fn abs(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> ...
function add (line 31) | fn add(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> ...
function sub (line 66) | fn sub(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> ...
function invert (line 99) | fn invert(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) ...
function mul (line 114) | fn mul(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> ...
function div (line 129) | fn div(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> ...
function is_list (line 150) | fn is_list(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>])...
function is_atom (line 169) | fn is_atom(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>])...
function is_integer (line 185) | fn is_integer(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term...
function is_pid (line 198) | fn is_pid(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) ...
function is_tuple (line 211) | fn is_tuple(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]...
function is_map (line 224) | fn is_map(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) ...
function list_subtract (line 257) | fn list_subtract(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<T...
function exact_eq (line 288) | fn exact_eq(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]...
function exact_not_eq (line 294) | fn exact_not_eq(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Te...
function and (line 301) | fn and(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> ...
function or (line 312) | fn or(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> N...
function tuple_size (line 323) | fn tuple_size(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term...
function is_function (line 334) | fn is_function(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Ter...
function not (line 474) | fn not(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> ...
function is_binary (line 485) | fn is_binary(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>...
function atom_to_list (line 502) | fn atom_to_list(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Te...
function less_than_or_equal (line 521) | fn less_than_or_equal(
function less_than (line 534) | fn less_than(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>...
function greater_than_or_equal (line 543) | fn greater_than_or_equal(
function greater_than (line 556) | fn greater_than(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Te...
function setelement (line 566) | fn setelement(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term...
function element (line 588) | fn element(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>])...
function erl_self (line 608) | fn erl_self(_vm: &VMState, proc: &mut ProcessContext, args: &[Rc<Term>])...
function put (line 628) | fn put(_vm: &VMState, proc: &mut ProcessContext, args: &[Rc<Term>]) -> N...
function get (line 642) | fn get(_vm: &VMState, proc: &mut ProcessContext, args: &[Rc<Term>]) -> N...
function erase (line 655) | fn erase(_vm: &VMState, proc: &mut ProcessContext, args: &[Rc<Term>]) ->...
function length (line 673) | fn length(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) ...
function hd (line 698) | fn hd(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> N...
function tl (line 712) | fn tl(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> N...
function map_size (line 727) | fn map_size(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]...
function make_erlang (line 738) | pub fn make_erlang() -> NativeModule {
FILE: libeir_interpreter/src/erl_lib/file.rs
function delete (line 6) | fn delete(_vm: &VMState, _proc: &mut ProcessContext, args: &[Term]) -> C...
function make_time (line 13) | pub fn make_time() -> NativeModule {
FILE: libeir_interpreter/src/erl_lib/lists.rs
function reverse_2 (line 30) | fn reverse_2(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>...
function reverse_1 (line 42) | fn reverse_1(vm: &VMState, proc: &mut ProcessContext, args: &[Rc<Term>])...
function make_lists (line 73) | pub fn make_lists() -> NativeModule {
FILE: libeir_interpreter/src/erl_lib/maps.rs
function new_0 (line 11) | fn new_0(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -...
function from_list_1 (line 18) | fn from_list_1(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Ter...
function make_maps (line 40) | pub fn make_maps() -> NativeModule {
FILE: libeir_interpreter/src/erl_lib/math.rs
function pow (line 12) | fn pow(_vm: &VMState, _proc: &mut ProcessContext, args: &[Rc<Term>]) -> ...
function make_math (line 29) | pub fn make_math() -> NativeModule {
FILE: libeir_interpreter/src/erl_lib/os.rs
function getenv (line 6) | fn getenv(_vm: &VMState, _proc: &mut ProcessContext, args: &[Term]) -> C...
function os_type (line 14) | fn os_type(_vm: &VMState, _proc: &mut ProcessContext, args: &[Term]) -> ...
function make_os (line 22) | pub fn make_os() -> NativeModule {
FILE: libeir_interpreter/src/erl_tests/mod.rs
function erl_to_core (line 8) | fn erl_to_core(erlang_code: &str) -> String {
function erl_to_ir (line 38) | fn erl_to_ir(erlang_code: &str) -> Module {
function ctx_from_erl (line 49) | fn ctx_from_erl(erlang_code: &str) -> VMState {
constant TEST_ERL_1 (line 60) | const TEST_ERL_1: &str = r##"
function simple_add (line 94) | fn simple_add() {
function simple_function_call (line 104) | fn simple_function_call() {
function simple_lambda (line 114) | fn simple_lambda() {
function simple_pattern_match (line 124) | fn simple_pattern_match() {
constant FACTORIAL_ERL (line 139) | const FACTORIAL_ERL: &str = r##"
function factorial (line 149) | fn factorial() {
function long_strings (line 159) | fn long_strings() {
function compile_core_file (line 172) | fn compile_core_file(path: &str) -> Module {
function compiler (line 182) | fn compiler() {
FILE: libeir_interpreter/src/mailbox.rs
type Mailbox (line 4) | pub struct Mailbox {
method new (line 10) | pub fn new() -> Self {
method get_trap_exits (line 16) | pub fn get_trap_exits(&self) -> bool {
method set_trap_exits (line 19) | pub fn set_trap_exits(&mut self, val: bool) {
FILE: libeir_interpreter/src/module.rs
type NativeReturn (line 10) | pub enum NativeReturn {
type NativeModule (line 15) | pub struct NativeModule {
method new (line 23) | pub fn new(name: Symbol) -> Self {
method add_fun (line 30) | pub fn add_fun(
method has_fun (line 39) | pub fn has_fun(&self, ident: &FunctionIdent) -> bool {
type ErlangFunction (line 44) | pub struct ErlangFunction {
type ErlangModule (line 49) | pub struct ErlangModule {
method from_eir (line 55) | pub fn from_eir(module: Module) -> Self {
type ModuleType (line 76) | pub enum ModuleType {
FILE: libeir_interpreter/src/pattern.rs
type MatchState (line 10) | pub enum MatchState {
method clause_num (line 18) | fn clause_num(&self) -> usize {
method clause_num_mut (line 26) | fn clause_num_mut(&mut self) -> &mut usize {
method into_guard (line 33) | fn into_guard(&mut self) {
method into_body (line 40) | fn into_body(&mut self) {
method into_finished (line 47) | fn into_finished(&mut self) {
type CaseContext (line 54) | pub struct CaseContext {
method new (line 151) | pub fn new(vars: Vec<Term>, clauses: Vec<Clause>) -> Self {
method do_body (line 160) | pub fn do_body(&mut self) -> usize {
method case_values (line 199) | pub fn case_values(&self) -> HashMap<SSAVariable, Term> {
method guard_ok (line 203) | pub fn guard_ok(&mut self) {
method guard_fail (line 207) | pub fn guard_fail(&mut self, clause_num: usize) {
function match_node (line 61) | fn match_node(term: &Term, node: &PatternNode,
FILE: libeir_interpreter/src/process/match.rs
function match_op (line 12) | pub fn match_op(
FILE: libeir_interpreter/src/process/mod.rs
type TermCall (line 25) | pub struct TermCall {
type Continuation (line 30) | pub enum Continuation {
type CallExecutor (line 36) | pub struct CallExecutor {
method new (line 41) | pub fn new() -> Self {
method run (line 47) | pub fn run(&mut self, vm: &VMState, proc: &mut ProcessContext, call: T...
method run_native (line 105) | pub fn run_native(
method run_erlang (line 129) | pub fn run_erlang(
method make_const_term (line 166) | fn make_const_term(&self, fun: &ErlangFunction, const_val: Const) -> R...
method make_term (line 210) | fn make_term(&self, fun: &ErlangFunction, value: Value) -> Rc<Term> {
method run_erlang_op (line 288) | pub fn run_erlang_op(&mut self, _vm: &VMState, fun: &ErlangFunction, b...
type ProcessContext (line 572) | pub struct ProcessContext {
method new (line 578) | pub fn new(pid: Pid) -> Self {
FILE: libeir_interpreter/src/receive.rs
type ReceiveContext (line 4) | pub struct ReceiveContext {
method new (line 9) | pub fn new(timeout: Term) -> Self {
FILE: libeir_interpreter/src/term.rs
type Pid (line 16) | pub struct Pid(pub usize);
type Reference (line 19) | pub struct Reference(pub usize);
type TermType (line 22) | pub enum TermType {
type FloatTerm (line 45) | pub struct FloatTerm(pub f64);
method from (line 63) | fn from(src: f64) -> Self {
method eq (line 47) | fn eq(&self, other: &FloatTerm) -> bool {
method cmp (line 52) | fn cmp(&self, other: &FloatTerm) -> Ordering {
method hash (line 58) | fn hash<T: Hasher>(&self, state: &mut T) {
type MapTerm (line 69) | pub struct MapTerm {
method new (line 74) | pub fn new() -> MapTerm {
method insert (line 81) | pub fn insert(&mut self, key: Rc<Term>, val: Rc<Term>) -> bool {
method get (line 95) | pub fn get(&self, key: &Rc<Term>) -> Option<Rc<Term>> {
method len (line 99) | pub fn len(&self) -> usize {
method eq (line 104) | fn eq(&self, other: &MapTerm) -> bool {
method partial_cmp (line 110) | fn partial_cmp(&self, other: &MapTerm) -> Option<Ordering> {
method cmp (line 115) | fn cmp(&self, other: &MapTerm) -> Ordering {
method hash (line 120) | fn hash<H: Hasher>(&self, state: &mut H) {
type Term (line 126) | pub enum Term {
method order_idx (line 158) | fn order_idx(&self) -> usize {
method from (line 388) | fn from(num: i64) -> Self {
method new_i64 (line 422) | pub fn new_i64(num: i64) -> Self {
method new_usize (line 425) | pub fn new_usize(num: usize) -> Self {
method new_atom (line 429) | pub fn new_atom(string: &str) -> Self {
method new_bool (line 433) | pub fn new_bool(val: bool) -> Self {
method slice_to_list (line 441) | pub fn slice_to_list(head: &[Rc<Term>], tail: Rc<Term>) -> Rc<Term> {
method extend_erl_string (line 449) | fn extend_erl_string(&self, buf: &mut String) -> bool {
method get_erl_string (line 469) | pub fn get_erl_string(&self) -> Option<String> {
method atom_str (line 478) | pub fn atom_str<'a>(&'a self) -> LocalInternedString {
method is_nil (line 486) | pub fn is_nil(&self) -> bool {
method get_type (line 493) | pub fn get_type(&self) -> TermType {
method as_boolean (line 514) | pub fn as_boolean(&self) -> Option<bool> {
method as_i64 (line 528) | pub fn as_i64(&self) -> Option<i64> {
method as_usize (line 536) | pub fn as_usize(&self) -> Option<usize> {
method as_integer (line 544) | pub fn as_integer(&self) -> Option<&BigInt> {
method as_atom (line 552) | pub fn as_atom(&self) -> Option<Symbol> {
method as_tuple (line 560) | pub fn as_tuple(&self) -> Option<&[Rc<Term>]> {
method as_binary (line 568) | pub fn as_binary(&self) -> Option<&BitVec> {
method as_map (line 576) | pub fn as_map(&self) -> Option<&MapTerm> {
method list_iter (line 584) | pub fn list_iter(term: &Rc<Term>) -> ListTermIterator {
method as_inproper_list (line 600) | pub fn as_inproper_list(term: &Rc<Term>) -> (Vec<Rc<Term>>, Rc<Term>) {
method as_list (line 611) | pub fn as_list(term: &Rc<Term>) -> Option<Vec<Rc<Term>>> {
method as_value_list (line 620) | pub fn as_value_list(term: &Rc<Term>) -> Vec<Rc<Term>> {
method to_doc (line 627) | pub fn to_doc(_term: Rc<Term>) -> pretty::Doc<'static, pretty::BoxDoc<...
method eq (line 183) | fn eq(&self, other: &Self) -> bool {
method cmp (line 256) | fn cmp(&self, other: &Self) -> Ordering {
method partial_cmp (line 261) | fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
method hash (line 344) | fn hash<H: Hasher>(&self, state: &mut H) {
type ListIteratorItem (line 393) | pub enum ListIteratorItem {
type ListTermIterator (line 398) | pub struct ListTermIterator {
type Item (line 402) | type Item = ListIteratorItem;
method next (line 403) | fn next(&mut self) -> Option<ListIteratorItem> {
type ErlEq (line 746) | pub trait ErlEq<Rhs = Self> {
method erl_eq (line 747) | fn erl_eq(&self, other: &Rhs) -> bool;
method erl_eq (line 759) | fn erl_eq(&self, other: &f64) -> bool {
method erl_eq (line 765) | fn erl_eq(&self, other: &Term) -> bool {
type ErlExactEq (line 750) | pub trait ErlExactEq<Rhs = Self> {
method erl_exact_eq (line 751) | fn erl_exact_eq(&self, other: &Rhs) -> bool;
method erl_exact_eq (line 836) | fn erl_exact_eq(&self, other: &Term) -> bool {
type ErlOrd (line 754) | pub trait ErlOrd<Rhs = Self> {
method erl_ord (line 755) | fn erl_ord(&self, other: &Rhs) -> ::std::cmp::Ordering;
method erl_ord (line 842) | fn erl_ord(&self, other: &Term) -> ::std::cmp::Ordering {
FILE: libeir_interpreter/src/trace/dummy.rs
function set_pid (line 8) | pub fn set_pid(_pid: Pid) {}
function enter_function (line 9) | pub fn enter_function(_ident: &FunctionIdent, _lambda: Option<Block>, _a...
function warning (line 13) | pub fn warning(_text: String) {}
function warning_args (line 14) | pub fn warning_args<F>(_text: String, _make_args: F) where F: FnOnce() -...
FILE: libeir_interpreter/src/trace/trace.rs
type TraceEntry (line 16) | enum TraceEntry {
function gen_vm_id (line 59) | pub fn gen_vm_id() {
function vm_id (line 67) | fn vm_id() -> usize {
type StackEntry (line 73) | struct StackEntry {
type TraceEvent (line 80) | struct TraceEvent {
type TraceEventType (line 85) | enum TraceEventType {
type TraceCollector (line 107) | struct TraceCollector {
method new (line 115) | fn new() -> Self {
function set_pid (line 125) | pub fn set_pid(pid: Pid) {
function get_pid (line 132) | pub fn get_pid() -> Pid {
function enter_function (line 139) | pub fn enter_function(ident: &FunctionIdent, lambda: Option<Block>, args...
function exit_function (line 165) | pub fn exit_function(ident: &FunctionIdent, ret: Option<&CallReturn>) {
function start_basic_block (line 184) | pub fn start_basic_block(module: &Atom, ident: &FunctionIdent, block: La...
function end_basic_block (line 199) | pub fn end_basic_block() {
function warning (line 210) | pub fn warning(text: String) {
function warning_args (line 224) | pub fn warning_args<F>(text: String, make_args: F) where F: FnOnce() -> ...
function dump_trace (line 238) | pub fn dump_trace(filename: String) {
FILE: libeir_interpreter/src/vm.rs
type WatchType (line 13) | pub enum WatchType {
type ReferenceGenerator (line 19) | pub struct ReferenceGenerator(Reference);
method new (line 21) | fn new() -> Self {
method next (line 25) | pub fn next(&mut self) -> Reference {
type VMState (line 32) | pub struct VMState {
method new (line 44) | pub fn new() -> Self {
method add_erlang_module (line 54) | pub fn add_erlang_module(&mut self, module: Module) {
method add_native_module (line 69) | pub fn add_native_module(&mut self, module: NativeModule) {
method add_nif_overlay (line 82) | pub fn add_nif_overlay(&mut self, module: NativeModule) {
method add_builtin_modules (line 92) | pub fn add_builtin_modules(&mut self) {
method call (line 99) | pub fn call(
FILE: libeir_ir/build.rs
function main (line 3) | fn main() {
FILE: libeir_ir/src/algo/equality.rs
type EqualityFail (line 10) | pub enum EqualityFail {
type EqCtx (line 52) | struct EqCtx<'a> {
type GraphEqOptions (line 61) | pub struct GraphEqOptions {
method default (line 66) | fn default() -> Self {
method graph_eq_opts (line 74) | pub fn graph_eq_opts(
method graph_eq (line 179) | pub fn graph_eq(
function traverse_value (line 189) | fn traverse_value<'a>(ctx: &mut EqCtx<'a>, l: Value, r: Value) -> Result...
function basic_equality (line 240) | fn basic_equality() {
function args_length_inequality (line 273) | fn args_length_inequality() {
function args_read_inequality (line 298) | fn args_read_inequality() {
function args_read_const_equality (line 323) | fn args_read_const_equality() {
function args_read_const_inequality (line 348) | fn args_read_const_inequality() {
function args_prim_inequality (line 373) | fn args_prim_inequality() {
function block_location_equality (line 400) | fn block_location_equality() {
FILE: libeir_ir/src/algo/func_tree.rs
type FunctionTree (line 10) | pub struct FunctionTree {
method validate_no_cycles (line 231) | fn validate_no_cycles(&self, entry: Block, mut curr: usize, limit: usi...
method dfs (line 241) | pub fn dfs(&self) -> Dfs<Block, EntityVisitMap<Block>> {
method dfs_iter (line 244) | pub fn dfs_iter<'a>(&'a self) -> impl Iterator<Item = Block> + 'a {
method dfs_post_order (line 248) | pub fn dfs_post_order(&self) -> DfsPostOrder<Block, EntityVisitMap<Blo...
method dfs_post_order_iter (line 251) | pub fn dfs_post_order_iter<'a>(&'a self) -> impl Iterator<Item = Block...
type FunctionEntry (line 22) | pub struct FunctionEntry {
type Escape (line 55) | enum Escape {
method func_tree (line 61) | pub fn func_tree(&self, live: &LiveValues, resolve_continuations: bool) ...
type NodeId (line 257) | type NodeId = Block;
type EdgeId (line 258) | type EdgeId = (Block, Block);
type Neighbors (line 262) | type Neighbors = std::iter::Cloned<std::collections::btree_set::Iter<'a,...
method neighbors (line 263) | fn neighbors(self, block: Block) -> Self::Neighbors {
type Map (line 269) | type Map = EntityVisitMap<Block>;
method visit_map (line 270) | fn visit_map(&self) -> EntityVisitMap<Block> {
method reset_map (line 273) | fn reset_map(&self, map: &mut EntityVisitMap<Block>) {
FILE: libeir_ir/src/algo/live.rs
method live_values (line 10) | pub fn live_values(&self) -> LiveValues {
type LiveValues (line 27) | pub struct LiveValues {
method get_aux (line 39) | fn get_aux(&self) -> &SetForest<Value> {
method aux_fmt (line 45) | fn aux_fmt(&self, f: &mut std::fmt::Formatter<'_>, _aux: &C) -> std::f...
method fmt (line 54) | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
method live_at (line 60) | pub fn live_at<'a>(&'a self, block: Block) -> BoundSet<'a, Value, ()> {
method live_in (line 63) | pub fn live_in<'a>(&'a self, block: Block) -> BoundSet<'a, Value, ()> {
method is_live_at (line 67) | pub fn is_live_at(&self, block: Block, value: Value) -> bool {
method is_live_in (line 70) | pub fn is_live_in(&self, block: Block, value: Value) -> bool {
function dataflow_pass (line 75) | fn dataflow_pass(
function calculate_live_values (line 138) | pub fn calculate_live_values(fun: &Function) -> LiveValues {
function test_simple (line 173) | fn test_simple() {
function test_cycle (line 208) | fn test_cycle() {
FILE: libeir_ir/src/algo/mangle/datatypes.rs
type FromT (line 8) | pub struct FromT<T>(pub T);
function map_fun (line 10) | pub(super) fn map_fun<'a, 'b, R, F, V>(self, recv: &'a R, mut f: F) -> F...
function inner (line 20) | pub fn inner(self) -> T {
function from (line 25) | fn from(f: T) -> Self {
function fmt (line 33) | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
type FromValue (line 37) | pub(super) type FromValue = FromT<Value>;
type FromBlock (line 38) | pub(super) type FromBlock = FromT<Block>;
type ToT (line 41) | pub struct ToT<T>(pub T);
function map_fun (line 43) | pub(super) fn map_fun<'a, 'b, R, F, V>(self, recv: &'a R, mut f: F) -> T...
function inner (line 53) | pub fn inner(self) -> T {
function from (line 58) | fn from(f: T) -> Self {
function fmt (line 66) | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
type ToValue (line 70) | pub type ToValue = ToT<Value>;
type ToBlock (line 71) | pub type ToBlock = ToT<Block>;
type MangleTarget (line 77) | pub enum MangleTarget<T> {
function fmt (line 85) | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
function inner (line 90) | pub fn inner(self) -> T {
function inner_ref (line 96) | pub fn inner_ref(&self) -> &T {
function fun (line 103) | pub(super) fn fun<'a, 'b, R>(&self, recv: &'a R) -> &'a Function
function map (line 113) | pub fn map<F, V>(self, mut f: F) -> MangleTarget<V>
function map_fun (line 129) | pub(super) fn map_fun<'a, 'b, R, F, V>(self, recv: &'a R, mut f: F) -> M...
function new_with (line 147) | pub fn new_with<N>(&self, new: N) -> MangleTarget<N> {
function from (line 154) | pub fn from(self) -> Option<FromT<T>> {
function to (line 160) | pub fn to(self) -> Option<ToT<T>> {
function transpose_opt (line 168) | pub fn transpose_opt(self) -> Option<MangleTarget<I>> {
function cloned (line 181) | pub fn cloned(&self) -> MangleTarget<T> {
function transpose_iter (line 189) | pub fn transpose_iter(self) -> impl Iterator<Item = MangleTarget<V>> {
function from (line 208) | fn from(i: FromT<I>) -> MangleTarget<I> {
function from (line 213) | fn from(i: ToT<I>) -> MangleTarget<I> {
type MangleValue (line 217) | pub(super) type MangleValue = MangleTarget<Value>;
type MangleBlock (line 218) | pub(super) type MangleBlock = MangleTarget<Block>;
FILE: libeir_ir/src/algo/mangle/mod.rs
type Mangler (line 29) | pub struct Mangler {
method new (line 49) | pub fn new() -> Self {
method clear (line 70) | fn clear(&mut self) {
method value_map (line 87) | pub fn value_map<'a>(&'a self) -> &'a BTreeMap<MangleValue, (MangleVal...
method start (line 93) | pub fn start<F>(&mut self, from_block: F)
method add_rename (line 101) | pub fn add_rename<O, N>(&mut self, old: O, new: N)
method add_rename_nofollow (line 114) | pub fn add_rename_nofollow<O, N>(&mut self, old: O, new: N)
method run (line 123) | pub fn run(&mut self, fun: &mut FunctionBuilder) -> Block {
method run_across (line 129) | pub fn run_across(&mut self, from: &Function, to: &mut FunctionBuilder...
method propagate_values (line 134) | fn propagate_values(&mut self) {
method run_inner (line 155) | fn run_inner<'a, 'b, R>(&mut self, recv: &'a mut R) -> Block
method map (line 359) | fn map<'a, 'b, R>(&mut self, bump: &Bump, recv: &'a mut R, mut val: Ma...
FILE: libeir_ir/src/algo/mangle/receiver.rs
type MangleReceiver (line 10) | pub(super) trait MangleReceiver<'b> {
method from (line 16) | fn from<'a>(&'a self) -> &'a Function;
method to (line 19) | fn to<'a>(&'a mut self) -> &'a mut FunctionBuilder<'b>;
method to_fun (line 20) | fn to_fun<'a>(&'a self) -> &'a Function;
method map_const (line 25) | fn map_const(&mut self, val: MangleValue) -> ToValue;
method map_free_value (line 30) | fn map_free_value(&mut self, val: MangleValue) -> ToValue;
method map_block_op (line 34) | fn map_block_op(&mut self, block: MangleBlock) -> OpKind;
type SingleMangleReceiver (line 38) | pub(super) struct SingleMangleReceiver<'a, 'b> {
function from (line 42) | fn from<'a>(&'a self) -> &'a Function {
function to (line 47) | fn to<'a>(&'a mut self) -> &'a mut FunctionBuilder<'b> {
function to_fun (line 50) | fn to_fun<'a>(&'a self) -> &'a Function {
function map_const (line 53) | fn map_const(&mut self, val: MangleValue) -> ToValue {
function map_free_value (line 56) | fn map_free_value(&mut self, val: MangleValue) -> ToValue {
function map_block_op (line 59) | fn map_block_op(&mut self, block: MangleBlock) -> OpKind {
type CopyMangleReceiver (line 67) | pub(super) struct CopyMangleReceiver<'a, 'b> {
function from (line 72) | fn from<'a>(&'a self) -> &'a Function {
function to (line 75) | fn to<'a>(&'a mut self) -> &'a mut FunctionBuilder<'b> {
function to_fun (line 78) | fn to_fun<'a>(&'a self) -> &'a Function {
function map_const (line 81) | fn map_const(&mut self, _val: MangleValue) -> ToValue {
function map_free_value (line 84) | fn map_free_value(&mut self, _val: MangleValue) -> ToValue {
function map_block_op (line 87) | fn map_block_op(&mut self, _block: MangleBlock) -> OpKind {
FILE: libeir_ir/src/algo/mangle/tests.rs
function simple_mangle (line 7) | fn simple_mangle() {
function preserves_block_locations (line 56) | fn preserves_block_locations() {
function mangle_primop (line 96) | fn mangle_primop() {
function mangle_recursive (line 134) | fn mangle_recursive() {
function mangle_entry (line 191) | fn mangle_entry() {
FILE: libeir_ir/src/algo/op_branches.rs
type BranchIter (line 4) | pub struct BranchIter<'a> {
type Item (line 11) | type Item = Value;
method next (line 12) | fn next(&mut self) -> Option<Value> {
method op_branch_iter (line 38) | pub fn op_branch_iter<'a>(&'a self, block: Block) -> BranchIter<'a> {
method op_branch_len (line 47) | pub fn op_branch_len(&self, block: Block) -> Option<usize> {
method op_branch_target (line 79) | pub fn op_branch_target(&self, block: Block, n: usize) -> Value {
FILE: libeir_ir/src/algo/validate.rs
type FnvHashMap (line 5) | type FnvHashMap<K, V> = HashMap<K, V, FnvBuildHasher>;
type ValidationError (line 15) | pub enum ValidationError {
function get_value_list (line 50) | fn get_value_list<'a>(fun: &'a Function, value: Value) -> Option<&'a [Va...
method validate (line 61) | pub fn validate(&self, errors: &mut Vec<ValidationError>) {
method validate_call_to (line 73) | fn validate_call_to(
method validate_blocks (line 93) | fn validate_blocks(&self, errors: &mut Vec<ValidationError>) {
method validate_entry_invariants (line 184) | fn validate_entry_invariants(&self, errors: &mut Vec<ValidationError>) {
method validate_ssa_visibility (line 212) | fn validate_ssa_visibility(&self, doms: &Dominators<Block>, errors: &mut...
method insert_live_for_node (line 272) | fn insert_live_for_node(
FILE: libeir_ir/src/binary.rs
type Endianness (line 5) | pub enum Endianness {
type BinaryEntrySpecifier (line 12) | pub enum BinaryEntrySpecifier {
method has_size (line 38) | pub fn has_size(&self) -> bool {
method is_native_endian (line 46) | pub fn is_native_endian(&self) -> bool {
method default (line 70) | fn default() -> Self {
FILE: libeir_ir/src/constant/atomic.rs
type BigIntTerm (line 22) | pub struct BigIntTerm(pub BigInt);
method value (line 25) | pub fn value(&self) -> &BigInt {
method into (line 31) | fn into(self) -> BigInt {
method fmt (line 46) | fn fmt(&self, fmt: &mut Formatter) -> FmtResult {
type IntTerm (line 52) | pub struct IntTerm(pub i64);
method value (line 55) | pub fn value(&self) -> i64 {
method into (line 61) | fn into(self) -> i64 {
method fmt (line 71) | fn fmt(&self, fmt: &mut Formatter) -> FmtResult {
function from_num (line 76) | fn from_num<N>(n: N) -> AtomicTerm
type FloatTerm (line 109) | pub struct FloatTerm(pub Float);
method value (line 112) | pub fn value(&self) -> f64 {
method hash (line 119) | fn hash<H>(&self, state: &mut H)
method fmt (line 150) | fn fmt(&self, fmt: &mut Formatter) -> FmtResult {
type AtomTerm (line 156) | pub struct AtomTerm(pub Symbol);
method eq (line 179) | fn eq(&self, other: &str) -> bool {
method fmt (line 184) | fn fmt(&self, fmt: &mut Formatter) -> FmtResult {
type BinaryTerm (line 190) | pub struct BinaryTerm(pub BitVec);
method value (line 193) | pub fn value(&self) -> &BitVec {
type NilTerm (line 214) | pub struct NilTerm;
type AtomicTerm (line 222) | pub enum AtomicTerm {
method from (line 13) | fn from(int: Integer) -> AtomicTerm {
method from (line 36) | fn from(data: BigIntTerm) -> Self {
method from (line 41) | fn from(data: BigInt) -> Self {
method from (line 66) | fn from(data: IntTerm) -> Self {
method from (line 103) | fn from(data: char) -> Self {
method from (line 127) | fn from(data: FloatTerm) -> Self {
method from (line 132) | fn from(data: f64) -> Self {
method from (line 137) | fn from(data: Float) -> Self {
method from (line 142) | fn from(data: Number) -> Self {
method from (line 158) | fn from(data: AtomTerm) -> Self {
method from (line 163) | fn from(data: Symbol) -> Self {
method from (line 168) | fn from(data: bool) -> Self {
method from (line 198) | fn from(data: BinaryTerm) -> Self {
method from (line 203) | fn from(data: Vec<u8>) -> Self {
method from (line 208) | fn from(data: BitVec) -> Self {
method from (line 216) | fn from(_data: NilTerm) -> Self {
method fmt (line 232) | fn fmt(&self, fmt: &mut Formatter) -> FmtResult {
FILE: libeir_ir/src/constant/float.rs
constant SIGN_MASK (line 6) | const SIGN_MASK: u64 = 0x8000_0000_0000_0000u64;
constant EXP_MASK (line 7) | const EXP_MASK: u64 = 0x7ff0_0000_0000_0000u64;
constant MAN_MASK (line 8) | const MAN_MASK: u64 = 0x000f_ffff_ffff_ffffu64;
constant CANONICAL_NAN_BITS (line 11) | const CANONICAL_NAN_BITS: u64 = 0x7ff8_0000_0000_0000u64;
constant CANONICAL_ZERO_BITS (line 12) | const CANONICAL_ZERO_BITS: u64 = 0x0u64;
function raw_double_bits (line 15) | pub fn raw_double_bits<F: Float>(f: &F) -> u64 {
FILE: libeir_ir/src/constant/mod.rs
type Const (line 18) | pub struct Const(u32);
type ConstKind (line 22) | pub enum ConstKind {
method aux_hash (line 38) | fn aux_hash<H: Hasher>(&self, state: &mut H, container: &ListPool<Cons...
method aux_eq (line 62) | fn aux_eq(
method is_map (line 96) | pub fn is_map(&self) -> bool {
type ConstantContainer (line 105) | pub struct ConstantContainer {
method new (line 122) | pub fn new() -> Self {
method const_kind (line 126) | pub fn const_kind(&self, value: Const) -> &ConstKind {
method list_cell (line 130) | pub fn list_cell(&mut self, head: Const, tail: Const) -> Const {
method nil (line 134) | pub fn nil(&mut self) -> Const {
method from (line 138) | pub fn from<T>(&mut self, val: T) -> Const
method get (line 145) | pub fn get<T>(&self, val: T) -> Option<Const>
method as_bool (line 163) | pub fn as_bool(&self, val: Const) -> Option<bool> {
method write (line 172) | pub fn write(&self, val: Const, out: &mut dyn std::io::Write) {
method tuple_builder (line 214) | pub fn tuple_builder(&self) -> TupleBuilder {
method eq_other (line 218) | pub fn eq_other(&self, l: Const, r_cont: &ConstantContainer, r: Const)...
method default (line 112) | fn default() -> Self {
type IntoConst (line 240) | pub trait IntoConst {
method into_const (line 241) | fn into_const(self, c: &mut ConstantContainer) -> Const;
method get_const (line 242) | fn get_const(self, fun: &ConstantContainer) -> Option<Const>;
method into_const (line 247) | fn into_const(self, c: &mut ConstantContainer) -> Const {
method get_const (line 253) | fn get_const(self, c: &ConstantContainer) -> Option<Const> {
method into_const (line 265) | fn into_const(self, c: &mut ConstantContainer) -> Const {
method get_const (line 268) | fn get_const(self, c: &ConstantContainer) -> Option<Const> {
method into_const (line 274) | fn into_const(self, c: &mut ConstantContainer) -> Const {
method get_const (line 283) | fn get_const(self, c: &ConstantContainer) -> Option<Const> {
method into_const (line 289) | fn into_const(self, _c: &mut ConstantContainer) -> Const {
method get_const (line 292) | fn get_const(self, _c: &ConstantContainer) -> Option<Const> {
method into_const (line 298) | fn into_const(self, c: &mut ConstantContainer) -> Const {
method get_const (line 301) | fn get_const(self, c: &ConstantContainer) -> Option<Const> {
type EmptyMap (line 245) | pub struct EmptyMap;
type TupleBuilder (line 306) | pub struct TupleBuilder {
method new (line 310) | pub fn new() -> Self {
method push (line 316) | pub fn push(&mut self, elem: Const, c: &mut ConstantContainer) {
method clear (line 320) | pub fn clear(mut self, c: &mut ConstantContainer) {
method finish (line 324) | pub fn finish(self, c: &mut ConstantContainer) -> Const {
FILE: libeir_ir/src/dialect/mod.rs
type ArcDialect (line 23) | pub type ArcDialect = Arc<Dialect>;
type Dialect (line 27) | pub struct Dialect {
method new (line 43) | pub fn new() -> Self {
method contains_op (line 52) | pub fn contains_op<T: Op>(&self) -> bool {
method register_op (line 56) | pub fn register_op<T: Op>(&mut self) {
method register_op_branches_impl (line 60) | pub fn register_op_branches_impl<T: MetaEntry + OpBranches>(&mut self) {
method get_op_branches (line 65) | pub fn get_op_branches<'a>(&self, obj: &'a dyn Op) -> Option<&'a dyn O...
method register_op_printer_impl (line 69) | pub fn register_op_printer_impl<T: MetaEntry + OpPrinter>(&mut self) {
method get_op_printer (line 74) | pub fn get_op_printer<'a>(&self, obj: &'a dyn Op) -> Option<&'a dyn Op...
method register_op_parser (line 78) | pub fn register_op_parser(&mut self, sym: Symbol, parser: Box<dyn OpPa...
method get_op_parser (line 82) | pub fn get_op_parser(&self, sym: Symbol) -> Option<&dyn OpParser> {
method fmt (line 37) | fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
FILE: libeir_ir/src/function/builder/mod.rs
method builder (line 17) | pub fn builder(&mut self) -> FunctionBuilder<'_> {
type IntoValue (line 22) | pub trait IntoValue {
method into_value (line 23) | fn into_value<'a>(self, b: &mut FunctionBuilder<'a>) -> Value;
method get_value (line 24) | fn get_value(self, fun: &Function) -> Option<Value>;
method into_value (line 27) | fn into_value<'a>(self, _b: &mut FunctionBuilder<'a>) -> Value {
method get_value (line 30) | fn get_value(self, _fun: &Function) -> Option<Value> {
method into_value (line 35) | fn into_value<'a>(self, b: &mut FunctionBuilder<'a>) -> Value {
method get_value (line 38) | fn get_value(self, fun: &Function) -> Option<Value> {
method into_value (line 43) | fn into_value<'a>(self, b: &mut FunctionBuilder<'a>) -> Value {
method get_value (line 46) | fn get_value(self, fun: &Function) -> Option<Value> {
method into_value (line 54) | fn into_value<'a>(self, b: &mut FunctionBuilder<'a>) -> Value {
method get_value (line 60) | fn get_value(self, fun: &Function) -> Option<Value> {
method into_value (line 93) | fn into_value<'a>(self, b: &mut FunctionBuilder<'a>) -> Value {
method get_value (line 101) | fn get_value(self, fun: &Function) -> Option<Value> {
type DynValue (line 66) | pub enum DynValue {
method into (line 73) | fn into(self) -> DynValue {
method into (line 78) | fn into(self) -> DynValue {
method into (line 83) | fn into(self) -> DynValue {
method into (line 88) | fn into(self) -> DynValue {
type FunctionBuilder (line 111) | pub struct FunctionBuilder<'a> {
function new (line 122) | pub fn new(fun: &'a mut Function) -> FunctionBuilder<'a> {
function fun (line 135) | pub fn fun(&self) -> &Function {
function fun_mut (line 138) | pub fn fun_mut(&mut self) -> &mut Function {
function cons (line 142) | pub fn cons(&self) -> &ConstantContainer {
function cons_mut (line 145) | pub fn cons_mut(&mut self) -> &mut ConstantContainer {
function value (line 152) | pub fn value<T>(&mut self, v: T) -> Value
function value_map (line 159) | pub fn value_map<F>(&mut self, mut value: Value, map: &mut F) -> Value
function graph_update_block (line 193) | pub(crate) fn graph_update_block(&mut self, block: Block) {
function block_insert (line 261) | pub fn block_insert(&mut self) -> Block {
function block_insert_with_span (line 265) | pub fn block_insert_with_span(&mut self, span: Option<SourceSpan>) -> Bl...
function block_insert_get_val (line 270) | pub fn block_insert_get_val(&mut self) -> (Block, Value) {
function block_arg_insert (line 276) | pub fn block_arg_insert(&mut self, block: Block) -> Value {
function block_args (line 280) | pub fn block_args(&self, block: Block) -> &[Value] {
function block_reads (line 284) | pub fn block_reads(&self, block: Block) -> &[Value] {
function block_set_entry (line 288) | pub fn block_set_entry(&mut self, block: Block) {
function block_set_location (line 292) | pub fn block_set_location(&mut self, block: Block, loc: Location) {
function block_clear_take (line 296) | pub fn block_clear_take(&mut self, block: Block) -> Option<OpKind> {
function block_clear (line 336) | pub fn block_clear(&mut self, block: Block) {
function block_value_map (line 340) | pub fn block_value_map<F>(&mut self, block: Block, mut map: F)
function block_copy_body_map (line 356) | pub fn block_copy_body_map<F>(&mut self, from: Block, to: Block, mut map...
function graph_impl (line 396) | fn graph_impl() {
FILE: libeir_ir/src/function/builder/op.rs
function op_call_flow (line 14) | pub fn op_call_flow<'b, V>(&'b mut self, block: Block, target: V, args: ...
function op_call_function_next (line 32) | pub fn op_call_function_next<'b, V>(
function op_call_function (line 58) | pub fn op_call_function<'b, V>(
function op_trace_capture_raw_next (line 80) | pub fn op_trace_capture_raw_next(&mut self, span: SourceSpan, block: Blo...
function op_trace_capture_raw (line 90) | pub fn op_trace_capture_raw(&mut self, span: SourceSpan, block: Block) -...
function op_intrinsic (line 100) | pub fn op_intrinsic<'b, O: OpBuild>(
function op_map_put_build (line 121) | pub fn op_map_put_build(&mut self, span: SourceSpan, value: Value) -> Ma...
function op_unpack_value_list_next (line 125) | pub fn op_unpack_value_list_next(
function op_unpack_value_list (line 142) | pub fn op_unpack_value_list(&mut self, block: Block, list: Value, num: u...
function op_if_bool_next (line 152) | pub fn op_if_bool_next(
function op_if_bool (line 173) | pub fn op_if_bool(
function op_if_bool_strict_next (line 198) | pub fn op_if_bool_strict_next(
function op_if_bool_strict (line 217) | pub fn op_if_bool_strict(
function op_unreachable (line 233) | pub fn op_unreachable(&mut self, span: SourceSpan, block: Block) {
function op_match_build (line 243) | pub fn op_match_build(&mut self, span: SourceSpan) -> MatchBuilder {
type MatchBuilder (line 248) | pub struct MatchBuilder {
method new (line 267) | pub fn new(span: SourceSpan) -> Self {
method push_value_next (line 273) | pub fn push_value_next(&mut self, next: Value, val: Value, b: &mut Fun...
method push_value (line 281) | pub fn push_value(&mut self, val: Value, b: &mut FunctionBuilder) -> B...
method push_type_next (line 287) | pub fn push_type_next(&mut self, next: Value, typ: BasicType, b: &mut ...
method push_type (line 295) | pub fn push_type(&mut self, typ: BasicType, b: &mut FunctionBuilder) -...
method push_tuple_next (line 301) | pub fn push_tuple_next(&mut self, next: Value, arity: usize, b: &mut F...
method push_tuple (line 309) | pub fn push_tuple(&mut self, arity: usize, b: &mut FunctionBuilder) ->...
method push_binary (line 320) | pub fn push_binary(
method push_list_cell_next (line 344) | pub fn push_list_cell_next(&mut self, next: Value, b: &mut FunctionBui...
method push_list_cell (line 352) | pub fn push_list_cell(&mut self, b: &mut FunctionBuilder) -> Block {
method push_map_item_next (line 362) | pub fn push_map_item_next(&mut self, next: Value, key: Value, b: &mut ...
method push_map_item (line 370) | pub fn push_map_item(&mut self, key: Value, b: &mut FunctionBuilder) -...
method push_wildcard_next (line 379) | pub fn push_wildcard_next(&mut self, next: Value, b: &mut FunctionBuil...
method push_wildcard (line 387) | pub fn push_wildcard(&mut self, span: SourceSpan, b: &mut FunctionBuil...
method finish (line 396) | pub fn finish(self, block: Block, value: Value, b: &mut FunctionBuilde...
method default (line 256) | fn default() -> Self {
type MapPutBuilder (line 423) | pub struct MapPutBuilder {
method new (line 431) | pub fn new(span: SourceSpan, value: Value, b: &mut FunctionBuilder) ->...
method push_kv (line 453) | pub fn push_kv(
method finish (line 466) | pub fn finish(self, block: Block, b: &mut FunctionBuilder) -> (Block, ...
FILE: libeir_ir/src/function/builder/primop.rs
function prim_binop (line 10) | pub fn prim_binop(&mut self, span: SourceSpan, op: BinOp, lhs: Value, rh...
function prim_tuple (line 34) | pub fn prim_tuple(&mut self, span: SourceSpan, values: &[Value]) -> Value {
function prim_map (line 67) | pub fn prim_map(&mut self, span: SourceSpan, keys: &[Value], values: &[V...
function prim_list_cell (line 137) | pub fn prim_list_cell(&mut self, span: SourceSpan, head: Value, tail: Va...
function prim_value_list (line 165) | pub fn prim_value_list(&mut self, values: &[Value]) -> Value {
function prim_value_list_from_entity_list (line 188) | pub(crate) fn prim_value_list_from_entity_list(&mut self, values: Entity...
function prim_logic_op (line 212) | pub fn prim_logic_op(&mut self, span: SourceSpan, op: LogicOp, values: &...
function prim_capture_function (line 269) | pub fn prim_capture_function<M, F, A>(&mut self, span: SourceSpan, m: M,...
function prim_from_kind (line 297) | pub fn prim_from_kind(&mut self, span: SourceSpan, op: PrimOpKind, vals:...
FILE: libeir_ir/src/function/format.rs
type ContainerDebug (line 16) | pub trait ContainerDebug<C>: Debug {
method fmt (line 17) | fn fmt(&self, container: &C, f: &mut Formatter) -> Result;
type ContainerDebugAdapter (line 20) | pub struct ContainerDebugAdapter<'a, C, V> {
method fmt (line 28) | fn fmt(&self, f: &mut Formatter) -> Result {
method fmt (line 34) | fn fmt(&self, _con: &C, f: &mut Formatter) -> Result {
method fmt (line 40) | fn fmt(&self, fun: &Function, f: &mut Formatter) -> Result {
function fmt (line 51) | fn fmt(&self, fun: &Function, f: &mut Formatter) -> Result {
function fmt (line 69) | fn fmt(&self, con: &C, f: &mut Formatter) -> Result {
function fmt (line 92) | fn fmt(&self, con: &C, f: &mut Formatter) -> Result {
function fmt (line 115) | fn fmt(&self, con: &C, f: &mut Formatter) -> Result {
function fmt (line 129) | fn fmt(&self, con: &C, f: &mut Formatter) -> Result {
function fmt (line 141) | fn fmt(&self, _con: &C, f: &mut Formatter) -> Result {
FILE: libeir_ir/src/function/location.rs
type Location (line 13) | pub struct Location(u32);
type LocationTerminal (line 17) | pub struct LocationTerminal(u32);
type LocationTerminalData (line 21) | struct LocationTerminalData {
method aux_hash (line 41) | fn aux_hash<H: Hasher>(&self, state: &mut H, _container: &()) {
method aux_eq (line 46) | fn aux_eq(&self, rhs: &Self, _self_aux: &(), _rhs_aux: &()) -> bool {
type LocationData (line 52) | struct LocationData {
method aux_hash (line 56) | fn aux_hash<H: Hasher>(&self, state: &mut H, container: &ListPool<Loca...
method aux_eq (line 61) | fn aux_eq(
type LocationContainer (line 72) | pub struct LocationContainer {
method new (line 80) | pub fn new() -> Self {
method lookup (line 92) | pub fn lookup(&self, location: &Location) -> Vec<SourceSpan> {
method location_empty (line 104) | pub fn location_empty(&mut self) -> Location {
method location_unknown (line 113) | pub fn location_unknown(&mut self) -> Location {
method terminal (line 136) | pub fn terminal(
method location (line 156) | pub fn location(
method terminal_from_bytespan (line 173) | pub fn terminal_from_bytespan(
method from_bytespan (line 193) | pub fn from_bytespan(
method from_terminals (line 209) | pub fn from_terminals(&mut self, terminals: &[LocationTerminal]) -> Lo...
method concat_locations (line 221) | pub fn concat_locations(&mut self, bottom: Location, top: Location) ->...
method location_eq (line 249) | pub fn location_eq(&self, l_loc: Location, r: &Self, r_loc: Location) ...
method format_loc (line 276) | pub fn format_loc(&self, loc: Location) -> String {
FILE: libeir_ir/src/function/mod.rs
type Block (line 43) | pub struct Block(u32);
method aux_fmt (line 51) | fn aux_fmt(&self, f: &mut std::fmt::Formatter<'_>, _aux: &C) -> std::f...
method default (line 46) | fn default() -> Self {
type Argument (line 57) | pub struct Argument(u32);
type FunRef (line 62) | pub struct FunRef(u32);
type PrimOp (line 66) | pub struct PrimOp(u32);
type BlockData (line 70) | pub struct BlockData {
type PrimOpData (line 87) | pub struct PrimOpData {
method aux_hash (line 92) | fn aux_hash<H: Hasher>(&self, state: &mut H, container: &PoolContainer) {
method aux_eq (line 98) | fn aux_eq(
type AttributeKey (line 112) | pub enum AttributeKey {
type AttributeValue (line 116) | pub enum AttributeValue {
type Function (line 121) | pub struct Function {
method dialect (line 143) | pub fn dialect(&self) -> &ArcDialect {
method span (line 147) | pub fn span(&self) -> SourceSpan {
method cons (line 151) | pub fn cons(&self) -> &ConstantContainer {
method get_aux (line 157) | fn get_aux(&self) -> &ListPool<Value> {
method get_aux (line 162) | fn get_aux(&self) -> &SetForest<Block> {
method aux_fmt (line 168) | fn aux_fmt(&self, _f: &mut std::fmt::Formatter<'_>, _container: &C) ->...
method fmt (line 174) | fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
method value_get (line 181) | pub fn value_get<T>(&self, v: T) -> Option<Value>
method iter_constants (line 188) | pub fn iter_constants(&self) -> std::collections::hash_set::Iter<'_, V...
method const_kind (line 192) | pub fn const_kind(&self, constant: Const) -> &ConstKind {
method const_entries (line 196) | pub fn const_entries<'f>(&'f self, entries: &'f EntityList<Const>) -> ...
method value_kind (line 200) | pub fn value_kind(&self, value: Value) -> ValueKind {
method value_locations (line 204) | pub fn value_locations(&self, value: Value) -> Option<Vec<SourceSpan>> {
method value_is_constant (line 211) | pub fn value_is_constant(&self, value: Value) -> bool {
method value_list_length (line 215) | pub fn value_list_length(&self, value: Value) -> usize {
method value_list_get_n (line 227) | pub fn value_list_get_n(&self, value: Value, n: usize) -> Option<Value> {
method value_argument (line 246) | pub fn value_argument(&self, value: Value) -> Option<(Block, usize)> {
method value_block (line 254) | pub fn value_block(&self, value: Value) -> Option<Block> {
method value_const (line 262) | pub fn value_const(&self, value: Value) -> Option<Const> {
method value_primop (line 270) | pub fn value_primop(&self, value: Value) -> Option<PrimOp> {
method value_usages (line 278) | pub fn value_usages(&self, value: Value) -> BoundSet<Block, ()> {
method value_walk_nested_values (line 284) | pub fn value_walk_nested_values<F, R>(&self, value: Value, visit: &mut...
method value_walk_nested_values_mut (line 294) | pub fn value_walk_nested_values_mut<F, R>(
method primop_kind (line 312) | pub fn primop_kind(&self, primop: PrimOp) -> &PrimOpKind {
method primop_reads (line 315) | pub fn primop_reads(&self, primop: PrimOp) -> &[Value] {
method primop_walk_nested_values (line 319) | pub fn primop_walk_nested_values<F, R>(&self, primop: PrimOp, visit: &...
method primop_walk_nested_values_mut (line 330) | pub fn primop_walk_nested_values_mut<F, R>(
method block_insert (line 350) | fn block_insert(&mut self) -> Block {
method block_insert_with_span (line 354) | fn block_insert_with_span(&mut self, span: Option<SourceSpan>) -> Block {
method block_arg_insert (line 373) | fn block_arg_insert(&mut self, block: Block) -> Value {
method block_arg_n (line 380) | pub fn block_arg_n(&self, block: Block, num: usize) -> Option<Value> {
method block_kind (line 384) | pub fn block_kind(&self, block: Block) -> Option<&OpKind> {
method block_location (line 388) | pub fn block_location(&self, block: Block) -> Location {
method block_locations (line 392) | pub fn block_locations(&self, block: Block) -> Vec<SourceSpan> {
method block_entry (line 397) | pub fn block_entry(&self) -> Block {
method block_args (line 400) | pub fn block_args<B>(&self, block: B) -> &[Value]
method block_reads (line 408) | pub fn block_reads(&self, block: Block) -> &[Value] {
method block_value (line 412) | pub fn block_value(&self, block: Block) -> Value {
method block_walk_nested_values (line 416) | pub fn block_walk_nested_values<F, R>(&self, block: Block, visit: &mut...
method block_walk_nested_values_mut (line 427) | pub fn block_walk_nested_values_mut<F, R>(
method block_op_eq (line 443) | pub fn block_op_eq(&self, lb: Block, r_fun: &Function, rb: Block) -> b...
method block_iter (line 459) | pub fn block_iter(&self) -> impl Iterator<Item = Block> {
method graph_validate_block (line 468) | pub(crate) fn graph_validate_block(&self, block: Block) {
method graph_validate_global (line 494) | pub fn graph_validate_global(&self) {
method new (line 542) | pub fn new(span: SourceSpan, ident: FunctionIdent) -> Self {
method ident (line 568) | pub fn ident(&self) -> &FunctionIdent {
method entry_arg_num (line 572) | pub fn entry_arg_num(&self) -> usize {
type GeneralSet (line 501) | pub trait GeneralSet<V> {
method contains (line 502) | fn contains(&self, key: &V, fun: &Function) -> bool;
method insert (line 503) | fn insert(&mut self, key: V, fun: &mut Function) -> bool;
function contains (line 509) | fn contains(&self, key: &V, _fun: &Function) -> bool {
function insert (line 512) | fn insert(&mut self, key: V, _fun: &mut Function) -> bool {
function contains (line 520) | fn contains(&self, key: &V, fun: &Function) -> bool {
function insert (line 523) | fn insert(&mut self, key: V, fun: &mut Function) -> bool {
type SetPoolProvider (line 528) | pub trait SetPoolProvider: Sized + Copy {
method pool (line 529) | fn pool(fun: &Function) -> &SetForest<Self>;
method pool_mut (line 530) | fn pool_mut(fun: &mut Function) -> &mut SetForest<Self>;
method pool (line 533) | fn pool(fun: &Function) -> &SetForest<Block> {
method pool_mut (line 536) | fn pool_mut(fun: &mut Function) -> &mut SetForest<Block> {
FILE: libeir_ir/src/function/op.rs
type CallKind (line 7) | pub enum CallKind {
type BasicType (line 18) | pub enum BasicType {
type MatchKind (line 39) | pub enum MatchKind {
type MapPutUpdate (line 64) | pub enum MapPutUpdate {
type OpKind (line 72) | pub enum OpKind {
method is_call (line 141) | pub fn is_call(&self) -> bool {
method get_dyn (line 148) | pub fn get_dyn<O: Op>(&self) -> Option<&O> {
FILE: libeir_ir/src/function/pool_container.rs
type PoolContainer (line 7) | pub struct PoolContainer {
FILE: libeir_ir/src/function/primop.rs
type BinOp (line 4) | pub enum BinOp {
method symmetric (line 23) | pub fn symmetric(self) -> bool {
type LogicOp (line 35) | pub enum LogicOp {
type PrimOpKind (line 43) | pub enum PrimOpKind {
FILE: libeir_ir/src/function/serialize.rs
method serialize (line 6) | fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
FILE: libeir_ir/src/function/value.rs
type Value (line 11) | pub struct Value(u32);
method aux_fmt (line 19) | fn aux_fmt(&self, f: &mut std::fmt::Formatter<'_>, _aux: &C) -> std::f...
method default (line 14) | fn default() -> Self {
method make_id (line 26) | fn make_id(&self, out: &mut String) {
type ValueData (line 33) | pub struct ValueData {
type ValueKind (line 40) | pub enum ValueKind {
method is_arg (line 48) | pub fn is_arg(&self) -> bool {
type ValueMap (line 57) | pub struct ValueMap {
method new (line 63) | pub fn new() -> Self {
method push (line 70) | pub fn push(&mut self, kind: ValueKind) -> Value {
method push_with_location (line 74) | pub fn push_with_location(&mut self, kind: ValueKind, location: Option...
method get (line 88) | pub fn get(&self, kind: ValueKind) -> Option<Value> {
type Output (line 94) | type Output = ValueData;
method index (line 95) | fn index(&self, key: Value) -> &ValueData {
method index_mut (line 100) | fn index_mut(&mut self, key: Value) -> &mut ValueData {
FILE: libeir_ir/src/graph/block_graph.rs
method block_graph (line 17) | pub fn block_graph(&self) -> BlockGraph<'_> {
type BlockGraph (line 32) | pub struct BlockGraph<'a> {
function new (line 37) | pub fn new(fun: &'a Function) -> Self {
function dfs (line 41) | pub fn dfs(&self) -> Dfs<Block, EntityVisitMap<Block>> {
function dfs_iter (line 45) | pub fn dfs_iter(&'a self) -> impl Iterator<Item = Block> + 'a {
function dfs_post_order (line 49) | pub fn dfs_post_order(&self) -> DfsPostOrder<Block, EntityVisitMap<Block...
function dfs_post_order_iter (line 53) | pub fn dfs_post_order_iter(&'a self) -> impl Iterator<Item = Block> + 'a {
function outgoing (line 57) | pub fn outgoing(&'a self, block: Block) -> impl Iterator<Item = Block> +...
type BlockEdge (line 65) | pub struct BlockEdge(Block, usize);
type BlockSuccessors (line 67) | pub struct BlockSuccessors<'a> {
type Item (line 71) | type Item = Block;
method next (line 73) | fn next(&mut self) -> Option<Block> {
type BlockPredecessors (line 78) | pub struct BlockPredecessors<'a> {
function new (line 82) | fn new(graph: &'a BlockGraph, block: Block) -> Self {
type Item (line 91) | type Item = Block;
method next (line 93) | fn next(&mut self) -> Option<Block> {
type NodeId (line 99) | type NodeId = Block;
type EdgeId (line 100) | type EdgeId = BlockEdge;
type Neighbors (line 104) | type Neighbors = BlockSuccessors<'a>;
method neighbors (line 106) | fn neighbors(self, block: Block) -> Self::Neighbors {
type NeighborsDirected (line 115) | type NeighborsDirected = Either<BlockSuccessors<'a>, BlockPredecessors<'...
method neighbors_directed (line 117) | fn neighbors_directed(self, block: Block, dir: Direction) -> Self::Neigh...
type EntityVisitMap (line 125) | pub struct EntityVisitMap<E>
function new (line 135) | pub fn new(size: usize) -> Self {
function reset (line 140) | pub fn reset(&mut self, size: usize) {
function visit (line 150) | fn visit(&mut self, a: E) -> bool {
function is_visited (line 154) | fn is_visited(&self, a: &E) -> bool {
type Map (line 160) | type Map = EntityVisitMap<Block>;
method visit_map (line 162) | fn visit_map(&self) -> EntityVisitMap<Block> {
method reset_map (line 166) | fn reset_map(&self, map: &mut EntityVisitMap<Block>) {
function test_edge (line 182) | fn test_edge() {
FILE: libeir_ir/src/graph/control_flow_graph.rs
method control_flow_graph (line 16) | pub fn control_flow_graph(&self) -> ControlFlowGraph {
type CfgBranch (line 22) | pub struct CfgBranch(pub usize);
type ControlFlowGraph (line 30) | pub struct ControlFlowGraph {
method new (line 38) | pub fn new() -> Self {
method calculate (line 47) | pub fn calculate(&mut self, fun: &Function, entry: Value) {
method dfs (line 76) | pub fn dfs(&self) -> Dfs<Value, EntityVisitMap<Value>> {
method dfs_iter (line 80) | pub fn dfs_iter<'a>(&'a self) -> impl Iterator<Item = Value> + 'a {
method dfs_post_order (line 84) | pub fn dfs_post_order(&self) -> DfsPostOrder<Value, EntityVisitMap<Val...
method dfs_post_order_iter (line 88) | pub fn dfs_post_order_iter<'a>(&'a self) -> impl Iterator<Item = Value...
type NodeId (line 94) | type NodeId = Value;
type EdgeId (line 95) | type EdgeId = CfgBranch;
type ControlFlowSuccessors (line 98) | pub struct ControlFlowSuccessors<'a> {
type Item (line 104) | type Item = Value;
method next (line 105) | fn next(&mut self) -> Option<Value> {
type ControlFlowPredecessors (line 115) | pub struct ControlFlowPredecessors<'a> {
function new (line 121) | pub fn new(graph: &'a ControlFlowGraph, value: Value) -> Self {
type Item (line 130) | type Item = Value;
method next (line 131) | fn next(&mut self) -> Option<Value> {
type Neighbors (line 142) | type Neighbors = ControlFlowSuccessors<'a>;
method neighbors (line 143) | fn neighbors(self, value: Value) -> Self::Neighbors {
type NeighborsDirected (line 152) | type NeighborsDirected = Either<ControlFlowSuccessors<'a>, ControlFlowPr...
method neighbors_directed (line 153) | fn neighbors_directed(self, value: Value, dir: Direction) -> Self::Neigh...
type Map (line 162) | type Map = EntityVisitMap<Value>;
method visit_map (line 164) | fn visit_map(&self) -> EntityVisitMap<Value> {
method reset_map (line 168) | fn reset_map(&self, map: &mut EntityVisitMap<Value>) {
FILE: libeir_ir/src/graph/live_block_graph.rs
method live_block_graph (line 21) | pub fn live_block_graph(&self) -> LiveBlockGraph<'_> {
type LiveBlockGraph (line 33) | pub struct LiveBlockGraph<'a> {
function new (line 39) | pub fn new(fun: &'a Function) -> Self {
function dfs (line 50) | pub fn dfs(&self) -> Dfs<Block, EntityVisitMap<Block>> {
function dfs_iter (line 53) | pub fn dfs_iter(&'a self) -> impl Iterator<Item = Block> + 'a {
function dfs_post_order (line 57) | pub fn dfs_post_order(&self) -> DfsPostOrder<Block, EntityVisitMap<Block...
function dfs_post_order_iter (line 60) | pub fn dfs_post_order_iter(&'a self) -> impl Iterator<Item = Block> + 'a {
function outgoing (line 64) | pub fn outgoing(&'a self, block: Block) -> impl Iterator<Item = Block> +...
function incoming (line 68) | pub fn incoming(&'a self, block: Block) -> impl Iterator<Item = Block> +...
type LiveBlockPredecessors (line 76) | pub struct LiveBlockPredecessors<'a> {
function new (line 81) | fn new(graph: &'a LiveBlockGraph, block: Block) -> Self {
type Item (line 91) | type Item = Block;
method next (line 93) | fn next(&mut self) -> Option<Block> {
type NodeId (line 104) | type NodeId = Block;
type EdgeId (line 105) | type EdgeId = BlockEdge;
type Neighbors (line 109) | type Neighbors = BlockSuccessors<'a>;
method neighbors (line 111) | fn neighbors(self, block: Block) -> Self::Neighbors {
type NeighborsDirected (line 117) | type NeighborsDirected = Either<BlockSuccessors<'a>, LiveBlockPredecesso...
method neighbors_directed (line 119) | fn neighbors_directed(self, block: Block, dir: Direction) -> Self::Neigh...
type Map (line 128) | type Map = EntityVisitMap<Block>;
method visit_map (line 130) | fn visit_map(&self) -> EntityVisitMap<Block> {
method reset_map (line 134) | fn reset_map(&self, map: &mut EntityVisitMap<Block>) {
type NodeIterator (line 139) | pub struct NodeIterator(Vec<Block>, usize);
type Item (line 141) | type Item = Block;
method next (line 142) | fn next(&mut self) -> Option<Block> {
type NodeIdentifiers (line 150) | type NodeIdentifiers = NodeIterator;
method node_identifiers (line 151) | fn node_identifiers(self) -> Self::NodeIdentifiers {
function test_back_edge (line 168) | fn test_back_edge() {
FILE: libeir_ir/src/ir_construct_macro.rs
function basic_ir_build (line 110) | fn basic_ir_build() {
FILE: libeir_ir/src/lib.rs
type FunctionIdent (line 65) | pub struct FunctionIdent {
method cmp (line 71) | fn cmp(&self, other: &FunctionIdent) -> Ordering {
method fmt (line 76) | fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
FILE: libeir_ir/src/module.rs
type FunctionDefinition (line 10) | pub struct FunctionDefinition {
method index (line 15) | pub fn index(&self) -> FunctionIndex {
method function (line 19) | pub fn function(&self) -> &Function {
method function_mut (line 23) | pub fn function_mut(&mut self) -> &mut Function {
type FunctionIndex (line 29) | pub struct FunctionIndex(u32);
type Module (line 32) | pub struct Module {
method new (line 39) | pub fn new(name: Ident) -> Self {
method new_with_span (line 48) | pub fn new_with_span(name: Ident, span: SourceSpan) -> Self {
method name (line 57) | pub fn name(&self) -> Ident {
method span (line 61) | pub fn span(&self) -> SourceSpan {
method add_function (line 65) | pub fn add_function(
method ident_index (line 92) | pub fn ident_index(&self, ident: &FunctionIdent) -> Option<FunctionInd...
method name_arity_index (line 95) | pub fn name_arity_index(&self, name: Symbol, arity: usize) -> Option<F...
method function_iter (line 99) | pub fn function_iter(&self) -> impl Iterator<Item = &FunctionDefinitio...
method function_iter_mut (line 102) | pub fn function_iter_mut(&mut self) -> impl Iterator<Item = &mut Funct...
method index_iter (line 106) | pub fn index_iter(&self) -> impl Iterator<Item = FunctionIndex> {
type Output (line 134) | type Output = FunctionDefinition;
method index (line 135) | fn index(&self, idx: FunctionIndex) -> &FunctionDefinition {
method index_mut (line 140) | fn index_mut(&mut self, idx: FunctionIndex) -> &mut FunctionDefinition {
type Output (line 146) | type Output = FunctionDefinition;
method index (line 147) | fn index(&self, ident: &FunctionIdent) -> &FunctionDefinition {
method clone (line 111) | fn clone(&self) -> Self {
FILE: libeir_ir/src/operation/binary_construct.rs
type BinaryConstructToken (line 52) | pub struct BinaryConstructToken(());
type BinaryConstructStart (line 57) | pub struct BinaryConstructStart;
method build (line 74) | pub fn build(builder: &mut FunctionBuilder, block: Block) -> Block {
method build_target (line 81) | pub fn build_target(builder: &mut FunctionBuilder, block: Block, targe...
method branches_len (line 62) | fn branches_len(&self) -> usize {
method branch_num (line 65) | fn branch_num(&self, fun: &Function, block: Block, branch_n: usize) -> V...
type Token (line 92) | type Token = BinaryConstructToken;
type BinaryConstructPush (line 99) | pub struct BinaryConstructPush {
method build (line 140) | pub fn build(
method build_target (line 155) | pub fn build_target(
method name (line 105) | fn name(&self) -> &str {
method dyn_clone (line 108) | fn dyn_clone(&self) -> DynOp {
method type_id (line 111) | fn type_id(&self) -> TypeId {
method meta_entry (line 114) | fn meta_entry(&self) -> &dyn MetaEntry {
method op_eq (line 117) | fn op_eq(&self, other: &dyn Op) -> bool {
method branches_len (line 127) | fn branches_len(&self) -> usize {
method branch_num (line 130) | fn branch_num(&self, fun: &Function, block: Block, branch_n: usize) -> V...
type Token (line 186) | type Token = BinaryConstructToken;
type BinaryConstructFinish (line 192) | pub struct BinaryConstructFinish;
method build (line 223) | pub fn build(builder: &mut FunctionBuilder, block: Block, bin_ref: Val...
method build_target (line 230) | pub fn build_target(
method name (line 196) | fn name(&self) -> &str {
method dyn_clone (line 199) | fn dyn_clone(&self) -> DynOp {
method type_id (line 202) | fn type_id(&self) -> TypeId {
method meta_entry (line 205) | fn meta_entry(&self) -> &dyn MetaEntry {
method branches_len (line 211) | fn branches_len(&self) -> usize {
method branch_num (line 214) | fn branch_num(&self, fun: &Function, block: Block, branch_n: usize) -> V...
type Token (line 246) | type Token = BinaryConstructToken;
function register (line 249) | pub fn register(dialect: &mut Dialect) {
FILE: libeir_ir/src/operation/case.rs
type CaseToken (line 16) | pub struct CaseToken(());
type Case (line 37) | pub struct Case {
method pat (line 43) | pub fn pat<'a>(&'a self) -> &'a PatternContainer {
method clauses (line 46) | pub fn clauses<'a>(&'a self) -> &'a [PatternClause] {
method builder (line 115) | pub fn builder() -> CaseBuilder {
type Inner (line 52) | struct Inner {
method name (line 58) | fn name(&self) -> &str {
method dyn_clone (line 61) | fn dyn_clone(&self) -> DynOp {
method type_id (line 64) | fn type_id(&self) -> TypeId {
method meta_entry (line 67) | fn meta_entry(&self) -> &dyn MetaEntry {
method op_eq (line 70) | fn op_eq(&self, other: &dyn Op) -> bool {
method branches_len (line 80) | fn branches_len(&self) -> usize {
method branch_num (line 83) | fn branch_num(&self, fun: &Function, block: Block, branch_n: usize) -> V...
method to_doc (line 97) | fn to_doc<'doc>(&self, ctx: &mut dyn FormatOpCtx<'doc>, _block: Block) -...
type CaseBuilder (line 120) | pub struct CaseBuilder {
method new (line 151) | pub fn new(span: SourceSpan) -> Self {
method set_span (line 157) | pub fn set_span(&mut self, span: SourceSpan) {
method push_clause (line 161) | pub fn push_clause<'a>(
method push_value (line 172) | pub fn push_value<'a>(&mut self, value: Value, _b: &mut FunctionBuilde...
method finish (line 176) | pub fn finish<'a>(self, block: Block, b: &mut FunctionBuilder<'a>) {
method default (line 134) | fn default() -> Self {
type Token (line 248) | type Token = CaseToken;
type CaseParser (line 263) | struct CaseParser;
method parse (line 265) | fn parse(
function parse_case_body (line 283) | fn parse_case_body(ctx: &mut ParseCtx) -> Result<(), DynParserError> {
function register (line 289) | pub fn register(dialect: &mut Dialect) {
function basic_parse (line 301) | fn basic_parse() {
FILE: libeir_ir/src/operation/mod.rs
type Op (line 33) | pub trait Op: MetaEntry + Send {
method name (line 34) | fn name(&self) -> &str;
method dyn_clone (line 36) | fn dyn_clone(&self) -> DynOp;
method type_id (line 38) | fn type_id(&self) -> TypeId;
method meta_entry (line 40) | fn meta_entry(&self) -> &dyn MetaEntry;
method op_eq (line 45) | fn op_eq(&self, other: &dyn Op) -> bool {
method debug_fmt (line 49) | fn debug_fmt(&self, formatter: &mut Formatter) -> FmtResult {
function try_cast (line 55) | pub fn try_cast<T: Op>(&self) -> Option<&T> {
function downcast_ref (line 62) | pub fn downcast_ref<T: Op>(&self) -> Option<&T> {
function downcast_ref_unchecked (line 75) | pub unsafe fn downcast_ref_unchecked<T: Op>(&self) -> &T {
type OpBuild (line 81) | pub trait OpBuild: Op {
type DynOp (line 92) | pub struct DynOp(Value<dyn Op>);
method new (line 95) | pub fn new<T: Op>(value: T) -> Self {
type Target (line 101) | type Target = dyn Op;
method deref (line 102) | fn deref(&self) -> &dyn Op {
method clone (line 108) | fn clone(&self) -> Self {
method fmt (line 114) | fn fmt(&self, formatter: &mut Formatter) -> FmtResult {
FILE: libeir_ir/src/operation/receive.rs
type ReceiveToken (line 38) | pub struct ReceiveToken(());
type ReceiveStart (line 53) | pub struct ReceiveStart;
method build (line 99) | pub fn build(builder: &mut FunctionBuilder, block: Block, timeout: Val...
method build_target (line 106) | pub fn build_target(
method name (line 57) | fn name(&self) -> &str {
method dyn_clone (line 60) | fn dyn_clone(&self) -> DynOp {
method type_id (line 63) | fn type_id(&self) -> TypeId {
method meta_entry (line 66) | fn meta_entry(&self) -> &dyn MetaEntry {
method op_eq (line 69) | fn op_eq(&self, other: &dyn Op) -> bool {
method branches_len (line 75) | fn branches_len(&self) -> usize {
method branch_num (line 78) | fn branch_num(&self, fun: &Function, block: Block, branch_n: usize) -> V...
method to_doc (line 87) | fn to_doc<'doc>(&self, ctx: &mut dyn FormatOpCtx<'doc>, block: Block) ->...
type Token (line 122) | type Token = ReceiveToken;
type ReceiveWait (line 141) | pub struct ReceiveWait;
method build (line 176) | pub fn build(builder: &mut FunctionBuilder, block: Block, recv_ref: Va...
method build_target (line 187) | pub fn build_target(
method name (line 145) | fn name(&self) -> &str {
method dyn_clone (line 148) | fn dyn_clone(&self) -> DynOp {
method type_id (line 151) | fn type_id(&self) -> TypeId {
method meta_entry (line 154) | fn meta_entry(&self) -> &dyn MetaEntry {
method op_eq (line 157) | fn op_eq(&self, other: &dyn Op) -> bool {
method branches_len (line 163) | fn branches_len(&self) -> usize {
method branch_num (line 166) | fn branch_num(&self, fun: &Function, block: Block, branch_n: usize) -> V...
type Token (line 205) | type Token = ReceiveToken;
type ReceiveDone (line 225) | pub struct ReceiveDone;
method build (line 259) | pub fn build(
method build_target (line 275) | pub fn build_target(
method name (line 229) | fn name(&self) -> &str {
method dyn_clone (line 232) | fn dyn_clone(&self) -> DynOp {
method type_id (line 235) | fn type_id(&self) -> TypeId {
method meta_entry (line 238) | fn meta_entry(&self) -> &dyn MetaEntry {
method op_eq (line 241) | fn op_eq(&self, other: &dyn Op) -> bool {
method branches_len (line 247) | fn branches_len(&self) -> usize {
method branch_num (line 250) | fn branch_num(&self, fun: &Function, block: Block, branch_n: usize) -> V...
type Token (line 293) | type Token = ReceiveToken;
function register (line 296) | pub fn register(dialect: &mut Dialect) {
FILE: libeir_ir/src/pattern/fmt.rs
method fmt (line 5) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
FILE: libeir_ir/src/pattern/mod.rs
type PatternNode (line 12) | pub struct PatternNode(u32);
type PatternValue (line 18) | pub struct PatternValue(u32);
type PatternClause (line 22) | pub struct PatternClause(u32);
type PatternContainer (line 26) | pub struct PatternContainer {
method new (line 127) | pub fn new() -> Self {
method clause_value (line 131) | pub fn clause_value(&mut self, clause: PatternClause) -> PatternValue {
method clause_node_value (line 137) | pub fn clause_node_value(&mut self, clause: PatternClause, node: Patte...
method node_empty (line 147) | pub fn node_empty(&mut self, span: Option<SourceSpan>) -> PatternNode {
method binary (line 155) | pub fn binary(
method wildcard (line 175) | pub fn wildcard(&mut self, node: PatternNode) {
method constant (line 182) | pub fn constant(&mut self, node: PatternNode, val: Const) {
method value (line 189) | pub fn value(&mut self, node: PatternNode, val: PatternValue) {
method tuple (line 196) | pub fn tuple(&mut self, node: PatternNode) {
method tuple_elem_push (line 202) | pub fn tuple_elem_push(&mut self, tup: PatternNode, node: PatternNode) {
method list (line 213) | pub fn list(&mut self, node: PatternNode, head: PatternNode, tail: Pat...
method map (line 220) | pub fn map(&mut self, node: PatternNode) {
method map_push (line 229) | pub fn map_push(&mut self, map: PatternNode, key: PatternValue, value:...
method node_finish (line 245) | pub fn node_finish(&mut self, node: PatternNode) {
method node_set_span (line 251) | pub fn node_set_span(&mut self, node: PatternNode, span: SourceSpan) {
method clause_start (line 255) | pub fn clause_start(&mut self, span: SourceSpan) -> PatternClause {
method clause_node_push (line 270) | pub fn clause_node_push(&mut self, clause: PatternClause, node: Patter...
method clause_bind_push (line 276) | pub fn clause_bind_push(&mut self, clause: PatternClause, node: Patter...
method clause_value_push (line 282) | pub fn clause_value_push(&mut self, clause: PatternClause, val: Patter...
method clause_finish (line 288) | pub fn clause_finish(&mut self, clause: PatternClause) {
method copy_from (line 295) | pub fn copy_from(&mut self, clause: PatternClause, from: &PatternConta...
method update_binds (line 341) | pub fn update_binds(&mut self, clause: PatternClause, map: &HashMap<Pa...
method clause_root_nodes (line 355) | pub fn clause_root_nodes(&self, clause: PatternClause) -> &[PatternNod...
method clause_binds (line 360) | pub fn clause_binds(&self, clause: PatternClause) -> &[PatternNode] {
method clause_values (line 365) | pub fn clause_values(&self, clause: PatternClause) -> &[PatternValue] {
method clause_node_binds_iter (line 370) | pub fn clause_node_binds_iter<'a>(
method node_span (line 387) | pub fn node_span(&self, node: PatternNode) -> SourceSpan {
method node_kind (line 391) | pub fn node_kind(&self, node: PatternNode) -> &PatternNodeKind {
method merge_patterns (line 462) | pub fn merge_patterns(
method merge_pattern_constant (line 575) | pub fn merge_pattern_constant(
method make_structural (line 685) | pub fn make_structural(&mut self, clause: PatternClause) -> PatternCla...
method default (line 40) | fn default() -> PatternContainer {
type PatternClauseData (line 56) | struct PatternClauseData {
type PatternNodeData (line 78) | struct PatternNodeData {
type PatternNodeKind (line 85) | pub enum PatternNodeKind {
type PatternBinaryEntryData (line 108) | pub struct PatternBinaryEntryData {}
type PatternMergeFail (line 110) | pub enum PatternMergeFail {
function copy_pattern_node (line 396) | fn copy_pattern_node(
FILE: libeir_ir/src/text/ast/mod.rs
type DynToken (line 8) | pub enum DynToken {
method span (line 51) | pub fn span(&self) -> SourceSpan {
type Module (line 98) | pub struct Module {
type ModuleItem (line 105) | pub enum ModuleItem {
type Function (line 110) | pub struct Function {
type FunctionItem (line 118) | pub enum FunctionItem {
type Meta (line 126) | pub struct Meta {
type Label (line 133) | pub struct Label {
type Assignment (line 141) | pub struct Assignment {
type Op (line 148) | pub enum Op {
type CaseOp (line 161) | pub struct CaseOp {
type CaseEntry (line 169) | pub struct CaseEntry {
type CasePattern (line 178) | pub enum CasePattern {
type MatchOp (line 195) | pub struct MatchOp {
type MatchEntry (line 201) | pub struct MatchEntry {
type MatchKind (line 207) | pub enum MatchKind {
type UnpackValueListOp (line 218) | pub struct UnpackValueListOp {
type CallControlFlowOp (line 226) | pub struct CallControlFlowOp {
type CallFunctionOp (line 232) | pub struct CallFunctionOp {
type IfBoolOp (line 241) | pub struct IfBoolOp {
type TraceCaptureRawOp (line 250) | pub struct TraceCaptureRawOp {
type Value (line 256) | pub enum Value {
method value (line 272) | pub fn value(&self) -> Option<Ident> {
method block (line 278) | pub fn block(&self) -> Option<Ident> {
FILE: libeir_ir/src/text/ast/raise.rs
type RaiseCtx (line 11) | struct RaiseCtx {
method block_name (line 16) | pub fn block_name(&mut self, _block: Block) -> Ident {
method value_name (line 20) | pub fn value_name(&mut self, _value: Value) -> Ident {
method raise (line 26) | pub fn raise(&self) -> ast::Function {
FILE: libeir_ir/src/text/dot_printer.rs
function function_into_graph_printer (line 12) | pub fn function_into_graph_printer<O>(fun: &Function, g: &mut GraphPrint...
function function_to_dot (line 56) | pub fn function_to_dot(fun: &Function) -> String {
FILE: libeir_ir/src/text/lower/location.rs
type ParsedTerminalLocation (line 6) | pub struct ParsedTerminalLocation {
type ParsedLocation (line 13) | pub struct ParsedLocation {
function parse_terminal_location (line 17) | pub fn parse_terminal_location(
function parse_location (line 47) | pub fn parse_location(ctx: &mut ParseCtx) -> Result<ParsedLocation, DynP...
FILE: libeir_ir/src/text/lower/mod.rs
type ErrCollector (line 17) | type ErrCollector<'a> = &'a mut dyn ErrorReceiver<E = LowerError, W = Lo...
type LowerContext (line 19) | pub struct LowerContext<'a, 'b> {
function error (line 26) | pub fn error<T: ToDiagnostic>(&mut self, diag: T) {
type LowerError (line 34) | pub enum LowerError {
method to_diagnostic (line 72) | fn to_diagnostic(&self) -> Diagnostic {
type LowerMap (line 109) | pub struct LowerMap {
method get_value (line 114) | pub fn get_value(&self, ident: &str) -> Value {
method get_block (line 118) | pub fn get_block(&self, ident: &str) -> Block {
function lower (line 124) | pub fn lower(&self, errors: ErrCollector) -> Result<Module, ()> {
type Name (line 146) | pub enum Name {
method span (line 151) | pub fn span(&self) -> SourceSpan {
function insert_check_duplicate (line 159) | fn insert_check_duplicate(
function lower (line 178) | pub fn lower(&self, errors: ErrCollector, module: Ident) -> Result<(Func...
function lower_into (line 192) | pub fn lower_into(
function lower_operation (line 328) | fn lower_operation(
function lower_case_pattern (line 480) | fn lower_case_pattern(
function lower_value (line 510) | fn lower_value(
FILE: libeir_ir/src/text/parse_dyn/mod.rs
type Nesting (line 10) | pub enum Nesting {
type Token (line 20) | pub enum Token {
function flatten_dyn_token (line 68) | pub fn flatten_dyn_token(tok: &[DynToken]) -> Vec<(Token, SourceSpan)> {
type ParseCtx (line 225) | pub struct ParseCtx<'a> {
type DynParserError (line 233) | pub enum DynParserError {
method to_diagnostic (line 239) | fn to_diagnostic(&self) -> Diagnostic {
function new (line 252) | pub fn new(tokens: &'a [DynToken], span: SourceSpan) -> Self {
function pop (line 260) | pub fn pop(&mut self) -> Result<&'a DynToken, DynParserError> {
function peek (line 277) | pub fn peek(&self) -> Option<&'a DynToken> {
function try_parse (line 281) | pub fn try_parse<R, E>(
function comma (line 295) | pub fn comma<R, E>(
function repeat_any (line 314) | pub fn repeat_any<R, E>(&mut self, fun: impl Fn(&mut ParseCtx) -> Result...
function eof (line 325) | pub fn eof(&mut self) -> Result<(), DynParserError> {
function tok_string (line 332) | pub fn tok_string(&mut self) -> Result<Ident, DynParserError> {
function tok_integer (line 338) | pub fn tok_integer(&mut self) -> Result<(&'a Integer, SourceSpan), DynPa...
function tok_colon (line 345) | pub fn tok_colon(&mut self) -> Result<SourceSpan, DynParserError> {
function tok_at (line 351) | pub fn tok_at(&mut self) -> Result<SourceSpan, DynParserError> {
type ParsePos (line 365) | pub struct ParsePos(usize);
function val (line 367) | pub fn val(ctx: &mut ParseCtx) -> Result<Value, DynParserError> {
function val_value_list (line 383) | pub fn val_value_list(ctx: &mut ParseCtx) -> Result<Value, DynParserErro...
function val_list (line 400) | pub fn val_list(ctx: &mut ParseCtx) -> Result<Value, DynParserError> {
function val_atomic (line 419) | pub fn val_atomic(ctx: &mut ParseCtx) -> Result<Value, DynParserError> {
FILE: libeir_ir/src/text/parser/errors.rs
type ParseError (line 10) | pub type ParseError = lalrpop_util::ParseError<SourceIndex, Token, Parse...
type Errors (line 12) | pub type Errors = libeir_util_parse::Errors<ParserError, ParserError>;
type ParserError (line 16) | pub enum ParserError {
method span (line 61) | pub fn span(&self) -> Option<SourceSpan> {
method from (line 99) | fn from(err: LowerError) -> ParserError {
method from (line 104) | fn from(err: ParseError) -> ParserError {
method from (line 131) | fn from(diagnostic: Diagnostic) -> ParserError {
method to_diagnostic (line 72) | fn to_diagnostic(&self) -> Diagnostic {
FILE: libeir_ir/src/text/parser/lexer.rs
type LexicalError (line 58) | pub struct LexicalError;
type LexicalToken (line 61) | pub struct LexicalToken(pub SourceIndex, pub Token, pub SourceIndex);
method token (line 63) | pub fn token(&self) -> Token {
method span (line 67) | pub fn span(&self) -> SourceSpan {
type Token (line 73) | pub enum Token {
function is_escapechar (line 151) | fn is_escapechar(c: char) -> bool {
function is_control (line 165) | fn is_control(c: char) -> bool {
function is_inputchar (line 168) | fn is_inputchar(c: char) -> bool {
function is_digit (line 171) | fn is_digit(c: char) -> bool {
function is_octal (line 174) | fn is_octal(c: char) -> bool {
function is_uppercase (line 177) | fn is_uppercase(c: char) -> bool {
function is_lowercase (line 182) | fn is_lowercase(c: char) -> bool {
function is_namechar (line 187) | fn is_namechar(c: char) -> bool {
type Lexer (line 191) | pub struct Lexer<S> {
function new (line 203) | pub fn new(scanner: Scanner<S>) -> Self {
function lex (line 216) | pub fn lex(&mut self) -> Option<<Self as Iterator>::Item> {
function advance (line 237) | fn advance(&mut self) {
function advance_start (line 242) | fn advance_start(&mut self) {
function pop (line 282) | fn pop(&mut self) -> char {
function peek (line 287) | fn peek(&mut self) -> char {
function peek_next (line 290) | fn peek_next(&mut self) -> char {
function read (line 293) | fn read(&mut self) -> char {
function skip (line 296) | fn skip(&mut self) {
function span (line 299) | pub fn span(&self) -> SourceSpan {
function slice (line 302) | fn slice(&self) -> &str {
function slice_span (line 305) | fn slice_span(&self, span: impl Into<Range<usize>>) -> &str {
function ident (line 308) | fn ident(&self) -> Ident {
function skip_whitespace (line 312) | fn skip_whitespace(&mut self) {
function tokenize (line 319) | fn tokenize(&mut self) -> Token {
function lex_ident (line 369) | fn lex_ident(&mut self) -> Token {
function lex_string (line 391) | fn lex_string(&mut self) -> Token {
function lex_variable (line 415) | fn lex_variable(&mut self) -> Token {
function lex_integer (line 434) | fn lex_integer(&mut self) -> Token {
function lex_atom (line 449) | fn lex_atom(&mut self) -> Token {
type Item (line 482) | type Item = Result<(SourceIndex, Token, SourceIndex), ParserError>;
method next (line 484) | fn next(&mut self) -> Option<Self::Item> {
FILE: libeir_ir/src/text/parser/mod.rs
type Parser (line 20) | pub type Parser = parse::Parser<()>;
type ParserErrorReceiver (line 22) | type ParserErrorReceiver<'a> = dyn ErrorReceiver<E = ParserError, W = Pa...
type NamedFunction (line 51) | pub struct NamedFunction {
type Parser (line 57) | type Parser = self::grammar::ModuleParser;
type Error (line 58) | type Error = ParserError;
type Config (line 59) | type Config = ();
type Token (line 60) | type Token = std::result::Result<(SourceIndex, Token, SourceIndex), Pars...
method root_file_error (line 62) | fn root_file_error(source: std::io::Error, path: std::path::PathBuf) -> ...
method parse_tokens (line 66) | fn parse_tokens<S>(errors: &mut ParserErrorReceiver, tokens: S) -> Resul...
method parse (line 88) | fn parse<S>(_parser: &Parser, errors: &mut ParserErrorReceiver, source: ...
type Parser (line 98) | type Parser = self::grammar::StandaloneFunctionParser;
type Error (line 99) | type Error = ParserError;
type Config (line 100) | type Config = ();
type Token (line 101) | type Token = std::result::Result<(SourceIndex, Token, SourceIndex), Pars...
method root_file_error (line 103) | fn root_file_error(source: std::io::Error, path: std::path::PathBuf) -> ...
method parse_tokens (line 107) | fn parse_tokens<S>(errors: &mut ParserErrorReceiver, tokens: S) -> Resul...
method parse (line 133) | fn parse<'a, S>(
method parse (line 148) | pub fn parse(string: &str) -> std::result::Result<Self, ()> {
method parse_with_module (line 168) | pub fn parse_with_module(string: &str, module: Ident) -> std::result::Re...
function module_codemap (line 189) | pub fn module_codemap(text: &str, codemap: Arc<CodeMap>) -> (Result<crat...
function module (line 213) | pub fn module(text: &str) -> (Result<crate::Module, ()>, Errors) {
function module_unwrap (line 217) | pub fn module_unwrap(text: &str) -> crate::Module {
function function_map_codemap (line 231) | pub fn function_map_codemap(
function function_map (line 258) | pub fn function_map(text: &str) -> (Result<(crate::Function, LowerMap), ...
function function_codemap (line 262) | pub fn function_codemap(
function function (line 272) | pub fn function(text: &str) -> (Result<crate::Function, ()>, Errors) {
function function_unwrap (line 279) | pub fn function_unwrap(text: &str) -> crate::Function {
function function_map_unwrap (line 293) | pub fn function_map_unwrap(text: &str) -> (crate::Function, LowerMap) {
function parse_empty_function (line 323) | fn parse_empty_function() {
function lower_empty_function_fails (line 336) | fn lower_empty_function_fails() {
function parse_kitchen_sink (line 341) | fn parse_kitchen_sink() {
function lower_add_one (line 417) | fn lower_add_one() {
function location (line 430) | fn location() {
FILE: libeir_ir/src/text/printer.old.rs
type EirAnnotator (line 56) | pub trait EirAnnotator {
method annotate_function (line 57) | fn annotate_function(&mut self, out: &mut String, fun: &Function);
method annotate_block (line 58) | fn annotate_block(&mut self, out: &mut String, fun: &Function, block: ...
type ToEirTextContext (line 93) | pub struct ToEirTextContext {
method new (line 99) | pub fn new() -> Self {
method add_annotator (line 102) | pub fn add_annotator<T>(&mut self, ann: T) where T: EirAnnotator + 'st...
method annotate_function (line 105) | pub fn annotate_function(&mut self, fun: &Function) {
method annotate_block (line 110) | pub fn annotate_block(&mut self, fun: &Function, block: Block) -> Opti...
type ToEirText (line 123) | pub trait ToEirText {
method to_eir_text (line 124) | fn to_eir_text(&self, ctx: &mut ToEirTextContext, indent: usize, out: ...
method to_eir_text (line 139) | fn to_eir_text(&self, _ctx: &mut ToEirTextContext, indent: usize, out:...
method to_eir_text (line 172) | fn to_eir_text(&self, ctx: &mut ToEirTextContext, indent: usize, out: ...
method to_eir_text (line 193) | fn to_eir_text(&self, ctx: &mut ToEirTextContext, indent: usize, out: ...
type ToEirTextFun (line 126) | pub trait ToEirTextFun {
method to_eir_text_fun (line 127) | fn to_eir_text_fun(&self, ctx: &mut ToEirTextContext, fun: &Function, ...
method to_eir_text_fun (line 257) | fn to_eir_text_fun(&self, ctx: &mut ToEirTextContext, fun: &Function,
function write_indent (line 131) | fn write_indent(out: &mut dyn Write, indent: usize) -> std::io::Result<(...
function print_constants (line 147) | pub fn print_constants(_ctx: &mut ToEirTextContext, _fun: &Function, _in...
function format_pattern (line 231) | fn format_pattern(_ctx: &mut ToEirTextContext, pat: &PatternContainer, _...
function get_value_list (line 245) | fn get_value_list<'a>(fun: &'a Function, value: Value) -> Option<&'a [Va...
function format_value (line 553) | fn format_value(value: Value, fun: &Function, out: &mut dyn Write) -> st...
function format_value_list (line 564) | fn format_value_list(values: &[Value], fun: &Function,
FILE: libeir_ir/src/text/printer/constant.rs
function constant_to_doc (line 5) | pub fn constant_to_doc<'a>(
type ConstantState (line 14) | enum ConstantState {
function constant_to_doc_state (line 31) | fn constant_to_doc_state<'a>(
function atomic_to_doc (line 123) | fn atomic_to_doc<'a>(arena: &'a Arena<'a>, atomic: &AtomicTerm) -> RefDo...
FILE: libeir_ir/src/text/printer/mod.rs
type DynError (line 20) | type DynError = Box<dyn Error>;
function get_value_list (line 40) | fn get_value_list<'a>(fun: &'a Function, value: Value) -> Option<&'a [Va...
type FormatConfig (line 50) | pub struct FormatConfig<B, V, L>
type StandardFormatConfig (line 70) | pub type StandardFormatConfig =
method default (line 73) | fn default() -> Self {
type FormatState (line 84) | pub struct FormatState<'a> {
type BlockIteratorConfig (line 90) | pub trait BlockIteratorConfig {
method new (line 92) | fn new(&self, fun: &Function) -> Self::Iter;
type Iter (line 103) | type Iter = DfsBlockIterator;
method new (line 104) | fn new(&self, fun: &Function) -> Self::Iter {
type BlockIterator (line 97) | pub trait BlockIterator {
method next (line 98) | fn next(&mut self, fun: &Function) -> Option<Block>;
method next (line 115) | fn next(&mut self, fun: &Function) -> Option<Block> {
type DfsBlockIteratorConfig (line 101) | pub struct DfsBlockIteratorConfig;
type DfsBlockIterator (line 111) | pub struct DfsBlockIterator {
type ValueSite (line 122) | pub enum ValueSite {
type ValueFormatter (line 126) | pub trait ValueFormatter {
method value (line 127) | fn value(&self, out: &mut String, fun: &Function, site: ValueSite, val...
method value (line 134) | fn value(&self, out: &mut String, fun: &Function, _site: ValueSite, va...
type StandardValueFormatter (line 132) | pub struct StandardValueFormatter;
type BlockValueLayout (line 142) | pub trait BlockValueLayout {
method layout_module (line 145) | fn layout_module(&mut self, fun: &Function);
method layout (line 147) | fn layout(&mut self, fun: &Function, block: Block);
method values (line 150) | fn values(&self) -> &[Value];
method should_layout (line 154) | fn should_layout(&self, value: Value, within: Option<Value>) -> bool;
method layout_module (line 170) | fn layout_module(&mut self, fun: &Function) {}
method layout (line 171) | fn layout(&mut self, fun: &Function, block: Block) {
method values (line 195) | fn values(&self) -> &[Value] {
method should_layout (line 199) | fn should_layout(&self, value: Value, within: Option<Value>) -> bool {
type ReferencePrimopBlockValueLayout (line 157) | pub struct ReferencePrimopBlockValueLayout {
method default (line 162) | fn default() -> Self {
type BlockFormatSink (line 204) | pub trait BlockFormatSink {
method write_indent (line 207) | fn write_indent(&mut self, num: usize) -> Result<(), DynError> {
method write_str (line 214) | fn write_str(&mut self, string: &str) -> Result<(), DynError>;
method commit_line (line 215) | fn commit_line(&mut self) -> Result<Self::LineIndex, DynError>;
method block_lines (line 221) | fn block_lines(&mut self, _block: Block, _range: (Self::LineIndex, Sel...
type LineIndex (line 238) | type LineIndex = ();
method write_str (line 239) | fn write_str(&mut self, string: &str) -> Result<(), DynError> {
method commit_line (line 243) | fn commit_line(&mut self) -> Result<(), DynError> {
type StringSink (line 224) | pub struct StringSink {
method new (line 228) | pub fn new() -> Self {
method finalize (line 233) | pub fn finalize(self) -> String {
type FunctionFormatData (line 249) | pub(crate) struct FunctionFormatData<'a, B, V, L>
function block_to_doc (line 266) | pub(crate) fn block_to_doc(
function block_body_to_doc (line 316) | pub(crate) fn block_body_to_doc(
function value_assign_to_doc (line 352) | pub(crate) fn value_assign_to_doc(
function constant (line 448) | fn constant(
function value_use_only (line 457) | fn value_use_only(
function value_use (line 470) | fn value_use(
function format_callee (line 487) | fn format_callee(
function format_function_body_state (line 537) | fn format_function_body_state<B, V, L, S>(
function format_function_body (line 585) | pub fn format_function_body<B, V, L, S>(
function format_module (line 603) | pub fn format_module<B, V, L, S>(
method to_text (line 639) | pub fn to_text<B, V, L>(&self, config: &mut FormatConfig<B, V, L>) -> St...
method to_text_standard (line 650) | pub fn to_text_standard(&self) -> String {
method block_to_text (line 654) | pub fn block_to_text<B, V, L>(&self, block: Block, config: &mut FormatCo...
method to_text (line 684) | pub fn to_text<B, V, L>(&self, config: &mut FormatConfig<B, V, L>) -> St...
method to_text_standard (line 695) | pub fn to_text_standard(&self) -> String {
function woo (line 705) | fn woo() {
FILE: libeir_ir/src/text/printer/operation.rs
type FormatOpCtxImpl (line 13) | pub struct FormatOpCtxImpl<'a, 'b, 'doc, B, V, L>
function arena (line 30) | fn arena(&self) -> &'doc pretty::Arena<'doc> {
function value_use_to_doc (line 34) | fn value_use_to_doc(&mut self, value: DynValue) -> RefDoc<'doc, ()> {
function binary_specifier_to_doc (line 41) | fn binary_specifier_to_doc<'a>(
function block_op_to_doc (line 112) | pub fn block_op_to_doc(
function type_to_text (line 407) | fn type_to_text(ty: &BasicType) -> String {
FILE: libeir_ir/src/traits/op_branches.rs
type OpBranches (line 6) | pub trait OpBranches {
method branches_len (line 10) | fn branches_len(&self) -> usize;
method branch_num (line 14) | fn branch_num(&self, fun: &Function, block: Block, branch_n: usize) ->...
FILE: libeir_ir/src/traits/parser.rs
type OpParser (line 5) | pub trait OpParser: Send + Sync {
method parse (line 6) | fn parse(
FILE: libeir_ir/src/traits/printer.rs
type FormatOpCtx (line 5) | pub trait FormatOpCtx<'doc> {
method arena (line 6) | fn arena(&self) -> &'doc pretty::Arena<'doc>;
method value_use_to_doc (line 7) | fn value_use_to_doc(&mut self, value: DynValue) -> RefDoc<'doc, ()>;
type OpPrinter (line 10) | pub trait OpPrinter {
method to_doc (line 11) | fn to_doc<'doc>(&self, ctx: &mut dyn FormatOpCtx<'doc>, block: Block) ...
FILE: libeir_lowerutils/src/lib.rs
type LowerData (line 13) | pub struct LowerData {
type Escape (line 22) | enum Escape {
function analyze (line 27) | pub fn analyze(fun: &Function) -> LowerData {
FILE: libeir_lowerutils/src/tests.rs
function simple_function (line 4) | fn simple_function() {
function nested_functions (line 23) | fn nested_functions() {
FILE: libeir_passes/src/compile_pattern/erlang_pattern_provider.rs
type ValueOrConst (line 17) | pub enum ValueOrConst {
method from_value (line 24) | fn from_value(val_bind: ValueBind, fun: &Function) -> Self {
type NodeKind (line 38) | pub enum NodeKind {
method num_children (line 68) | pub fn num_children(self) -> usize {
type NodeData (line 84) | pub struct NodeData {
type ErlangPatternProvider (line 90) | pub struct ErlangPatternProvider<'a> {
type Node (line 109) | pub struct Node(u32);
type Var (line 113) | pub struct Var(u32);
function new (line 117) | pub fn new() -> Self {
function add_child (line 144) | pub fn add_child(&mut self, node: Node, kind: NodeKind, pat_node: Patter...
function add_clause (line 154) | pub fn add_clause(&mut self) -> Node {
function wildcard (line 163) | fn wildcard(&self) -> Node {
function pattern_node_to_cfg_node (line 167) | pub fn pattern_node_to_cfg_node(&self, pat: PatternNode) -> Node {
type PatternNodeKey (line 173) | type PatternNodeKey = Node;
type PatternNodeKind (line 174) | type PatternNodeKind = NodeKind;
type CfgVariable (line 175) | type CfgVariable = Var;
constant WILDCARD (line 177) | const WILDCARD: NodeKind = NodeKind::Wildcard;
method get_root (line 179) | fn get_root(&self) -> ExpandedClauseNodes<Var, Node> {
method kind_includes (line 187) | fn kind_includes(&self, kind: NodeKind, key: Node) -> bool {
method get_kind (line 201) | fn get_kind(&self, key: Node) -> NodeKind {
method get_wildcard_node (line 205) | fn get_wildcard_node(&self) -> Node {
method expand_clause_nodes (line 209) | fn expand_clause_nodes(
function pattern_node_to_provider (line 348) | fn pattern_node_to_provider(
function pattern_to_provider (line 467) | pub(super) fn pattern_to_provider<'a>(
FILE: libeir_passes/src/compile_pattern/lower_cfg.rs
type DecisionTreeDestinations (line 14) | pub struct DecisionTreeDestinations<'bump> {
type LowerCtx (line 20) | struct LowerCtx<'a, 'b, 'bump> {
function node_to_value (line 27) | fn node_to_value(
function value_or_const_to_value (line 41) | fn value_or_const_to_value(
function get_var_value (line 56) | fn get_var_value(&self, var: Var) -> Value {
function bind (line 60) | fn bind(&mut self, var: Var, val: Value) {
function lower_cfg (line 65) | pub fn lower_cfg(
function lower_cfg_rec (line 150) | fn lower_cfg_rec(
FILE: libeir_passes/src/compile_pattern/mod.rs
type BFnvHashMap (line 5) | type BFnvHashMap<'bump, K, V> = HashMap<K, V, FnvBuildHasher, &'bump Bump>;
type CompilePatternPass (line 26) | pub struct CompilePatternPass {
method new (line 31) | pub fn new() -> Self {
method compile_pattern (line 48) | pub fn compile_pattern(&mut self, b: &mut FunctionBuilder) {
method name (line 39) | fn name(&self) -> &str {
method run_function_pass (line 42) | fn run_function_pass(&mut self, b: &mut FunctionBuilder) {
type ValueBind (line 176) | pub(super) enum ValueBind {
FILE: libeir_passes/src/lib.rs
type FunctionPass (line 22) | pub trait FunctionPass {
method name (line 23) | fn name(&self) -> &str;
method run_function_pass (line 24) | fn run_function_pass(&mut self, b: &mut FunctionBuilder);
type PassType (line 27) | enum PassType {
type PassManager (line 31) | pub struct PassManager {
method new (line 36) | pub fn new() -> Self {
method push_function_pass (line 40) | pub fn push_function_pass<P>(&mut self, pass: P)
method run (line 47) | pub fn run(&mut self, module: &mut Module) {
method default (line 70) | fn default() -> Self {
FILE: libeir_passes/src/naive_inline_closures/mod.rs
type NaiveInlineClosuresPass (line 13) | pub struct NaiveInlineClosuresPass {
method new (line 19) | pub fn new() -> Self {
method inline_closures (line 37) | pub fn inline_closures(&mut self, b: &mut FunctionBuilder) {
method name (line 28) | fn name(&self) -> &str {
method run_function_pass (line 31) | fn run_function_pass(&mut self, b: &mut FunctionBuilder) {
FILE: libeir_passes/src/naive_inline_closures/tests.rs
function inline_basic_function (line 6) | fn inline_basic_function() {
function inline_nested_functions (line 52) | fn inline_nested_functions() {
FILE: libeir_passes/src/simplify_cfg/analyze/call.rs
function propagate (line 5) | pub(super) fn propagate(ctx: &mut AnalysisContext, block: Block) -> bool {
FILE: libeir_passes/src/simplify_cfg/analyze/if_bool.rs
function propagate (line 5) | pub(super) fn propagate(ctx: &mut AnalysisContext, block: Block) -> bool {
FILE: libeir_passes/src/simplify_cfg/analyze/mod.rs
type BlockEdge (line 20) | type BlockEdge = (Block, Block);
type GraphAnalysis (line 23) | pub struct GraphAnalysis<'bump> {
type TreeData (line 36) | pub struct TreeData<'bump> {
function is_before (line 44) | fn is_before(&self, lhs: Block, rhs: Block) -> bool {
function is_value_relevant (line 60) | fn is_value_relevant(&self, tree_target: Block, value: Value) -> bool {
type ChainAnalysis (line 77) | pub struct ChainAnalysis<'bump> {
type CondValue (line 94) | pub struct CondValue<'bump> {
type PhiSource (line 102) | pub struct PhiSource {
type EntryEdgeAnalysis (line 119) | pub struct EntryEdgeAnalysis<'bump> {
type AnalysisContext (line 134) | struct AnalysisContext<'bump, 'a> {
function init_block (line 147) | fn init_block(&mut self, block: Block) {
function follow (line 152) | pub fn follow(&self, mut val: Value) -> Value {
function set_branch (line 160) | pub fn set_branch(&mut self, target: Value) {
function add_rename (line 164) | pub fn add_rename(&mut self, callee: Block, caller_read: Value, callee_a...
function analyze_graph (line 209) | pub fn analyze_graph<'bump, 'fun>(
type ChainMapping (line 409) | pub struct ChainMapping {
method iter_entries_for (line 414) | pub fn iter_entries_for<'a>(&'a self, block: Block) -> impl Iterator<I...
method entry_to_chain (line 417) | pub fn entry_to_chain(&self, entry: Block) -> Chain {
function build_node (line 422) | pub fn build_node<'bump>(
function analyze_chain (line 566) | pub fn analyze_chain<'bump>(
FILE: libeir_passes/src/simplify_cfg/analyze/unpack_value_list.rs
function propagate (line 5) | pub(super) fn propagate(ctx: &mut AnalysisContext, block: Block, n: usiz...
FILE: libeir_passes/src/simplify_cfg/chain_graph/mod.rs
type ValueRef (line 22) | pub enum ValueRef {
type Node (line 28) | pub struct Node(u32);
method make_id (line 31) | fn make_id(&self, out: &mut String) {
type Chain (line 38) | pub struct Chain(u32);
method make_id (line 41) | fn make_id(&self, out: &mut String) {
type ChainGraph (line 80) | pub struct ChainGraph {
method new (line 115) | pub fn new(target_block: Block) -> Self {
method propagate_alias (line 139) | pub fn propagate_alias(&self, mut node: Node) -> Node {
method get_terminal_value_node (line 149) | pub fn get_terminal_value_node(&self, value: Value) -> Option<Node> {
method get_member_value_node (line 153) | pub fn get_member_value_node(&self, value: Value) -> Option<Node> {
method get_member_or_terminal (line 158) | pub fn get_member_or_terminal(&self, value: Value) -> Option<Node> {
method mark_root (line 172) | pub fn mark_root(&mut self, value: Value, node: Node) {
method get_root (line 179) | pub fn get_root(&self, value: Value) -> Option<Node> {
method get_uniform (line 182) | pub fn get_uniform(&self, value: Value) -> Option<Node> {
method iter_roots (line 186) | pub fn iter_roots<'a>(&'a self) -> impl Iterator<Item = (Value, Node)>...
method iter_uniform_mappings (line 189) | pub fn iter_uniform_mappings<'a>(&'a self) -> impl Iterator<Item = (Va...
method insert_scoped (line 193) | pub fn insert_scoped(&mut self, value: Value) -> Node {
method insert_chain_entry_arg (line 205) | pub fn insert_chain_entry_arg(&mut self, chain: Chain, arg_index: usiz...
method insert_phi (line 227) | pub fn insert_phi(&mut self, tier: usize, value: Value) -> Node {
method phi_add_entry (line 244) | pub fn phi_add_entry(&mut self, node: Node, chain: Chain, dep: Node) {
method insert_prim (line 253) | pub fn insert_prim(&mut self, value: Value) -> Node {
method insert_block_capture (line 268) | pub fn insert_block_capture(&mut self, value: Value, block: Block) -> ...
method add_dep (line 284) | pub fn add_dep(&mut self, node: Node, dep: Node, value: Value) {
method gen_dot (line 296) | pub fn gen_dot(&self, out: &std::path::Path) {
method chain_count (line 358) | pub fn chain_count(&self) -> usize {
method entry_chain (line 362) | pub fn entry_chain(&mut self, arity: usize, blocks: Vec<Block>) -> Cha...
method get_chain_entry_block (line 369) | pub fn get_chain_entry_block(&self, chain: Chain) -> Block {
method node (line 373) | pub fn node(&self, node: Node) -> &NodeKind {
method follow_chain (line 377) | pub fn follow_chain(&self, mut node: Node, chain: Chain) -> Node {
method follow_chain_maybe (line 389) | pub fn follow_chain_maybe(&self, mut node: Node, chain: Chain) -> Opti...
method dfs (line 406) | pub fn dfs(&self, start: Node, order: &mut Vec<Node>) {
method process (line 418) | pub fn process(&mut self) {
method propagate_graph_aliases (line 432) | fn propagate_graph_aliases(&mut self) {
method insert_anon_phi (line 482) | fn insert_anon_phi(&mut self) -> Node {
method remove_uniform (line 494) | pub fn remove_uniform(&mut self) {
method expand_phis (line 529) | pub fn expand_phis(&mut self) {
method reduce_phis2 (line 546) | pub fn reduce_phis2(&mut self) {
method reduce_phis (line 755) | pub fn reduce_phis(&mut self) {
type ChainData (line 105) | pub struct ChainData {
type NodeKind (line 892) | pub enum NodeKind {
method is_phi (line 905) | pub fn is_phi(&self) -> bool {
method is_prim (line 911) | pub fn is_prim(&self) -> bool {
method is_block_capture (line 917) | pub fn is_block_capture(&self) -> bool {
method is_scope (line 923) | pub fn is_scope(&self) -> bool {
method is_entry_arg (line 929) | pub fn is_entry_arg(&self) -> bool {
method is_terminal (line 936) | pub fn is_terminal(&self) -> bool {
method terminal_value (line 943) | pub fn terminal_value(&self) -> Value {
method dependencies (line 951) | pub fn dependencies<'a>(&'a self) -> impl Iterator<Item = Node> + 'a {
type EntryArg (line 992) | pub struct EntryArg {
type Phi (line 1000) | pub struct Phi {
type Prim (line 1008) | pub struct Prim {
type BlockCapture (line 1018) | pub struct BlockCapture {
FILE: libeir_passes/src/simplify_cfg/chain_graph/synthesis/compound.rs
type CompoundStrategy (line 9) | pub struct CompoundStrategy;
method try_run (line 12) | fn try_run(&self, graph: &ChainGraph, fun: &Function, live: &LiveValues)...
FILE: libeir_passes/src/simplify_cfg/chain_graph/synthesis/mod.rs
type Synthesis (line 16) | pub struct Synthesis {
method fmt (line 33) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
method new (line 54) | pub fn new() -> Self {
method create_segment (line 72) | fn create_segment(&mut self, head: SegmentHeadKind) -> Segment {
method create_entry_segment (line 85) | pub fn create_entry_segment(&mut self, chain: Chain, graph: &ChainGrap...
method create_intermediate_segment (line 105) | pub fn create_intermediate_segment(&mut self) -> Segment {
method segment (line 109) | pub fn segment<'a>(&'a mut self, segment: Segment) -> SegmentBuilder<'...
method visit_segment (line 117) | pub fn visit_segment(&mut self, segment: Segment) {
method substitute (line 121) | pub fn substitute(&mut self, chain: Chain, value: Value) {
method postprocess (line 131) | pub fn postprocess(&mut self, graph: &ChainGraph) {
type SegmentBuilder (line 182) | pub struct SegmentBuilder<'a> {
function create_arg_instance (line 188) | fn create_arg_instance(&mut self, node: Node) -> Instance {
function create_creation_instance (line 195) | fn create_creation_instance(&mut self, node: Node) -> Instance {
function push_in_arg (line 202) | pub fn push_in_arg(&mut self, node: Node) -> Instance {
function push_external (line 215) | pub fn push_external(&mut self, instance: Instance) {
function push_instance (line 223) | pub fn push_instance(&mut self, node: Node) -> Instance {
function push_out_arg (line 235) | pub fn push_out_arg(&mut self, instance: Instance) {
function finish_to (line 241) | pub fn finish_to(&mut self, segment: Segment) {
function finish_target (line 250) | pub fn finish_target(&mut self, single: bool) {
type Instance (line 263) | pub struct Instance(u32);
type InstanceKind (line 267) | pub enum InstanceKind {
method is_relevant (line 283) | pub fn is_relevant(&self) -> bool {
method node (line 289) | pub fn node(&self) -> Node {
type Segment (line 300) | pub struct Segment(u32);
type SegmentData (line 309) | pub struct SegmentData {
method aux_fmt (line 338) | fn aux_fmt(&self, f: &mut std::fmt::Formatter<'_>, aux: &Synthesis) ->...
type SegmentHeadKind (line 352) | pub enum SegmentHeadKind {
method is_intermediate (line 374) | pub fn is_intermediate(&self) -> bool {
type SegmentBodyKind (line 383) | pub enum SegmentBodyKind {
method aux_fmt (line 428) | fn aux_fmt(&self, f: &mut std::fmt::Formatter<'_>, aux: &Synthesis) ->...
method is_none (line 447) | pub fn is_none(&self) -> bool {
type SynthesisStrategy (line 455) | pub trait SynthesisStrategy {
method try_run (line 458) | fn try_run(&self, graph: &ChainGraph, fun: &Function, live: &LiveValue...
FILE: libeir_passes/src/simplify_cfg/chain_graph/synthesis/simple.rs
type SimpleStrategy (line 23) | pub struct SimpleStrategy;
method try_run (line 26) | fn try_run(
FILE: libeir_passes/src/simplify_cfg/chain_graph/synthesis/single.rs
function can_subsitute (line 5) | pub fn can_subsitute(graph: &ChainGraph, fun: &Function, chain: Chain) -...
type SingleStrategy (line 45) | pub struct SingleStrategy;
method try_run (line 48) | fn try_run(&self, graph: &ChainGraph, fun: &Function, _live: &LiveValues...
FILE: libeir_passes/src/simplify_cfg/chain_graph/synthesis/terminating_target.rs
type TerminatingTargetStrategy (line 16) | pub struct TerminatingTargetStrategy;
method try_run (line 19) | fn try_run(&self, graph: &ChainGraph, fun: &Function, live: &LiveValues)...
FILE: libeir_passes/src/simplify_cfg/mod.rs
type BFnvHashMap (line 10) | type BFnvHashMap<'bump, K, V> = HashMap<K, V, FnvBuildHasher, &'bump Bump>;
type SimplifyCfgPass (line 29) | pub struct SimplifyCfgPass {
method new (line 97) | pub fn new() -> Self {
method simplify_cfg (line 116) | fn simplify_cfg(&mut self, b: &mut FunctionBuilder) {
method name (line 107) | fn name(&self) -> &str {
method run_function_pass (line 110) | fn run_function_pass(&mut self, b: &mut FunctionBuilder) {
FILE: libeir_passes/src/simplify_cfg/rewrite.rs
function rewrite (line 15) | pub fn rewrite(
FILE: libeir_passes/src/simplify_cfg/tests.rs
function primop_in_chain (line 7) | fn primop_in_chain() {
function double_primop_in_chain (line 44) | fn double_primop_in_chain() {
function split_primop_in_chain (line 82) | fn split_primop_in_chain() {
function two_split_primop_in_chain (line 133) | fn two_split_primop_in_chain() {
function simple_tail_call_elimination (line 184) | fn simple_tail_call_elimination() {
function tail_call_elimination (line 220) | fn tail_call_elimination() {
function recursive_simplification (line 258) | fn recursive_simplification() {
function value_list_removal (line 296) | fn value_list_removal() {
function partial_loop (line 330) | fn partial_loop() {
function tight_partial_loop (line 379) | fn tight_partial_loop() {
function deep_primop_rename_single_branch (line 439) | fn deep_primop_rename_single_branch() {
function deep_primop_rename_after_entry_single_branch (line 481) | fn deep_primop_rename_after_entry_single_branch() {
function converging_from_single (line 541) | fn converging_from_single() {
function basic_locations (line 590) | fn basic_locations() {
function block_capture_with_scope_in_chain (line 697) | fn block_capture_with_scope_in_chain() {
function dynamic_ops (line 727) | fn dynamic_ops() {
function bbbb (line 787) | fn bbbb() {
function cccc (line 942) | fn cccc() {
function terminating_strategy_checks_live_in_outgoing (line 1108) | fn terminating_strategy_checks_live_in_outgoing() {
FILE: libeir_passes/src/util.rs
type EdgeSet (line 4) | pub struct EdgeSet<T: Copy + Ord>(pub BTreeMap<T, T>);
function new (line 6) | pub fn new() -> Self {
function insert (line 9) | pub fn insert(&mut self, key: T, val: T) {
function propagate_edges (line 12) | pub fn propagate_edges(&mut self) {
type Walker (line 32) | pub struct Walker<T> {
function new (line 40) | pub fn new() -> Self {
function with (line 43) | pub fn with(to_walk: Vec<T>) -> Self {
function clear (line 49) | pub fn clear(&mut self) {
function put (line 53) | pub fn put(&mut self, t: T) {
function next (line 58) | pub fn next(&mut self) -> Option<T> {
FILE: libeir_passes/src/validate.rs
type ValidatePass (line 7) | pub struct ValidatePass {
method new (line 12) | pub fn new() -> Self {
method name (line 20) | fn name(&self) -> &str {
method run_function_pass (line 23) | fn run_function_pass(&mut self, b: &mut FunctionBuilder) {
FILE: libeir_syntax_core/build.rs
function main (line 4) | fn main() {
FILE: libeir_syntax_core/src/ast.rs
type MapExactAssoc (line 4) | pub enum MapExactAssoc {
type Annotated (line 10) | pub struct Annotated<I>(pub I, pub Vec<()>);
function empty (line 12) | pub fn empty(inner: I) -> Self {
type Module (line 18) | pub struct Module {
type FunctionName (line 26) | pub struct FunctionName {
type Integer (line 42) | pub struct Integer {
method as_u32 (line 47) | pub fn as_u32(&self) -> u32 {
method as_usize (line 51) | pub fn as_usize(&self) -> usize {
type AtomicLiteral (line 58) | type AtomicLiteral = AtomicTerm;
type Constant (line 79) | pub enum Constant {
type FunctionDefinition (line 107) | pub struct FunctionDefinition {
type SingleExpression (line 113) | pub enum SingleExpression {
type CaseClause (line 147) | pub struct CaseClause {
type Pattern (line 154) | pub enum Pattern {
method nil (line 164) | pub fn nil() -> Annotated<Pattern> {
type Expression (line 169) | pub type Expression = Annotated<Vec<Annotated<SingleExpression>>>;
method nil (line 171) | pub fn nil() -> Self {
type Function (line 178) | pub struct Function {
type PrimOpCall (line 184) | pub struct PrimOpCall {
FILE: libeir_syntax_core/src/lexer.rs
type Tok (line 10) | pub enum Tok<'input> {
constant KEYWORDS (line 68) | const KEYWORDS: &'static [(&'static str, Tok<'static>)] = &[
function is_escapechar (line 89) | fn is_escapechar(c: char) -> bool {
function is_control (line 95) | fn is_control(c: char) -> bool {
function is_inputchar (line 98) | fn is_inputchar(c: char) -> bool {
function is_digit (line 101) | fn is_digit(c: char) -> bool {
function is_octal (line 104) | fn is_octal(c: char) -> bool {
function is_uppercase (line 107) | fn is_uppercase(c: char) -> bool {
function is_lowercase (line 112) | fn is_lowercase(c: char) -> bool {
function is_namechar (line 117) | fn is_namechar(c: char) -> bool {
type Tokenizer (line 122) | pub struct Tokenizer<'input> {
function new (line 130) | pub fn new(text: &'input str) -> Self {
function bump (line 140) | fn bump(&mut self) -> Option<(usize, char)> {
function bump_escape (line 145) | fn bump_escape(&mut self) -> Result<(), ()> {
function take_while (line 178) | fn take_while<F>(&mut self, fun: F) -> &'input str where F: Fn(char) -> ...
function next_token (line 201) | fn next_token(&mut self) -> Option<Result<(usize, Tok<'input>, usize), (...
type Item (line 453) | type Item = Result<(usize, Tok<'input>, usize), ()>;
method next (line 455) | fn next(&mut self) -> Option<Result<(usize, Tok<'input>, usize), ()>> {
function test_symbols (line 461) | fn test_symbols() {
function test_keywords (line 486) | fn test_keywords() {
function test_atoms (line 503) | fn test_atoms() {
function test_variables (line 521) | fn test_variables() {
function test_lex_compile_core_file (line 534) | fn test_lex_compile_core_file() {
FILE: libeir_syntax_core/src/lower_hir.rs
method from_parsed (line 12) | fn from_parsed(module: &::parser::Module) -> Self {
method from_parsed (line 47) | fn from_parsed(fun: &::parser::Function, fun_ident: &FunctionIdent) -> S...
function pat_node_from_parsed (line 55) | fn pat_node_from_parsed(node: &::parser::Pattern,
method from_parsed (line 107) | fn from_parsed(pat: &::parser::Pattern,
method from_parsed_single (line 123) | fn from_parsed_single(expr: &PSE, fun_ident: &FunctionIdent) -> SingleEx...
method from_parsed (line 321) | fn from_parsed(fun: &::parser::Expression, fun_ident: &FunctionIdent) ->...
function from_parsed (line 332) | pub fn from_parsed(parsed: &::parser::Module) -> Module {
FILE: libeir_syntax_core/src/parser/grammar.rs
type __Symbol (line 34) | pub enum __Symbol<'input>
constant __ACTION (line 109) | const __ACTION: &'static [i16] = &[
constant __EOF_ACTION (line 853) | const __EOF_ACTION: &'static [i16] = &[
constant __GOTO (line 1597) | const __GOTO: &'static [i16] = &[
function __expected_tokens (line 2341) | fn __expected_tokens(__state: usize) -> Vec<::std::string::String> {
type __StateMachine (line 2399) | pub struct __StateMachine<'input>
type Location (line 2408) | type Location = usize;
type Error (line 2409) | type Error = ();
type Token (line 2410) | type Token = Tok<'input>;
type TokenIndex (line 2411) | type TokenIndex = usize;
type Symbol (line 2412) | type Symbol = __Symbol<'input>;
type Success (line 2413) | type Success = Annotated<Module>;
type StateIndex (line 2414) | type StateIndex = i16;
type Action (line 2415) | type Action = i16;
type ReduceIndex (line 2416) | type ReduceIndex = i16;
type NonterminalIndex (line 2417) | type NonterminalIndex = usize;
function start_location (line 2420) | fn start_location(&self) -> Self::Location {
function start_state (line 2425) | fn start_state(&self) -> Self::StateIndex {
function token_to_index (line 2430) | fn token_to_index(&self, token: &Self::Token) -> Option<usize> {
function action (line 2435) | fn action(&self, state: i16, integer: usize) -> i16 {
function error_action (line 2440) | fn error_action(&self, state: i16) -> i16 {
function eof_action (line 2445) | fn eof_action(&self, state: i16) -> i16 {
function goto (line 2450) | fn goto(&self, state: i16, nt: usize) -> i16 {
function token_to_symbol (line 2454) | fn token_to_symbol(&self, token_index: usize, token: Self::Token) -> Sel...
function expected_tokens (line 2458) | fn expected_tokens(&self, state: i16) -> Vec<String> {
function uses_error_recovery (line 2463) | fn uses_error_recovery(&self) -> bool {
function error_recovery_symbol (line 2468) | fn error_recovery_symbol(
function reduce (line 2475) | fn reduce(
function simulate_reduce (line 2492) | fn simulate_reduce(&self, action: i16) -> __state_machine::SimulatedRedu...
function __token_to_integer (line 2496) | fn __token_to_integer<
function __token_to_symbol (line 2554) | fn __token_to_symbol<
function __simulate_reduce (line 2754) | fn __simulate_reduce<
type AnnotatedModuleParser (line 4272) | pub struct AnnotatedModuleParser {
method new (line 4277) | pub fn new() -> AnnotatedModuleParser {
method parse (line 4284) | pub fn parse<
function __reduce (line 4306) | pub(crate) fn __reduce<
function __pop_Variant44 (line 5088) | fn __pop_Variant44<
function __pop_Variant32 (line 5099) | fn __pop_Variant32<
function __pop_Variant70 (line 5110) | fn __pop_Variant70<
function __pop_Variant10 (line 5121) | fn __pop_Variant10<
function __pop_Variant27 (line 5132) | fn __pop_Variant27<
function __pop_Variant22 (line 5143) | fn __pop_Variant22<
function __pop_Variant30 (line 5154) | fn __pop_Variant30<
function __pop_Variant8 (line 5165) | fn __pop_Variant8<
function __pop_Variant3 (line 5176) | fn __pop_Variant3<
function __pop_Variant19 (line 5187) | fn __pop_Variant19<
function __pop_Variant12 (line 5198) | fn __pop_Variant12<
function __pop_Variant16 (line 5209) | fn __pop_Variant16<
function __pop_Variant35 (line 5220) | fn __pop_Variant35<
function __pop_Variant37 (line 5231) | fn __pop_Variant37<
function __pop_Variant38 (line 5242) | fn __pop_Variant38<
function __pop_Variant39 (line 5253) | fn __pop_Variant39<
function __pop_Variant4 (line 5264) | fn __pop_Variant4<
function __pop_Variant14 (line 5275) | fn __pop_Variant14<
function __pop_Variant41 (line 5286) | fn __pop_Variant41<
function __pop_Variant45 (line 5297) | fn __pop_Variant45<
function __pop_Variant46 (line 5308) | fn __pop_Variant46<
function __pop_Variant66 (line 5319) | fn __pop_Variant66<
function __pop_Variant49 (line 5330) | fn __pop_Variant49<
function __pop_Variant24 (line 5341) | fn __pop_Variant24<
function __pop_Variant6 (line 5352) | fn __pop_Variant6<
function __pop_Variant62 (line 5363) | fn __pop_Variant62<
function __pop_Variant63 (line 5374) | fn __pop_Variant63<
function __pop_Variant28 (line 5385) | fn __pop_Variant28<
function __pop_Variant61 (line 5396) | fn __pop_Variant61<
function __pop_Variant67 (line 5407) | fn __pop_Variant67<
function __pop_Variant68 (line 5418) | fn __pop_Variant68<
function __pop_Variant71 (line 5429) | fn __pop_Variant71<
function __pop_Variant0 (line 5440) | fn __pop_Variant0<
function __pop_Variant59 (line 5451) | fn __pop_Variant59<
function __pop_Variant50 (line 5462) | fn __pop_Variant50<
function __pop_Variant47 (line 5473) | fn __pop_Variant47<
function __pop_Variant55 (line 5484) | fn __pop_Variant55<
function __pop_Variant51 (line 5495) | fn __pop_Variant51<
function __pop_Variant53 (line 5506) | fn __pop_Variant53<
function __pop_Variant54 (line 5517) | fn __pop_Variant54<
function __pop_Variant52 (line 5528) | fn __pop_Variant52<
function __pop_Variant56 (line 5539) | fn __pop_Variant56<
function __pop_Variant57 (line 5550) | fn __pop_Variant57<
function __pop_Variant58 (line 5561) | fn __pop_Variant58<
function __pop_Variant2 (line 5572) | fn __pop_Variant2<
function __pop_Variant69 (line 5583) | fn __pop_Variant69<
function __pop_Variant21 (line 5594) | fn __pop_Variant21<
function __pop_Variant48 (line 5605) | fn __pop_Variant48<
function __pop_Variant9 (line 5616) | fn __pop_Variant9<
function __pop_Variant43 (line 5627) | fn __pop_Variant43<
function __pop_Variant34 (line 5638) | fn __pop_Variant34<
function __pop_Variant42 (line 5649) | fn __pop_Variant42<
function __pop_Variant5 (line 5660) | fn __pop_Variant5<
function __pop_Variant40 (line 5671) | fn __pop_Variant40<
function __pop_Variant60 (line 5682) | fn __pop_Variant60<
function __pop_Variant7 (line 5693) | fn __pop_Variant7<
function __pop_Variant65 (line 5704) | fn __pop_Variant65<
function __pop_Variant33 (line 5715) | fn __pop_Variant33<
function __pop_Variant11 (line 5726) | fn __pop_Variant11<
function __pop_Variant23 (line 5737) | fn __pop_Variant23<
function __pop_Variant31 (line 5748) | fn __pop_Variant31<
function __pop_Variant20 (line 5759) | fn __pop_Variant20<
function __pop_Variant13 (line 5770) | fn __pop_Variant13<
function __pop_Variant17 (line 5781) | fn __pop_Variant17<
function __pop_Variant36 (line 5792) | fn __pop_Variant36<
function __pop_Variant18 (line 5803) | fn __pop_Variant18<
function __pop_Variant15 (line 5814) | fn __pop_Variant15<
function __pop_Variant25 (line 5825) | fn __pop_Variant25<
function __pop_Variant26 (line 5836) | fn __pop_Variant26<
function __pop_Variant64 (line 5847) | fn __pop_Variant64<
function __pop_Variant29 (line 5858) | fn __pop_Variant29<
function __pop_Variant1 (line 5869) | fn __pop_Variant1<
function __reduce0 (line 5880) | pub(crate) fn __reduce0<
function __reduce1 (line 5900) | pub(crate) fn __reduce1<
function __reduce2 (line 5920) | pub(crate) fn __reduce2<
function __reduce3 (line 5938) | pub(crate) fn __reduce3<
function __reduce4 (line 5958) | pub(crate) fn __reduce4<
function __reduce5 (line 5978) | pub(crate) fn __reduce5<
function __reduce6 (line 5996) | pub(crate) fn __reduce6<
function __reduce7 (line 6016) | pub(crate) fn __reduce7<
function __reduce8 (line 6036) | pub(crate) fn __reduce8<
function __reduce9 (line 6054) | pub(crate) fn __reduce9<
function __reduce10 (line 6076) | pub(crate) fn __reduce10<
function __reduce11 (line 6094) | pub(crate) fn __reduce11<
function __reduce12 (line 6113) | pub(crate) fn __reduce12<
function __reduce13 (line 6135) | pub(crate) fn __reduce13<
function __reduce14 (line 6158) | pub(crate) fn __reduce14<
function __reduce15 (line 6178) | pub(crate) fn __reduce15<
function __reduce16 (line 6196) | pub(crate) fn __reduce16<
function __reduce17 (line 6215) | pub(crate) fn __reduce17<
function __reduce18 (line 6235) | pub(crate) fn __reduce18<
function __reduce19 (line 6256) | pub(crate) fn __reduce19<
function __reduce20 (line 6276) | pub(crate) fn __reduce20<
function __reduce21 (line 6294) | pub(crate) fn __reduce21<
function __reduce22 (line 6313) | pub(crate) fn __reduce22<
function __reduce23 (line 6333) | pub(crate) fn __reduce23<
function __reduce24 (line 6354) | pub(crate) fn __reduce24<
function __reduce25 (line 6374) | pub(crate) fn __reduce25<
function __reduce26 (line 6392) | pub(crate) fn __reduce26<
function __reduce27 (line 6411) | pub(crate) fn __reduce27<
function __reduce28 (line 6431) | pub(crate) fn __reduce28<
function __reduce29 (line 6452) | pub(crate) fn __reduce29<
function __reduce30 (line 6472) | pub(crate) fn __reduce30<
function __reduce31 (line 6490) | pub(crate) fn __reduce31<
function __reduce32 (line 6509) | pub(crate) fn __reduce32<
function __reduce33 (line 6529) | pub(crate) fn __reduce33<
function __reduce34 (line 6550) | pub(crate) fn __reduce34<
function __reduce35 (line 6570) | pub(crate) fn __reduce35<
function __reduce36 (line 6588) | pub(crate) fn __reduce36<
function __reduce37 (line 6607) | pub(crate) fn __reduce37<
function __reduce38 (line 6627) | pub(crate) fn __reduce38<
function __reduce39 (line 6648) | pub(crate) fn __reduce39<
function __reduce40 (line 6669) | pub(crate) fn __reduce40<
function __reduce41 (line 6690) | pub(crate) fn __reduce41<
function __reduce42 (line 6708) | pub(crate) fn __reduce42<
function __reduce43 (line 6728) | pub(crate) fn __reduce43<
function __reduce44 (line 6746) | pub(crate) fn __reduce44<
function __reduce45 (line 6765) | pub(crate) fn __reduce45<
function __reduce46 (line 6785) | pub(crate) fn __reduce46<
function __reduce47 (line 6806) | pub(crate) fn __reduce47<
function __reduce48 (line 6826) | pub(crate) fn __reduce48<
function __reduce49 (line 6844) | pub(crate) fn __reduce49<
function __reduce50 (line 6863) | pub(crate) fn __reduce50<
function __reduce51 (line 6883) | pub(crate) fn __reduce51<
function __reduce52 (line 6904) | pub(crate) fn __reduce52<
function __reduce53 (line 6924) | pub(crate) fn __reduce53<
function __reduce54 (line 6942) | pub(crate) fn __reduce54<
function __reduce55 (line 6961) | pub(crate) fn __reduce55<
function __reduce56 (line 6981) | pub(crate) fn __reduce56<
function __reduce57 (line 7002) | pub(crate) fn __reduce57<
function __reduce58 (line 7023) | pub(crate) fn __reduce58<
function __reduce59 (line 7043) | pub(crate) fn __reduce59<
function __reduce60 (line 7061) | pub(crate) fn __reduce60<
function __reduce61 (line 7080) | pub(crate) fn __reduce61<
function __reduce62 (line 7100) | pub(crate) fn __reduce62<
function __reduce63 (line 7121) | pub(crate) fn __reduce63<
function __reduce64 (line 7142) | pub(crate) fn __reduce64<
function __reduce65 (line 7163) | pub(crate) fn __reduce65<
function __reduce66 (line 7185) | pub(crate) fn __reduce66<
function __reduce67 (line 7205) | pub(crate) fn __reduce67<
function __reduce68 (line 7223) | pub(crate) fn __reduce68<
function __reduce69 (line 7242) | pub(crate) fn __reduce69<
function __reduce70 (line 7262) | pub(crate) fn __reduce70<
function __reduce71 (line 7283) | pub(crate) fn __reduce71<
function __reduce72 (line 7304) | pub(crate) fn __reduce72<
function __reduce73 (line 7328) | pub(crate) fn __reduce73<
function __reduce74 (line 7347) | pub(crate) fn __reduce74<
function __reduce75 (line 7365) | pub(crate) fn __reduce75<
function __reduce76 (line 7384) | pub(crate) fn __reduce76<
function __reduce77 (line 7406) | pub(crate) fn __reduce77<
function __reduce78 (line 7425) | pub(crate) fn __reduce78<
function __reduce79 (line 7447) | pub(crate) fn __reduce79<
function __reduce80 (line 7465) | pub(crate) fn __reduce80<
function __reduce81 (line 7484) | pub(crate) fn __reduce81<
function __reduce82 (line 7503) | pub(crate) fn __reduce82<
function __reduce83 (line 7523) | pub(crate) fn __reduce83<
function __reduce84 (line 7542) | pub(crate) fn __reduce84<
function __reduce85 (line 7564) | pub(crate) fn __reduce85<
function __reduce86 (line 7583) | pub(crate) fn __reduce86<
function __reduce87 (line 7605) | pub(crate) fn __reduce87<
function __reduce88 (line 7624) | pub(crate) fn __reduce88<
function __reduce89 (line 7646) | pub(crate) fn __reduce89<
function __reduce90 (line 7667) | pub(crate) fn __reduce90<
function __reduce91 (line 7686) | pub(crate) fn __reduce91<
function __reduce92 (line 7705) | pub(crate) fn __reduce92<
function __reduce93 (line 7724) | pub(crate) fn __reduce93<
function __reduce94 (line 7745) | pub(crate) fn __reduce94<
function __reduce95 (line 7766) | pub(crate) fn __reduce95<
function __reduce96 (line 7789) | pub(crate) fn __reduce96<
function __reduce97 (line 7810) | pub(crate) fn __reduce97<
function __reduce98 (line 7834) | pub(crate) fn __reduce98<
function __reduce99 (line 7856) | pub(crate) fn __reduce99<
function __reduce100 (line 7878) | pub(crate) fn __reduce100<
function __reduce101 (line 7900) | pub(crate) fn __reduce101<
function __reduce102 (line 7924) | pub(crate) fn __reduce102<
function __reduce103 (line 7948) | pub(crate) fn __reduce103<
function __reduce104 (line 7974) | pub(crate) fn __reduce104<
function __reduce105 (line 7998) | pub(crate) fn __reduce105<
function __reduce106 (line 8017) | pub(crate) fn __reduce106<
function __reduce107 (line 8039) | pub(crate) fn __reduce107<
function __reduce108 (line 8058) | pub(crate) fn __reduce108<
function __reduce109 (line 8080) | pub(crate) fn __reduce109<
function __reduce110 (line 8099) | pub(crate) fn __reduce110<
function __reduce111 (line 8117) | pub(crate) fn __reduce111<
function __reduce112 (line 8136) | pub(crate) fn __reduce112<
function __reduce113 (line 8158) | pub(crate) fn __reduce113<
function __reduce114 (line 8177) | pub(crate) fn __reduce114<
function __reduce115 (line 8199) | pub(crate) fn __reduce115<
function __reduce116 (line 8218) | pub(crate) fn __reduce116<
function __reduce117 (line 8236) | pub(crate) fn __reduce117<
function __reduce118 (line 8255) | pub(crate) fn __reduce118<
function __reduce119 (line 8274) | pub(crate) fn __reduce119<
function __reduce120 (line 8293) | pub(crate) fn __reduce120<
function __reduce121 (line 8311) | pub(crate) fn __reduce121<
function __reduce122 (line 8330) | pub(crate) fn __reduce122<
function __reduce123 (line 8349) | pub(crate) fn __reduce123<
function __reduce124 (line 8367) | pub(crate) fn __reduce124<
function __reduce125 (line 8389) | pub(crate) fn __reduce125<
function __reduce126 (line 8408) | pub(crate) fn __reduce126<
function __reduce127 (line 8427) | pub(crate) fn __reduce127<
function __reduce128 (line 8446) | pub(crate) fn __reduce128<
function __reduce129 (line 8465) | pub(crate) fn __reduce129<
function __reduce130 (line 8484) | pub(crate) fn __reduce130<
function __reduce131 (line 8505) | pub(crate) fn __reduce131<
function __reduce132 (line 8528) | pub(crate) fn __reduce132<
function __reduce133 (line 8547) | pub(crate) fn __reduce133<
function __reduce134 (line 8565) | pub(crate) fn __reduce134<
function __reduce135 (line 8587) | pub(crate) fn __reduce135<
function __reduce136 (line 8608) | pub(crate) fn __reduce136<
function __reduce137 (line 8626) | pub(crate) fn __reduce137<
function __reduce138 (line 8648) | pub(crate) fn __reduce138<
function __reduce139 (line 8667) | pub(crate) fn __reduce139<
function __reduce140 (line 8686) | pub(crate) fn __reduce140<
function __reduce141 (line 8704) | pub(crate) fn __reduce141<
function __reduce142 (line 8724) | pub(crate) fn __reduce142<
function __reduce143 (line 8743) | pub(crate) fn __reduce143<
function __reduce144 (line 8762) | pub(crate) fn __reduce144<
function __reduce145 (line 8780) | pub(crate) fn __reduce145<
function __reduce146 (line 8800) | pub(crate) fn __reduce146<
function __reduce147 (line 8819) | pub(crate) fn __reduce147<
function __reduce148 (line 8838) | pub(crate) fn __reduce148<
function __reduce149 (line 8856) | pub(crate) fn __reduce149<
function __reduce150 (line 8876) | pub(crate) fn __reduce150<
function __reduce151 (line 8895) | pub(crate) fn __reduce151<
function __reduce152 (line 8914) | pub(crate) fn __reduce152<
function __reduce153 (line 8932) | pub(crate) fn __reduce153<
function __reduce154 (line 8952) | pub(crate) fn __reduce154<
function __reduce155 (line 8971) | pub(crate) fn __reduce155<
function __reduce156 (line 8990) | pub(crate) fn __reduce156<
function __reduce157 (line 9008) | pub(crate) fn __reduce157<
function __reduce158 (line 9028) | pub(crate) fn __reduce158<
function __reduce159 (line 9047) | pub(crate) fn __reduce159<
function __reduce160 (line 9066) | pub(crate) fn __reduce160<
function __reduce161 (line 9084) | pub(crate) fn __reduce161<
function __reduce162 (line 9104) | pub(crate) fn __reduce162<
function __reduce163 (line 9123) | pub(crate) fn __reduce163<
function __reduce164 (line 9142) | pub(crate) fn __reduce164<
function __reduce165 (line 9160) | pub(crate) fn __reduce165<
function __reduce166 (line 9180) | pub(crate) fn __reduce166<
function __reduce167 (line 9199) | pub(crate) fn __reduce167<
function __reduce168 (line 9218) | pub(crate) fn __reduce168<
function __reduce169 (line 9236) | pub(crate) fn __reduce169<
function __reduce170 (line 9256) | pub(crate) fn __reduce170<
function __reduce171 (line 9275) | pub(crate) fn __reduce171<
function __reduce172 (line 9294) | pub(crate) fn __reduce172<
function __reduce173 (line 9312) | pub(crate) fn __reduce173<
function __reduce174 (line 9332) | pub(crate) fn __reduce174<
function __reduce175 (line 9351) | pub(crate) fn __reduce175<
function __reduce176 (line 9370) | pub(crate) fn __reduce176<
function __reduce177 (line 9388) | pub(crate) fn __reduce177<
function __reduce178 (line 9408) | pub(crate) fn __reduce178<
function __reduce179 (line 9427) | pub(crate) fn __reduce179<
function __reduce180 (line 9448) | pub(crate) fn __reduce180<
function __reduce181 (line 9471) | pub(crate) fn __reduce181<
function __reduce182 (line 9492) | pub(crate) fn __reduce182<
function __reduce183 (line 9511) | pub(crate) fn __reduce183<
function __reduce184 (line 9530) | pub(crate) fn __reduce184<
function __reduce185 (line 9548) | pub(crate) fn __reduce185<
function __reduce186 (line 9571) | pub(crate) fn __reduce186<
function __reduce187 (line 9592) | pub(crate) fn __reduce187<
function __reduce188 (line 9613) | pub(crate) fn __reduce188<
function __reduce189 (line 9632) | pub(crate) fn __reduce189<
function __reduce190 (line 9651) | pub(crate) fn __reduce190<
function __reduce191 (line 9670) | pub(crate) fn __reduce191<
function __reduce192 (line 9689) | pub(crate) fn __reduce192<
function __reduce193 (line 9708) | pub(crate) fn __reduce193<
function __reduce194 (line 9726) | pub(crate) fn __reduce194<
function __reduce195 (line 9750) | pub(crate) fn __reduce195<
function __reduce196 (line 9771) | pub(crate) fn __reduce196<
function __reduce197 (line 9789) | pub(crate) fn __reduce197<
function __reduce198 (line 9808) | pub(crate) fn __reduce198<
function __reduce199 (line 9827) | pub(crate) fn __reduce199<
function __reduce200 (line 9847) | pub(crate) fn __reduce200<
function __reduce201 (line 9868) | pub(crate) fn __reduce201<
function __reduce202 (line 9887) | pub(crate) fn __reduce202<
function __reduce203 (line 9905) | pub(crate) fn __reduce203<
function __reduce204 (line 9925) | pub(crate) fn __reduce204<
function __reduce205 (line 9944) | pub(crate) fn __reduce205<
function __reduce206 (line 9968) | pub(crate) fn __reduce206<
function __reduce207 (line 9993) | pub(crate) fn __reduce207<
function __reduce208 (line 10014) | pub(crate) fn __reduce208<
function __reduce209 (line 10035) | pub(crate) fn __reduce209<
function __reduce210 (line 10056) | pub(crate) fn __reduce210<
function __reduce211 (line 10075) | pub(crate) fn __reduce211<
function __reduce212 (line 10094) | pub(crate) fn __reduce212<
function __reduce213 (line 10113) | pub(crate) fn __reduce213<
function __reduce214 (line 10134) | pub(crate) fn __reduce214<
function __reduce215 (line 10155) | pub(crate) fn __reduce215<
function __reduce216 (line 10178) | pub(crate) fn __reduce216<
function __reduce217 (line 10199) | pub(crate) fn __reduce217<
function __reduce218 (line 10220) | pub(crate) fn __reduce218<
function __reduce219 (line 10243) | pub(crate) fn __reduce219<
function __reduce220 (line 10262) | pub(crate) fn __reduce220<
function __reduce221 (line 10280) | pub(crate) fn __reduce221<
function __reduce222 (line 10301) | pub(crate) fn __reduce222<
function __reduce223 (line 10320) | pub(crate) fn __reduce223<
function __reduce224 (line 10341) | pub(crate) fn __reduce224<
function __reduce225 (line 10364) | pub(crate) fn __reduce225<
function __reduce226 (line 10385) | pub(crate) fn __reduce226<
function __reduce227 (line 10404) | pub(crate) fn __reduce227<
function __reduce228 (line 10426) | pub(crate) fn __reduce228<
function __reduce229 (line 10445) | pub(crate) fn __reduce229<
function __reduce230 (line 10464) | pub(crate) fn __reduce230<
function __reduce231 (line 10483) | pub(crate) fn __reduce231<
function __reduce232 (line 10504) | pub(crate) fn __reduce232<
function __reduce233 (line 10527) | pub(crate) fn __reduce233<
function __reduce234 (line 10548) | pub(crate) fn __reduce234<
function __reduce235 (line 10572) | pub(crate) fn __reduce235<
function __reduce236 (line 10597) | pub(crate) fn __reduce236<
function __reduce237 (line 10617) | pub(crate) fn __reduce237<
function __reduce238 (line 10639) | pub(crate) fn __reduce238<
function __reduce239 (line 10662) | pub(crate) fn __reduce239<
function __reduce240 (line 10685) | pub(crate) fn __reduce240<
function __reduce241 (line 10706) | pub(crate) fn __reduce241<
function __reduce242 (line 10729) | pub(crate) fn __reduce242<
function __reduce243 (line 10757) | pub(crate) fn __reduce243<
function __reduce244 (line 10780) | pub(crate) fn __reduce244<
function __reduce245 (line 10804) | pub(crate) fn __reduce245<
function __reduce246 (line 10823) | pub(crate) fn __reduce246<
function __reduce247 (line 10845) | pub(crate) fn __reduce247<
function __reduce248 (line 10866) | pub(crate) fn __reduce248<
function __reduce249 (line 10885) | pub(crate) fn __reduce249<
function __reduce250 (line 10904) | pub(crate) fn __reduce250<
function __action0 (line 10929) | fn __action0<
function __action1 (line 10940) | fn __action1<
function __action2 (line 10957) | fn __action2<
function __action3 (line 10968) | fn __action3<
function __action4 (line 10979) | fn __action4<
function __action5 (line 10990) | fn __action5<
function __action6 (line 11012) | fn __action6<
function __action7 (line 11025) | fn __action7<
function __action8 (line 11038) | fn __action8<
function __action9 (line 11051) | fn __action9<
function __action10 (line 11064) | fn __action10<
function __action11 (line 11080) | fn __action11<
function __action12 (line 11091) | fn __action12<
function __action13 (line 11102) | fn __action13<
function __action14 (line 11113) | fn __action14<
function __action15 (line 11124) | fn __action15<
function __action16 (line 11137) | fn __action16<
function __action17 (line 11151) | fn __action17<
function __action18 (line 11162) | fn __action18<
function __action19 (line 11176) | fn __action19<
function __action20 (line 11187) | fn __action20<
function __action21 (line 11198) | fn __action21<
function __action22 (line 11209) | fn __action22<
function __action23 (line 11222) | fn __action23<
function __action24 (line 11236) | fn __action24<
function __action25 (line 11252) | fn __action25<
function __action26 (line 11270) | fn __action26<
function __action27 (line 11282) | fn __action27<
function __action28 (line 11297) | fn __action28<
function __action29 (line 11312) | fn __action29<
function __action30 (line 11325) | fn __action30<
function __action31 (line 11340) | fn __action31<
function __action32 (line 11361) | fn __action32<
function __action33 (line 11378) | fn __action33<
function __action34 (line 11389) | fn __action34<
function __action35 (line 11403) | fn __action35<
function __action36 (line 11417) | fn __action36<
function __action37 (line 11429) | fn __action37<
function __action38 (line 11440) | fn __action38<
function __action39 (line 11453) | fn __action39<
function __action40 (line 11464) | fn __action40<
function __action41 (line 11477) | fn __action41<
function __action42 (line 11488) | fn __action42<
function __action43 (line 11501) | fn __action43<
function __action44 (line 11512) | fn __action44<
function __action45 (line 11525) | fn __action45<
function __action46 (line 11536) | fn __action46<
function __action47 (line 11547) | fn __action47<
function __action48 (line 11558) | fn __action48<
function __action49 (line 11571) | fn __action49<
function __action50 (line 11584) | fn __action50<
function __action51 (line 11598) | fn __action51<
function __action52 (line 11611) | fn __action52<
function __action53 (line 11626) | fn __action53<
function __action54 (line 11639) | fn __action54<
function __action55 (line 11654) | fn __action55<
function __action56 (line 11667) | fn __action56<
function __action57 (line 11681) | fn __action57<
function __action58 (line 11692) | fn __action58<
function __action59 (line 11703) | fn __action59<
function __action60 (line 11714) | fn __action60<
function __action61 (line 11725) | fn __action61<
function __action62 (line 11736) | fn __action62<
function __action63 (line 11749) | fn __action63<
function __action64 (line 11763) | fn __action64<
function __action65 (line 11777) | fn __action65<
function __action66 (line 11788) | fn __action66<
function __action67 (line 11800) | fn __action67<
function __action68 (line 11812) | fn __action68<
function __action69 (line 11828) | fn __action69<
function __action70 (line 11844) | fn __action70<
function __action71 (line 11860) | fn __action71<
function __action72 (line 11871) | fn __action72<
function __action73 (line 11883) | fn __action73<
function __action74 (line 11895) | fn __action74<
function __action75 (line 11911) | fn __action75<
function __action76 (line 11922) | fn __action76<
function __action77 (line 11936) | fn __action77<
function __action78 (line 11947) | fn __action78<
function __action79 (line 11961) | fn __action79<
function __action80 (line 11977) | fn __action80<
function __action81 (line 11988) | fn __action81<
function __action82 (line 12000) | fn __action82<
function __action83 (line 12013) | fn __action83<
function __action84 (line 12024) | fn __action84<
function __action85 (line 12038) | fn __action85<
function __action86 (line 12050) | fn __action86<
function __action87 (line 12061) | fn __action87<
function __action88 (line 12072) | fn __action88<
function __action89 (line 12086) | fn __action89<
function __action90 (line 12102) | fn __action90<
function __action91 (line 12113) | fn __action91<
function __action92 (line 12127) | fn __action92<
function __action93 (line 12140) | fn __action93<
function __action94 (line 12151) | fn __action94<
function __action95 (line 12163) | fn __action95<
function __action96 (line 12175) | fn __action96<
function __action97 (line 12191) | fn __action97<
function __action98 (line 12207) | fn __action98<
function __action99 (line 12218) | fn __action99<
function __action100 (line 12232) | fn __action100<
function __action101 (line 12243) | fn __action101<
function __action102 (line 12257) | fn __action102<
function __action103 (line 12273) | fn __action103<
function __action104 (line 12284) | fn __action104<
function __action105 (line 12298) | fn __action105<
function __action106 (line 12309) | fn __action106<
function __action107 (line 12323) | fn __action107<
function __action108 (line 12334) | fn __action108<
function __action109 (line 12348) | fn __action109<
function __action110 (line 12364) | fn __action110<
function __action111 (line 12377) | fn __action111<
function __action112 (line 12393) | fn __action112<
function __action113 (line 12405) | fn __action113<
function __action114 (line 12416) | fn __action114<
function __action115 (line 12427) | fn __action115<
function __action116 (line 12441) | fn __action116<
function __action117 (line 12452) | fn __action117<
function __action118 (line 12464) | fn __action118<
function __action119 (line 12475) | fn __action119<
function __action120 (line 12487) | fn __action120<
function __action121 (line 12499) | fn __action121<
function __action122 (line 12510) | fn __action122<
function __action123 (line 12522) | fn __action123<
function __action124 (line 12533) | fn __action124<
function __action125 (line 12545) | fn __action125<
function __action126 (line 12557) | fn __action126<
function __action127 (line 12568) | fn __action127<
function __action128 (line 12580) | fn __action128<
function __action129 (line 12591) | fn __action129<
function __action130 (line 12603) | fn __action130<
function __action131 (line 12615) | fn __action131<
function __action132 (line 12626) | fn __action132<
function __action133 (line 12638) | fn __action133<
function __action134 (line 12649) | fn __action134<
function __action135 (line 12661) | fn __action135<
function __action136 (line 12673) | fn __action136<
function __action137 (line 12684) | fn __action137<
function __action138 (line 12696) | fn __action138<
function __action139 (line 12707) | fn __action139<
function __action140 (line 12719) | fn __action140<
function __action141 (line 12731) | fn __action141<
function __action142 (line 12742) | fn __action142<
function __action143 (line 12754) | fn __action143<
function __action144 (line 12765) | fn __action144<
function __action145 (line 12777) | fn __action145<
function __action146 (line 12789) | fn __action146<
function __action147 (line 12800) | fn __action147<
function __action148 (line 12812) | fn __action148<
function __action149 (line 12823) | fn __action149<
function __action150 (line 12835) | fn __action150<
function __action151 (line 12846) | fn __action151<
function __action152 (line 12858) | fn __action152<
function __action153 (line 12870) | fn __action153<
function __action154 (line 12881) | fn __action154<
function __action155 (line 12893) | fn __action155<
function __action156 (line 12904) | fn __action156<
function __action157 (line 12916) | fn __action157<
function __action158 (line 12928) | fn __action158<
function __action159 (line 12939) | fn __action159<
function __action160 (line 12951) | fn __action160<
function __action161 (line 12962) | fn __action161<
function __action162 (line 12974) | fn __action162<
function __action163 (line 12986) | fn __action163<
function __action164 (line 12997) | fn __action164<
function __action165 (line 13009) | fn __action165<
function __action166 (line 13020) | fn __action166<
function __action167 (line 13032) | fn __action167<
function __action168 (line 13044) | fn __action168<
function __action169 (line 13055) | fn __action169<
function __action170 (line 13067) | fn __action170<
function __action171 (line 13078) | fn __action171<
function __action172 (line 13090) | fn __action172<
function __action173 (line 13102) | fn __action173<
function __action174 (line 13113) | fn __action174<
function __action175 (line 13125) | fn __action175<
function __action176 (line 13136) | fn __action176<
function __action177 (line 13148) | fn __action177<
function __action178 (line 13159) | fn __action178<
function __action179 (line 13171) | fn __action179<
function __action180 (line 13182) | fn __action180<
function __action181 (line 13194) | fn __action181<
function __action182 (line 13205) | fn __action182<
function __action183 (line 13217) | fn __action183<
function __action184 (line 13228) | fn __action184<
function __action185 (line 13240) | fn __action185<
function __action186 (line 13251) | fn __action186<
function __action187 (line 13263) | fn __action187<
function __action188 (line 13274) | fn __action188<
function __action189 (line 13286) | fn __action189<
function __action190 (line 13297) | fn __action190<
function __action191 (line 13309) | fn __action191<
function __action192 (line 13320) | fn __action192<
function __action193 (line 13332) | fn __action193<
function __action194 (line 13343) | fn __action194<
function __action195 (line 13355) | fn __action195<
function __action196 (line 13366) | fn __action196<
function __action197 (line 13378) | fn __action197<
function __action198 (line 13401) | fn __action198<
function __action199 (line 13430) | fn __action199<
function __action200 (line 13457) | fn __action200<
function __action201 (line 13480) | fn __action201<
function __action202 (line 13509) | fn __action202<
function __action203 (line 13536) | fn __action203<
function __action204 (line 13565) | fn __action204<
function __action205 (line 13592) | fn __action205<
function __action206 (line 13615) | fn __action206<
function __action207 (line 13644) | fn __action207<
function __action208 (line 13671) | fn __action208<
function __action209 (line 13700) | fn __action209<
function __action210 (line 13727) | fn __action210<
function __action211 (line 13754) | fn __action211<
function __action212 (line 13779) | fn __action212<
function __action213 (line 13806) | fn __action213<
function __action214 (line 13835) | fn __action214<
function __action215 (line 13858) | fn __action215<
function __action216 (line 13881) | fn __action216<
function __action217 (line 13904) | fn __action217<
function __action218 (line 13929) | fn __action218<
function __action219 (line 13952) | fn __action219<
function __action220 (line 13975) | fn __action220<
function __action221 (line 13998) | fn __action221<
function __action222 (line 14023) | fn __action222<
function __action223 (line 14046) | fn __action223<
function __action224 (line 14069) | fn __action224<
function __action225 (line 14092) | fn __action225<
function __action226 (line 14117) | fn __action226<
function __action227 (line 14140) | fn __action227<
function __action228 (line 14163) | fn __action228<
function __action229 (line 14186) | fn __action229<
function __action230 (line 14211) | fn __action230<
function __action231 (line 14234) | fn __action231<
function __action232 (line 14257) | fn __action232<
function __action233 (line 14280) | fn __action233<
function __action234 (line 14305) | fn __action234<
function __action235 (line 14328) | fn __action235<
function __action236 (line 14351) | fn __action236<
function __action237 (line 14376) | fn __action237<
function __action238 (line 14399) | fn __action238<
function __action239 (line 14426) | fn __action239<
function __action240 (line 14449) | fn __action240<
function __action241 (line 14472) | fn __action241<
function __action242 (line 14497) | fn __action242<
function __action243 (line 14520) | fn __action243<
function __action244 (line 14543) | fn __action244<
function __action245 (line 14566) | fn __action245<
function __action246 (line 14591) | fn __action246<
function __action247 (line 14614) | fn __action247<
function __action248 (line 14637) | fn __action248<
function __action249 (line 14660) | fn __action249<
function __action250 (line 14685) | fn __action250<
function __action251 (line 14708) | fn __action251<
function __action252 (line 14731) | fn __action252<
function __action253 (line 14756) | fn __action253<
function __action254 (line 14787) | fn __action254<
function __action255 (line 14810) | fn __action255<
function __action256 (line 14835) | fn __action256<
function __action257 (line 14858) | fn __action257<
function __action258 (line 14881) | fn __action258<
function __action259 (line 14906) | fn __action259<
function __action260 (line 14933) | fn __action260<
function __action261 (line 14956) | fn __action261<
function __action262 (line 14981) | fn __action262<
function __action263 (line 15004) | fn __action263<
function __action264 (line 15027) | fn __action264<
function __action265 (line 15048) | fn __action265<
function __action266 (line 15071) | fn __action266<
function __action267 (line 15094) | fn __action267<
function __action268 (line 15117) | fn __action268<
function __action269 (line 15146) | fn __action269<
function __action270 (line 15175) | fn __action270<
function __action271 (line 15206) | fn __action271<
function __action272 (line 15237) | fn __action272<
function __action273 (line 15258) | fn __action273<
function __action274 (line 15281) | fn __action274<
function __action275 (line 15304) | fn __action275<
function __action276 (line 15327) | fn __action276<
function __action277 (line 15348) | fn __action277<
function __action278 (line 15371) | fn __action278<
function __action279 (line 15394) | fn __action279<
function __action280 (line 15417) | fn __action280<
function __action281 (line 15438) | fn __action281<
function __action282 (line 15461) | fn __action282<
function __action283 (line 15484) | fn __action283<
function __action284 (line 15507) | fn __action284<
function __action285 (line 15528) | fn __action285<
function __action286 (line 15551) | fn __action286<
function __action287 (line 15574) | fn __action287<
function __action288 (line 15597) | fn __action288<
function __action289 (line 15618) | fn __action289<
function __action290 (line 15641) | fn __action290<
function __action291 (line 15664) | fn __action291<
function __action292 (line 15687) | fn __action292<
function __action293 (line 15708) | fn __action293<
function __action294 (line 15731) | fn __action294<
function __action295 (line 15754) | fn __action295<
function __action296 (line 15777) | fn __action296<
function __action297 (line 15798) | fn __action297<
function __action298 (line 15821) | fn __action298<
function __action299 (line 15844) | fn __action299<
function __action300 (line 15867) | fn __action300<
function __action301 (line 15900) | fn __action301<
function __action302 (line 15933) | fn __action302<
function __action303 (line 15954) | fn __action303<
function __action304 (line 15977) | fn __action304<
function __action305 (line 16000) | fn __action305<
function __action306 (line 16023) | fn __action306<
function __action307 (line 16048) | fn __action307<
function __action308 (line 16069) | fn __action308<
function __action309 (line 16090) | fn __action309<
function __action310 (line 16111) | fn __action310<
function __action311 (line 16136) | fn __action311<
function __action312 (line 16161) | fn __action312<
function __action313 (line 16190) | fn __action313<
function __action314 (line 16215) | fn __action314<
function __action315 (line 16246) | fn __action315<
function __action316 (line 16273) | fn __action316<
function __action317 (line 16300) | fn __action317<
function __action318 (line 16327) | fn __action318<
function __action319 (line 16358) | fn __action319<
function __action320 (line 16389) | fn __action320<
function __action321 (line 16424) | fn __action321<
function __action322 (line 16455) | fn __action322<
function __action323 (line 16476) | fn __action323<
function __action324 (line 16499) | fn __action324<
function __action325 (line 16522) | fn __action325<
type __ToTriple (line 16544) | pub trait __ToTriple<'input, > {
method to_triple (line 16545) | fn to_triple(value: Self) -> Result<(usize,Tok<'input>,usize), __lalrp...
function to_triple (line 16549) | fn to_triple(value: Self) -> Result<(usize,Tok<'input>,usize), __lalrpop...
function to_triple (line 16554) | fn to_triple(value: Self) -> Result<(usize,Tok<'input>,usize), __lalrpop...
FILE: libeir_syntax_core/src/parser/mod.rs
function parse (line 6) | pub fn parse<'input>(text: &'input str) -> Result<Annotated<Module>,
FILE: libeir_syntax_erl/build.rs
function main (line 3) | fn main() {
FILE: libeir_syntax_erl/src/abstr/lower.rs
function to_list_expr (line 14) | fn to_list_expr(
function lower (line 31) | pub fn lower(root: &aast::Root) -> ast::Module {
function lower_record_field (line 186) | fn lower_record_field(gen: &mut ast::NodeIdGenerator, tup_item: &aast::I...
function lower_function_clause (line 205) | fn lower_function_clause(
function lower_clause (line 237) | fn lower_clause(gen: &mut ast::NodeIdGenerator, clause: &aast::Item) -> ...
function lower_if_clause (line 264) | fn lower_if_clause(gen: &mut ast::NodeIdGenerator, clause: &aast::Item) ...
function lower_try_clause (line 285) | fn lower_try_clause(gen: &mut ast::NodeIdGenerator, clause: &aast::Item)...
function lower_guards (line 335) | fn lower_guards(gen: &mut ast::NodeIdGenerator, guard: &aast::Item) -> O...
function lower_body (line 355) | fn lower_body(gen: &mut ast::NodeIdGenerator, body: &aast::Item) -> Vec<...
function lower_expr (line 364) | fn lower_expr(gen: &mut ast::NodeIdGenerator, expr: &aast::Item) -> ast:...
function atom (line 812) | fn atom(item: &aast::Item) -> Ident {
function integer (line 818) | fn integer(item: &aast::Item) -> &aast::Int {
type ParseOrLowerError (line 835) | enum ParseOrLowerError {
method from (line 848) | fn from(e: ParseError) -> Self {
method from (line 853) | fn from(e: LowerError) -> Self {
method to_diagnostic (line 840) | fn to_diagnostic(&self) -> Diagnostic {
function parse (line 858) | fn parse<T, S>(input: S) -> T
function parse_file (line 876) | fn parse_file<T, S>(path: S) -> T
function basic_ast (line 895) | fn basic_ast() {
function maps (line 924) | fn maps() {
function match_suite (line 930) | fn match_suite() {
FILE: libeir_syntax_erl/src/evaluator.rs
type EvalError (line 16) | pub enum EvalError {
method to_diagnostic (line 46) | fn to_diagnostic(&self) -> Diagnostic {
type Term (line 79) | pub enum Term {
method from (line 136) | fn from(num: Number) -> Term {
method from (line 141) | fn from(cond: bool) -> Term {
method equals (line 151) | pub fn equals(&self, rhs: &Term, exact: bool) -> bool {
method eq (line 89) | fn eq(&self, other: &Term) -> bool {
method cmp (line 97) | fn cmp(&self, other: &Term) -> Ordering {
method partial_cmp (line 130) | fn partial_cmp(&self, other: &Term) -> Option<Ordering> {
type ResolveRecordIndexError (line 164) | pub enum ResolveRecordIndexError {
function eval_expr (line 169) | pub fn eval_expr(
FILE: libeir_syntax_erl/src/lexer/errors.rs
type LexicalError (line 12) | pub enum LexicalError {
method span (line 78) | pub fn span(&self) -> SourceSpan {
method hash (line 37) | fn hash<H: Hasher>(&self, state: &mut H) {
method to_diagnostic (line 50) | fn to_diagnostic(&self) -> Diagnostic {
type TokenConvertError (line 92) | pub struct TokenConvertError {
FILE: libeir_syntax_erl/src/lexer/lexer.rs
type Lexer (line 63) | pub struct Lexer<S> {
function new (line 95) | pub fn new(scanner: Scanner<S>) -> Self {
function lex (line 109) | pub fn lex(&mut self) -> Option<<Self as Iterator>::Item> {
function advance (line 130) | fn advance(&mut self) {
function advance_start (line 136) | fn advance_start(&mut self) {
function pop (line 160) | fn pop(&mut self) -> char {
function peek (line 167) | fn peek(&mut self) -> char {
function peek_next (line 173) | fn peek_next(&mut self) -> char {
function read (line 179) | fn read(&mut self) -> char {
function index (line 185) | fn index(&mut self) -> SourceIndex {
function skip (line 190) | fn skip(&mut self) {
function span (line 196) | pub fn span(&self) -> SourceSpan {
function slice (line 202) | fn slice(&self) -> &str {
function slice_span (line 207) | fn slice_span(&self, span: impl Into<Range<usize>>) -> &str {
function skip_whitespace (line 212) | fn skip_whitespace(&mut self) {
function tokenize (line 225) | fn tokenize(&mut self) -> Token {
function lex_comment (line 378) | fn lex_comment(&mut self) -> Token {
function lex_escape_sequence (line 454) | fn lex_escape_sequence(&mut self) -> Result<u64, LexicalError> {
function lex_string (line 488) | fn lex_string(&mut self) -> Token {
function lex_identifier (line 535) | fn lex_identifier(&mut self) -> Token {
function lex_bare_atom (line 552) | fn lex_bare_atom(&mut self) -> Token {
function lex_digits (line 569) | fn lex_digits(
function lex_number (line 602) | fn lex_number(&mut self) -> Token {
function lex_float (line 716) | fn lex_float(&mut self, num: String, seen_e: bool) -> Token {
function to_float_literal (line 757) | fn to_float_literal(&self, num: String) -> Token {
type Item (line 778) | type Item = Lexed;
method next (line 780) | fn next(&mut self) -> Option<Self::Item> {
function to_integer_literal (line 798) | fn to_integer_literal(literal: &str, radix: u32) -> Token {
function lex_symbols (line 841) | fn lex_symbols() {
function lex_comment (line 848) | fn lex_comment() {
function lex_float_literal (line 860) | fn lex_float_literal() {
function lex_identifier_or_atom (line 899) | fn lex_identifier_or_atom() {
function lex_integer_literal (line 919) | fn lex_integer_literal() {
function lex_string (line 991) | fn lex_string() {
function lex_whitespace (line 1007) | fn lex_whitespace() {
FILE: libeir_syntax_erl/src/lexer/mod.rs
type Lexed (line 16) | pub type Lexed = Result<LexicalToken, LexicalError>;
type TokenConvertResult (line 19) | pub type TokenConvertResult<T> = Result<T, TokenConvertError>;
FILE: libeir_syntax_erl/src/lexer/token.rs
type LexicalToken (line 12) | pub struct LexicalToken(pub SourceIndex, pub Token, pub SourceIndex);
method token (line 15) | pub fn token(&self) -> Token {
method span (line 20) | pub fn span(&self) -> SourceSpan {
method fmt (line 25) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
method into (line 30) | fn into(self) -> (SourceIndex, Token, SourceIndex) {
method from (line 35) | fn from(triple: (SourceIndex, Token, SourceIndex)) -> LexicalToken {
type TokenType (line 42) | pub enum TokenType {
method fmt (line 50) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
type AtomToken (line 62) | pub struct AtomToken(pub SourceIndex, pub Token, pub SourceIndex);
method token (line 64) | pub fn token(&self) -> Token {
method span (line 67) | pub fn span(&self) -> SourceSpan {
method symbol (line 70) | pub fn symbol(&self) -> Symbol {
type Error (line 78) | type Error = TokenConvertError;
method try_from (line 80) | fn try_from(t: LexicalToken) -> TokenConvertResult<AtomToken> {
method into (line 99) | fn into(self) -> LexicalToken {
method fmt (line 104) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
type IdentToken (line 110) | pub struct IdentToken(pub SourceIndex, pub Token, pub SourceIndex);
method token (line 112) | pub fn token(&self) -> Token {
method span (line 115) | pub fn span(&self) -> SourceSpan {
method symbol (line 118) | pub fn symbol(&self) -> Symbol {
type Error (line 126) | type Error = TokenConvertError;
method try_from (line 128) | fn try_from(t: LexicalToken) -> TokenConvertResult<IdentToken> {
method into (line 140) | fn into(self) -> LexicalToken {
method fmt (line 145) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
type StringToken (line 151) | pub struct StringToken(pub SourceIndex, pub Token, pub SourceIndex);
method token (line 153) | pub fn token(&self) -> Token {
method span (line 156) | pub fn span(&self) -> SourceSpan {
method symbol (line 159) | pub fn symbol(&self) -> Symbol {
type Error (line 167) | type Error = TokenConvertError;
method try_from (line 169) | fn try_from(t: LexicalToken) -> TokenConvertResult<StringToken> {
method into (line 181) | fn into(self) -> LexicalToken {
method fmt (line 186) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
type IntegerToken (line 192) | pub struct IntegerToken(pub SourceIndex, pub Token, pub SourceIndex);
method token (line 194) | pub fn token(&self) -> Token {
method span (line 197) | pub fn span(&self) -> SourceSpan {
method small_integer (line 200) | pub fn small_integer(&self) -> Option<i64> {
type Error (line 208) | type Error = TokenConvertError;
method try_from (line 210) | fn try_from(t: LexicalToken) -> TokenConvertResult<Self> {
method into (line 222) | fn into(self) -> LexicalToken {
method fmt (line 227) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
type SymbolToken (line 233) | pub struct SymbolToken(pub SourceIndex, pub Token, pub SourceIndex);
method token (line 235) | pub fn token(&self) -> Token {
method span (line 238) | pub fn span(&self) -> SourceSpan {
type Error (line 243) | type Error = TokenConvertError;
method try_from (line 245) | fn try_from(t: LexicalToken) -> TokenConvertResult<SymbolToken> {
method into (line 260) | fn into(self) -> LexicalToken {
method fmt (line 265) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
type DelayedSubstitution (line 271) | pub enum DelayedSubstitution {
type Token (line 278) | pub enum Token {
method from_bare_atom (line 456) | pub fn from_bare_atom<'input>(atom: &'input str) -> Self {
method get_closing_token (line 490) | pub fn get_closing_token(&self) -> Self {
method fmt (line 502) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
method eq (line 398) | fn eq(&self, other: &Token) -> bool {
method hash (line 442) | fn hash<H: Hasher>(&self, state: &mut H) {
FILE: libeir_syntax_erl/src/lib.rs
type ErlangError (line 18) | pub enum ErlangError {
method from (line 23) | fn from(e: ParserError) -> Self {
method from (line 28) | fn from(e: LowerError) -> Self {
method to_diagnostic (line 33) | fn to_diagnostic(&self) -> libeir_diagnostics::Diagnostic {
FILE: libeir_syntax_erl/src/lower/errors.rs
type LowerError (line 10) | pub enum LowerError {
method from (line 114) | fn from(err: crate::util::string_tokenizer::StringTokenizeError) -> Se...
method from (line 119) | fn from(err: StringError) -> LowerError {
method to_diagnostic (line 125) | fn to_diagnostic(&self) -> Diagnostic {
FILE: libeir_syntax_erl/src/lower/exception_handler_stack.rs
type ExceptionHandlerStack (line 4) | pub struct ExceptionHandlerStack {
method new (line 8) | pub fn new() -> Self {
method push_handler (line 12) | pub fn push_handler(&mut self, handler: Value) {
method pop_handler (line 16) | pub fn pop_handler(&mut self) {
method make_error_jump_trace (line 20) | pub fn make_error_jump_trace(
method make_error_jump (line 36) | pub fn make_error_jump(
method finish (line 53) | pub fn finish(&self) {
method len (line 57) | pub fn len(&self) -> usize {
FILE: libeir_syntax_erl/src/lower/expr/binary.rs
function make_size (line 19) | fn make_size(
function lower_binary_elem (line 60) | pub(crate) fn lower_binary_elem(
function lower_binary_expr (line 115) | pub(super) fn lower_binary_expr(
FILE: libeir_syntax_erl/src/lower/expr/binary_expr.rs
function lower_binary_expr (line 11) | pub(super) fn lower_binary_expr(
FILE: libeir_syntax_erl/src/lower/expr/case.rs
function lower_case_expr (line 13) | pub(super) fn lower_case_expr(
function lower_if_expr (line 86) | pub(super) fn lower_if_expr(
FILE: libeir_syntax_erl/src/lower/expr/catch.rs
function lower_try_expr (line 15) | pub(super) fn lower_try_expr(
function lower_catch_expr (line 196) | pub(super) fn lower_catch_expr(
FILE: libeir_syntax_erl/src/lower/expr/comprehension.rs
type ComprehensionError (line 24) | pub enum ComprehensionError {
function make_head_pattern (line 31) | fn make_head_pattern(
function make_structural_bin_pattern (line 79) | fn make_structural_bin_pattern(
function lower_qual (line 91) | fn lower_qual<F>(
function lower_list_comprehension_expr (line 343) | pub(super) fn lower_list_comprehension_expr(
function lower_binary_comprehension_expr (line 371) | pub(super) fn lower_binary_comprehension_expr(
FILE: libeir_syntax_erl/src/lower/expr/literal.rs
function lower_literal (line 12) | pub(super) fn lower_literal(
function intern_string_const (line 34) | pub fn intern_string_const(ident: Ident, c: &mut ConstantContainer) -> R...
FILE: libeir_syntax_erl/src/lower/expr/map.rs
function lower_map_update_expr (line 11) | pub(super) fn lower_map_update_expr(
function lower_map_expr (line 30) | pub(super) fn lower_map_expr(
function lower (line 55) | fn lower(
FILE: libeir_syntax_erl/src/lower/expr/mod.rs
function lower_block (line 33) | pub(super) fn lower_block<'a, T>(
function lower_block_same_scope (line 69) | pub(super) fn lower_block_same_scope<'a, T>(
function lower_single (line 92) | pub(super) fn lower_single(
function lower_single_same_scope (line 106) | pub(super) fn lower_single_same_scope(
function lower_expr (line 118) | fn lower_expr(
FILE: libeir_syntax_erl/src/lower/expr/receive.rs
function lower_receive (line 13) | pub(super) fn lower_receive(
FILE: libeir_syntax_erl/src/lower/expr/record.rs
function make_rec_fail (line 11) | fn make_rec_fail(
function lower_record_access_expr (line 31) | pub(super) fn lower_record_access_expr(
function lower_record_update_expr (line 65) | pub(super) fn lower_record_update_expr(
function lower_record_expr (line 122) | pub(super) fn lower_record_expr(
function lower_record_index (line 181) | pub(super) fn lower_record_index(
FILE: libeir_syntax_erl/src/lower/mod.rs
type LowerCtx (line 41) | pub(crate) struct LowerCtx<'a> {
function sentinel (line 71) | pub fn sentinel(&self) -> IrValue {
function error (line 75) | pub fn error(&mut self, err: LowerError) {
function warn (line 79) | pub fn warn(&mut self, err: LowerError) {
function failed (line 83) | pub fn failed(&self) -> bool {
function make_unique (line 87) | pub fn make_unique(&mut self) -> usize {
function resolve_rec_idx (line 93) | pub fn resolve_rec_idx(&self, name: Ident, field: Ident) -> Result<usize...
function resolve (line 106) | pub fn resolve(&mut self, ident: Ident) -> IrValue {
function bind_shadow (line 116) | pub fn bind_shadow(&mut self, ident: Ident, val: IrValue) {
function bind (line 125) | pub fn bind(&mut self, ident: Ident, val: IrValue) {
function function_name (line 134) | pub fn function_name(&self) -> String {
function current_location (line 137) | pub fn current_location(&self, b: &mut FunctionBuilder, span: SourceSpan...
function call_function (line 146) | pub fn call_function<M, F>(
function lower_module (line 184) | pub fn lower_module<'a>(
function lower_function (line 242) | fn lower_function(ctx: &mut LowerCtx, b: &mut FunctionBuilder, fun: &Fun...
function lower_function_base (line 267) | fn lower_function_base(
function lower_top_function (line 364) | fn lower_top_function(ctx: &mut LowerCtx, b: &mut FunctionBuilder, funct...
FILE: libeir_syntax_erl/src/lower/pattern/mod.rs
type EqGuard (line 19) | enum EqGuard {
type ClauseLowerCtx (line 24) | struct ClauseLowerCtx {
method clause_value (line 52) | pub fn clause_value(&mut self, pat: &mut PatternContainer, val: IrValu...
method lower_guard (line 197) | fn lower_guard(
type LoweredClause (line 62) | pub(crate) struct LoweredClause {
method make_body (line 71) | pub fn make_body(&self, ctx: &mut LowerCtx, b: &mut FunctionBuilder) -...
type UnreachableClause (line 90) | pub(crate) struct UnreachableClause {
method make_body (line 95) | pub fn make_body(&self, ctx: &mut LowerCtx, b: &mut FunctionBuilder) -...
function lower_clause (line 115) | pub(super) fn lower_clause<'a, P>(
FILE: libeir_syntax_erl/src/lower/pattern/tree/from_expr.rs
function pattern_to_tree_node_append_tail (line 24) | fn pattern_to_tree_node_append_tail(
method add_root (line 81) | pub(crate) fn add_root(
function pattern_to_tree_node (line 93) | fn pattern_to_tree_node(
FILE: libeir_syntax_erl/src/lower/pattern/tree/lower.rs
method lower (line 13) | pub(in super::super) fn lower(
method pseudo_binds (line 74) | pub fn pseudo_binds(&self) -> Vec<Ident> {
function create_nodes (line 84) | fn create_nodes(
function lower_tree_node (line 125) | fn lower_tree_node(
FILE: libeir_syntax_erl/src/lower/pattern/tree/merge.rs
function merge_tree_nodes (line 12) | pub(crate) fn merge_tree_nodes(ctx: &mut LowerCtx, b: &mut FunctionBuild...
function map_node (line 21) | fn map_node(ctx: &mut LowerCtx, b: &mut FunctionBuilder, t: &mut Tree, n...
function merge_nodes (line 94) | fn merge_nodes(
FILE: libeir_syntax_erl/src/lower/pattern/tree/mod.rs
type Tree (line 28) | pub(crate) struct Tree {
method new (line 41) | pub fn new() -> Self {
method process (line 56) | pub fn process(&mut self, ctx: &mut LowerCtx, b: &mut FunctionBuilder,...
method node_span (line 61) | pub fn node_span(&self, node: TreeNode) -> SourceSpan {
method rename (line 74) | fn rename(&mut self, from: TreeNode, to: TreeNode) {
type TreeNode (line 87) | pub(crate) struct TreeNode(u32);
type TreeNodeKind (line 91) | pub(crate) enum TreeNodeKind {
type ConstraintKind (line 129) | pub(crate) enum ConstraintKind {
method constant (line 136) | fn constant(&self) -> Option<Const> {
method primop (line 143) | fn primop(&self) -> Option<PrimOp> {
method value (line 150) | fn value(&self) -> Option<IrValue> {
FILE: libeir_syntax_erl/src/lower/pattern/tree/promote_values.rs
type PromoteCtx (line 15) | struct PromoteCtx<'a, 'b> {
function resolve_or_bind (line 22) | fn resolve_or_bind(
function resolve_only (line 52) | fn resolve_only(&self, ident: Ident) -> Option<Either<TreeNode, IrValue>> {
function bind (line 64) | fn bind(&mut self, ident: Ident, node: TreeNode) -> Option<TreeNode> {
function promote_values (line 79) | pub(crate) fn promote_values(
function process_constants_node (line 106) | fn process_constants_node(
function promote_values_node (line 129) | fn promote_values_node(
FILE: libeir_syntax_erl/src/lower/scope.rs
function is_wildcard (line 11) | pub fn is_wildcard(ident: Ident) -> bool {
type ScopeToken (line 15) | pub struct ScopeToken {
type ScopeTracker (line 21) | pub struct ScopeTracker {
method new (line 28) | pub fn new() -> Self {
method push (line 36) | pub fn push(&mut self) -> ScopeToken {
method pop (line 46) | pub fn pop(&mut self, token: ScopeToken) {
method pop_take (line 53) | pub fn pop_take(&mut self, token: ScopeToken) -> HashMap<Ident, IrValu...
method resolve (line 68) | pub fn resolve(&self, ident: Ident) -> Result<IrValue, LowerError> {
method bind (line 76) | pub fn bind(&mut self, ident: Ident, val: IrValue) -> Result<(), Lower...
method bind_shadow (line 92) | pub fn bind_shadow(&mut self, ident: Ident, val: IrValue) -> Result<()...
method height (line 109) | pub fn height(&self) -> usize {
type Branch (line 115) | struct Branch {
type ScopeMerge (line 126) | pub(super) struct ScopeMerge {
method new (line 131) | pub fn new() -> Self {
method branch (line 137) | pub fn branch(&mut self, cont: IrBlock, ret: IrValue, binds: HashMap<I...
method finish (line 145) | pub fn finish(&mut self, ctx: &mut LowerCtx, b: &mut FunctionBuilder) ...
FILE: libeir_syntax_erl/src/lower/tests.rs
function parse (line 13) | fn parse<T, S>(input: S, config: ParseConfig, codemap: Arc<CodeMap>) -> T
function lower (line 28) | fn lower(input: &str, config: ParseConfig) -> Result<IrModule, ()> {
function fib_lower (line 40) | fn fib_lower() {
function pat_1_lower (line 53) | fn pat_1_lower() {
function spec_named_return_type (line 66) | fn spec_named_return_type() {
function delayed_substitution_macros (line 79) | fn delayed_substitution_macros() {
FILE: libeir_syntax_erl/src/parser/ast/attributes.rs
type TypeDef (line 22) | pub struct TypeDef {
method eq (line 30) | fn eq(&self, other: &Self) -> bool {
type TypeSpec (line 67) | pub struct TypeSpec {
method eq (line 74) | fn eq(&self, other: &Self) -> bool {
type Callback (line 83) | pub struct Callback {
method eq (line 91) | fn eq(&self, other: &Self) -> bool {
type TypeSig (line 101) | pub struct TypeSig {
type TypeGuard (line 110) | pub struct TypeGuard {
method eq (line 116) | fn eq(&self, other: &TypeGuard) -> bool {
type UserAttribute (line 129) | pub struct UserAttribute {
method eq (line 135) | fn eq(&self, other: &Self) -> bool {
type Deprecation (line 142) | pub enum Deprecation {
method span (line 154) | pub fn span(&self) -> SourceSpan {
method eq (line 162) | fn eq(&self, other: &Self) -> bool {
method hash (line 181) | fn hash<H: Hasher>(&self, state: &mut H) {
type DeprecatedFlag (line 192) | pub enum DeprecatedFlag {
method fmt (line 199) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
type Attribute (line 211) | pub enum Attribute {
method eq (line 228) | fn eq(&self, other: &Attribute) -> bool {
FILE: libeir_syntax_erl/src/parser/ast/expr.rs
type Expr (line 15) | pub enum Expr {
method span (line 55) | pub fn span(&self) -> SourceSpan {
method id (line 90) | pub fn id(&self) -> NodeId {
type Var (line 128) | pub struct Var(pub NodeId, pub Ident);
method eq (line 130) | fn eq(&self, other: &Self) -> bool {
type Nil (line 137) | pub struct Nil(pub SourceSpan, pub NodeId);
method eq (line 139) | fn eq(&self, _: &Self) -> bool {
type Cons (line 146) | pub struct Cons {
method eq (line 153) | fn eq(&self, other: &Self) -> bool {
type Tuple (line 167) | pub struct Tuple {
method eq (line 173) | fn eq(&self, other: &Self) -> bool {
type Map (line 184) | pub struct Map {
method eq (line 190) | fn eq(&self, other: &Self) -> bool {
type MapUpdate (line 202) | pub struct MapUpdate {
method eq (line 209) | fn eq(&self, other: &Self) -> bool {
type MapProjection (line 216) | pub struct MapProjection {
method eq (line 223) | fn eq(&self, other: &Self) -> bool {
type Literal (line 235) | pub enum Literal {
method span (line 243) | pub fn span(&self) -> SourceSpan {
method id (line 252) | pub fn id(&self) -> NodeId {
method eq (line 263) | fn eq(&self, other: &Literal) -> bool {
method partial_cmp (line 277) | fn partial_cmp(&self, other: &Literal) -> Option<Ordering> {
type MapField (line 316) | pub enum MapField {
method key (line 331) | pub fn key(&self) -> Expr {
method value (line 338) | pub fn value(&self) -> Expr {
method span (line 345) | pub fn span(&self) -> SourceSpan {
method eq (line 353) | fn eq(&self, other: &Self) -> bool {
type Record (line 368) | pub struct Record {
method eq (line 375) | fn eq(&self, other: &Self) -> bool {
type RecordAccess (line 382) | pub struct RecordAccess {
method eq (line 390) | fn eq(&self, other: &Self) -> bool {
type RecordIndex (line 397) | pub struct RecordIndex {
method eq (line 404) | fn eq(&self, other: &Self) -> bool {
type RecordUpdate (line 411) | pub struct RecordUpdate {
method eq (line 419) | fn eq(&self, other: &Self) -> bool {
type RecordField (line 429) | pub struct RecordField {
method eq (line 437) | fn eq(&self, other: &Self) -> bool {
type Binary (line 443) | pub struct Binary {
method eq (line 449) | fn eq(&self, other: &Self) -> bool {
type BinaryElement (line 457) | pub struct BinaryElement {
method eq (line 465) | fn eq(&self, other: &Self) -> bool {
type BitType (line 474) | pub enum BitType {
method span (line 479) | pub fn span(&self) -> SourceSpan {
method eq (line 487) | fn eq(&self, other: &Self) -> bool {
type ListComprehension (line 499) | pub struct ListComprehension {
method eq (line 506) | fn eq(&self, other: &Self) -> bool {
type Binar
Condensed preview — 339 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (3,509K chars).
[
{
"path": ".gitignore",
"chars": 226,
"preview": "target/\n**/*.rs.bk\nCargo.lock\n\n*.dot\n*.dot.pdf\n*.core\n*.eir\n*.png\n\n!test_data/**/*.core\ntest_data/**/.*.core\n\n*.swp\n\ncom"
},
{
"path": ".gitmodules",
"chars": 71,
"preview": "[submodule \"otp\"]\n\tpath = otp\n\turl = https://github.com/erlang/otp.git\n"
},
{
"path": "DOCS.md",
"chars": 5527,
"preview": "# Type system\n\nThere are two parallel type systems:\n * Pessimistic types\n * Optimistic types\n\nPessimistic types are what"
},
{
"path": "LICENSE.md",
"chars": 11347,
"preview": " Apache License\n Version 2.0, January 2004\n "
},
{
"path": "README.md",
"chars": 1048,
"preview": "# Eir Project\nErlang compiler and IR implemented in Rust\n\n## Details\n\nCurrent features:\n* Unified Thorin based IR repres"
},
{
"path": "ROADMAP.org",
"chars": 1073,
"preview": "* Roadmap\n** 1. Cleanup\n*** Includes fixing all tech dept created leading up to the conference\n*** Setting up infrastruc"
},
{
"path": "azure-pipelines.yml",
"chars": 691,
"preview": "variables:\n nightly: nightly-2020-08-15\n RUSTFLAGS:\n\njobs:\n\n # Test crates\n - template: ci/azure-test.yml\n parame"
},
{
"path": "ci/azure-clone-patch-otp.yml",
"chars": 197,
"preview": "steps:\n - script: |\n set -e\n cd $(Build.SourcesDirectory)\n git submodule update --init --recursive\n "
},
{
"path": "ci/azure-install-dependencies.yml",
"chars": 234,
"preview": "steps:\n\n # Windows only: Install m4\n #- script: |\n # choco install msys2\n # refreshenv\n # pacman -S --noco"
},
{
"path": "ci/azure-install-rust.yml",
"chars": 1359,
"preview": "steps:\n # Linux and macOS.\n - script: |\n set -e\n curl https://sh.rustup.rs -sSf | sh -s -- -y --default-tool"
},
{
"path": "ci/azure-test.yml",
"chars": 916,
"preview": "jobs:\n - job: ${{ parameters.name }}\n displayName: ${{ parameters.displayName }}\n strategy:\n matrix:\n "
},
{
"path": "deny.toml",
"chars": 2638,
"preview": "[licenses]\n# This section is considered when running `cargo deny check license`\n# More documentation for the licenses se"
},
{
"path": "libeir_diagnostics/Cargo.toml",
"chars": 399,
"preview": "[package]\nname = \"libeir_diagnostics\"\nversion = \"0.1.0\"\nauthors = [\"Paul Schoenfelder <paulschoenfelder@gmail.com>\", \"Lu"
},
{
"path": "libeir_diagnostics/src/codemap.rs",
"chars": 5849,
"preview": "use std::ops::Range;\nuse std::path::PathBuf;\nuse std::sync::atomic::{AtomicU32, Ordering};\nuse std::sync::Arc;\n\nuse dash"
},
{
"path": "libeir_diagnostics/src/filename.rs",
"chars": 2656,
"preview": "//! Various source mapping utilities\n\nuse std::borrow::Cow;\nuse std::fmt;\nuse std::path::{Path, PathBuf};\n\n#[derive(Clon"
},
{
"path": "libeir_diagnostics/src/index.rs",
"chars": 2882,
"preview": "use std::num::NonZeroUsize;\nuse std::ops::{Add, AddAssign, Sub, SubAssign};\n\nuse codespan::{ByteIndex, ByteOffset, RawIn"
},
{
"path": "libeir_diagnostics/src/lib.rs",
"chars": 990,
"preview": "#![feature(crate_visibility_modifier)]\n\nmod codemap;\nmod filename;\nmod index;\nmod source;\nmod span;\n\npub use codespan::{"
},
{
"path": "libeir_diagnostics/src/source.rs",
"chars": 4624,
"preview": "use std::convert::Into;\nuse std::num::NonZeroU32;\nuse std::ops::Range;\n\nuse super::*;\n\n/// A handle that points to a fil"
},
{
"path": "libeir_diagnostics/src/span.rs",
"chars": 3442,
"preview": "use std::ops::Range;\n\nuse codespan::{ByteIndex, ByteOffset, Span};\n\nuse super::{CodeMap, SourceId, SourceIndex};\n\n#[deri"
},
{
"path": "libeir_frontend/Cargo.toml",
"chars": 602,
"preview": "[package]\nname = \"libeir_frontend\"\nversion = \"0.1.0\"\nauthors = [\"Hans Elias B. Josephsen <me@hansihe.com>\"]\nedition = \"2"
},
{
"path": "libeir_frontend/README.md",
"chars": 163,
"preview": "# libeir_frontend\n\nWrapper crate for all the different frontends in this project.\n\nCurrently includes:\n* eir frontend\n* "
},
{
"path": "libeir_frontend/src/abstr_erlang.rs",
"chars": 2615,
"preview": "use std::path::Path;\nuse std::sync::Arc;\n\nuse libeir_diagnostics::*;\nuse libeir_ir::Module;\nuse libeir_syntax_erl::{lowe"
},
{
"path": "libeir_frontend/src/eir.rs",
"chars": 2417,
"preview": "use std::path::Path;\nuse std::sync::Arc;\n\nuse libeir_diagnostics::*;\nuse libeir_ir::{\n text::{ast::Module as ModuleAs"
},
{
"path": "libeir_frontend/src/erlang.rs",
"chars": 2574,
"preview": "use std::path::Path;\nuse std::sync::Arc;\n\nuse libeir_diagnostics::*;\nuse libeir_ir::Module;\nuse libeir_syntax_erl::{\n "
},
{
"path": "libeir_frontend/src/lib.rs",
"chars": 4444,
"preview": "#[cfg(feature = \"frontend_abstr_erlang\")]\npub mod abstr_erlang;\n#[cfg(feature = \"frontend_eir\")]\npub mod eir;\n#[cfg(feat"
},
{
"path": "libeir_intern/Cargo.toml",
"chars": 363,
"preview": "[package]\nname = \"libeir_intern\"\nversion = \"0.1.0\"\nauthors = [\"Hans Elias B. Josephsen <me@hansihe.com>\"]\nedition = \"201"
},
{
"path": "libeir_intern/src/arena.rs",
"chars": 18270,
"preview": "#![allow(unused)]\n//! NOTE: Modified version of impl in rustc\n//!\n//! The arena, a fast but limited type of allocator.\n/"
},
{
"path": "libeir_intern/src/lib.rs",
"chars": 372,
"preview": "#![feature(core_intrinsics)]\n#![feature(dropck_eyepatch)]\n#![feature(raw_vec_internals)]\n#![feature(test)]\n\nextern crate"
},
{
"path": "libeir_intern/src/symbol.rs",
"chars": 20325,
"preview": "//! An \"interner\" is a data structure that associates values with usize tags and\n//! allows bidirectional lookup; i.e., "
},
{
"path": "libeir_interpreter/Cargo.toml",
"chars": 718,
"preview": "[package]\nname = \"libeir_interpreter\"\nversion = \"0.1.0\"\nauthors = [\"hansihe\"]\nedition = \"2018\"\nlicense = \"MIT OR Apache-"
},
{
"path": "libeir_interpreter/README.md",
"chars": 109,
"preview": "# libeir_interpreter\n\n**This interpreter is really basic and unfinished. It is only meant to aid testing.**\n\n"
},
{
"path": "libeir_interpreter/src/erl_lib/erlang.rs",
"chars": 25289,
"preview": "use libeir_intern::Symbol;\nuse libeir_util_number::bigint_to_double;\n\nuse crate::module::{NativeModule, NativeReturn};\nu"
},
{
"path": "libeir_interpreter/src/erl_lib/file.rs",
"chars": 532,
"preview": "use ::module::NativeModule;\nuse ::vm::VMState;\nuse ::term::Term;\nuse ::process::{ CallReturn, ProcessContext };\n\nfn dele"
},
{
"path": "libeir_interpreter/src/erl_lib/lists.rs",
"chars": 2646,
"preview": "use std::rc::Rc;\n\nuse crate::module::{NativeModule, NativeReturn};\nuse crate::process::ProcessContext;\nuse crate::term::"
},
{
"path": "libeir_interpreter/src/erl_lib/maps.rs",
"chars": 1300,
"preview": "use libeir_intern::Symbol;\n\nuse crate::module::{NativeModule, NativeReturn};\nuse crate::process::ProcessContext;\nuse cra"
},
{
"path": "libeir_interpreter/src/erl_lib/math.rs",
"chars": 887,
"preview": "use std::rc::Rc;\n\nuse crate::module::{NativeModule, NativeReturn};\nuse crate::process::ProcessContext;\nuse crate::term::"
},
{
"path": "libeir_interpreter/src/erl_lib/mod.rs",
"chars": 262,
"preview": "mod erlang;\npub use self::erlang::make_erlang;\n\n//mod os;\n//pub use self::os::make_os;\n\nmod lists;\npub use self::lists::"
},
{
"path": "libeir_interpreter/src/erl_lib/os.rs",
"chars": 836,
"preview": "use ::vm::VMState;\nuse ::module::NativeModule;\nuse ::term::Term;\nuse ::process::{ CallReturn, ProcessContext };\n\nfn gete"
},
{
"path": "libeir_interpreter/src/erl_tests/mod.rs",
"chars": 5574,
"preview": "extern crate tempdir;\n\nuse ::std::io::{ Read, Write };\nuse ::{ VMState, Term };\nuse eir::Module;\nuse ::term::ErlEq;\n\nfn "
},
{
"path": "libeir_interpreter/src/lib.rs",
"chars": 348,
"preview": "//#![deny(warnings)]\n\n//! LIR interpreter with zero consideration of performance.\n//! Made as an experiment to narrow do"
},
{
"path": "libeir_interpreter/src/mailbox.rs",
"chars": 422,
"preview": "use ::term::{ Term, Pid };\n\n#[derive(Debug)]\npub struct Mailbox {\n trap_exits: bool,\n messages: Vec<(Pid, Term)>,\n"
},
{
"path": "libeir_interpreter/src/module.rs",
"chars": 1893,
"preview": "use std::collections::HashMap;\nuse std::rc::Rc;\n\nuse crate::process::ProcessContext;\nuse crate::{Term, VMState};\n\nuse li"
},
{
"path": "libeir_interpreter/src/pattern.rs",
"chars": 6569,
"preview": "use std::collections::HashMap;\n\nuse ::term::Term;\nuse eir::Clause;\nuse eir::pattern::PatternNode;\nuse eir::AtomicTerm;\nu"
},
{
"path": "libeir_interpreter/src/process/match.rs",
"chars": 7638,
"preview": "use libeir_ir::{BasicType, BinaryEntrySpecifier, Block, Endianness, MatchKind};\n\nuse libeir_util_binary::BitCarrier;\nuse"
},
{
"path": "libeir_interpreter/src/process/mod.rs",
"chars": 23554,
"preview": "use std::any::TypeId;\nuse std::collections::HashMap;\nuse std::rc::Rc;\n\nuse num_traits::cast::ToPrimitive;\n\nuse libeir_in"
},
{
"path": "libeir_interpreter/src/receive.rs",
"chars": 199,
"preview": "use ::term::Term;\n\n#[derive(Debug)]\npub struct ReceiveContext {\n}\n\nimpl ReceiveContext {\n\n pub fn new(timeout: Term) "
},
{
"path": "libeir_interpreter/src/term.rs",
"chars": 26896,
"preview": "use std::cmp::{Ord, Ordering};\nuse std::collections::HashMap;\nuse std::hash::{Hash, Hasher};\nuse std::rc::Rc;\n\nuse libei"
},
{
"path": "libeir_interpreter/src/trace/dummy.rs",
"chars": 579,
"preview": "use std::rc::Rc;\nuse std::collections::HashMap;\n\nuse crate::term::{ Term, Pid };\n\nuse libeir_ir::{ FunctionIdent, Block "
},
{
"path": "libeir_interpreter/src/trace/mod.rs",
"chars": 201,
"preview": "\n//#[cfg(not(feature = \"trace\"))]\n//#[macro_use]\nmod dummy;\n//#[cfg(not(feature = \"trace\"))]\nuse self::dummy as trace;\n\n"
},
{
"path": "libeir_interpreter/src/trace/trace.rs",
"chars": 9524,
"preview": "\nuse std::rc::Rc;\nuse crate::term::{ Term, Pid };\n\nuse libeir_ir::{ FunctionIdent, Block, Value };\nuse libeir_intern::Sy"
},
{
"path": "libeir_interpreter/src/vm.rs",
"chars": 6294,
"preview": "use std::cell::RefCell;\nuse std::collections::HashMap;\nuse std::rc::Rc;\n\nuse crate::module::{ErlangModule, ModuleType, N"
},
{
"path": "libeir_ir/Cargo.toml",
"chars": 1603,
"preview": "[package]\nname = \"libeir_ir\"\nversion = \"0.1.0\"\nauthors = [\"Hans Elias B. Josephsen <me@hansihe.com>\"]\nedition = \"2018\"\nb"
},
{
"path": "libeir_ir/build.rs",
"chars": 257,
"preview": "extern crate lalrpop;\n\nfn main() {\n lalrpop::Configuration::new()\n .use_cargo_dir_conventions()\n .proce"
},
{
"path": "libeir_ir/src/algo/equality.rs",
"chars": 10634,
"preview": "use std::collections::{BTreeMap, VecDeque};\n\nuse snafu::Snafu;\n\nuse crate::Function;\nuse crate::ValueKind;\nuse crate::{B"
},
{
"path": "libeir_ir/src/algo/func_tree.rs",
"chars": 9671,
"preview": "use std::collections::{BTreeMap, BTreeSet};\n\nuse petgraph::visit::{Dfs, DfsPostOrder};\nuse petgraph::visit::{GraphBase, "
},
{
"path": "libeir_ir/src/algo/live.rs",
"chars": 7069,
"preview": "use std::collections::HashMap;\n\nuse crate::Function;\nuse crate::{Block, Value};\n\nuse cranelift_bforest::{BoundSet, Set, "
},
{
"path": "libeir_ir/src/algo/mangle/datatypes.rs",
"chars": 5805,
"preview": "#![allow(dead_code)]\nuse crate::Function;\nuse crate::{Block, Value};\n\nuse super::MangleReceiver;\n\n#[derive(Debug, Copy, "
},
{
"path": "libeir_ir/src/algo/mangle/mod.rs",
"chars": 13908,
"preview": "use std::collections::{BTreeMap, BTreeSet};\n\nuse bumpalo::Bump;\n\nuse libeir_diagnostics::SourceSpan;\n\nuse crate::Block;\n"
},
{
"path": "libeir_ir/src/algo/mangle/receiver.rs",
"chars": 3109,
"preview": "use crate::OpKind;\nuse crate::{Function, FunctionBuilder};\n\nuse super::{MangleBlock, MangleValue, ToValue};\n\n/// Trait u"
},
{
"path": "libeir_ir/src/algo/mangle/tests.rs",
"chars": 5718,
"preview": "use crate::{NilTerm, StandardFormatConfig};\n\nuse super::Mangler;\nuse super::ToT;\n\n#[test]\nfn simple_mangle() {\n let ("
},
{
"path": "libeir_ir/src/algo/mod.rs",
"chars": 106,
"preview": "pub mod equality;\npub mod func_tree;\npub mod live;\npub mod mangle;\npub mod op_branches;\npub mod validate;\n"
},
{
"path": "libeir_ir/src/algo/op_branches.rs",
"chars": 3731,
"preview": "use crate::Function;\nuse crate::{Block, CallKind, OpKind, Value};\n\npub struct BranchIter<'a> {\n fun: &'a Function,\n "
},
{
"path": "libeir_ir/src/algo/validate.rs",
"chars": 10713,
"preview": "use std::collections::HashSet;\n\nuse fnv::FnvBuildHasher;\nuse hashbrown::HashMap;\ntype FnvHashMap<K, V> = HashMap<K, V, F"
},
{
"path": "libeir_ir/src/binary.rs",
"chars": 1800,
"preview": "use serde::{Deserialize, Serialize};\nuse std::default::Default;\n\n#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Seria"
},
{
"path": "libeir_ir/src/constant/atomic.rs",
"chars": 5531,
"preview": "use std::fmt::{Display, Formatter, Result as FmtResult};\nuse std::hash::{Hash, Hasher};\n\nuse libeir_util_number::{cast, "
},
{
"path": "libeir_ir/src/constant/float.rs",
"chars": 906,
"preview": "use libeir_util_number::traits::Float;\n\n// Copied from https://github.com/reem/rust-ordered-float\n\n// masks for the part"
},
{
"path": "libeir_ir/src/constant/mod.rs",
"chars": 9822,
"preview": "use std::hash::{Hash, Hasher};\n\nuse libeir_intern::Ident;\n\nuse libeir_util_datastructures::aux_hash_map::AuxHashMap;\nuse"
},
{
"path": "libeir_ir/src/dialect/mod.rs",
"chars": 2457,
"preview": "use std::any::TypeId;\nuse std::collections::{HashMap, HashSet};\nuse std::fmt::{self, Debug, Formatter};\nuse std::sync::A"
},
{
"path": "libeir_ir/src/function/builder/mod.rs",
"chars": 12288,
"preview": "use libeir_diagnostics::SourceSpan;\n\nuse super::Function;\nuse super::ValueKind;\nuse super::{Block, Const, Location, OpKi"
},
{
"path": "libeir_ir/src/function/builder/op.rs",
"chars": 14219,
"preview": "use cranelift_entity::EntityList;\nuse libeir_diagnostics::SourceSpan;\n\nuse crate::binary::BinaryEntrySpecifier;\nuse crat"
},
{
"path": "libeir_ir/src/function/builder/primop.rs",
"chars": 11286,
"preview": "use cranelift_entity::EntityList;\n\nuse libeir_diagnostics::SourceSpan;\n\nuse super::{BinOp, FunctionBuilder, PrimOpData, "
},
{
"path": "libeir_ir/src/function/format.rs",
"chars": 4968,
"preview": "#[macro_export]\nmacro_rules! function_format {\n ($fun:expr, $str:expr, $($arg:expr),*) => {\n format!($str, $($"
},
{
"path": "libeir_ir/src/function/location.rs",
"chars": 9153,
"preview": "use std::hash::{Hash, Hasher};\n\nuse libeir_util_datastructures::dedup_aux_primary_map::DedupPrimaryMap;\nuse libeir_util_"
},
{
"path": "libeir_ir/src/function/mod.rs",
"chars": 16463,
"preview": "use std::cmp::Eq;\nuse std::collections::HashSet;\nuse std::hash::{Hash, Hasher};\n\nuse cranelift_bforest::{BoundSet, Set, "
},
{
"path": "libeir_ir/src/function/op.rs",
"chars": 4240,
"preview": "use crate::binary::BinaryEntrySpecifier;\nuse crate::operation::{DynOp, Op};\n\nuse serde::{Deserialize, Serialize};\n\n#[der"
},
{
"path": "libeir_ir/src/function/pool_container.rs",
"chars": 210,
"preview": "use cranelift_bforest::SetForest;\nuse cranelift_entity::ListPool;\n\nuse super::{Block, Value};\n\n#[derive(Clone)]\npub stru"
},
{
"path": "libeir_ir/src/function/primop.rs",
"chars": 1613,
"preview": "use serde::{Deserialize, Serialize};\n\n#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]\npub enu"
},
{
"path": "libeir_ir/src/function/serialize.rs",
"chars": 278,
"preview": "use super::Function;\n\nuse serde::{ Serialize, Serializer, Deserialize };\n\nimpl Serialize for Function {\n fn serialize"
},
{
"path": "libeir_ir/src/function/value.rs",
"chars": 2495,
"preview": "use std::collections::HashMap;\nuse std::ops::{Index, IndexMut};\n\nuse super::{Block, Const, Location, PrimOp};\nuse cranel"
},
{
"path": "libeir_ir/src/graph/block_graph.rs",
"chars": 6229,
"preview": "use petgraph::visit::{Dfs, DfsPostOrder};\nuse petgraph::visit::{\n GraphBase, IntoNeighbors, IntoNeighborsDirected, Vi"
},
{
"path": "libeir_ir/src/graph/control_flow_graph.rs",
"chars": 4815,
"preview": "use std::collections::BTreeSet;\n\nuse petgraph::visit::{Dfs, DfsPostOrder};\nuse petgraph::visit::{GraphBase, IntoNeighbor"
},
{
"path": "libeir_ir/src/graph/live_block_graph.rs",
"chars": 6296,
"preview": "use std::collections::HashSet;\n\nuse petgraph::visit::{Dfs, DfsPostOrder};\nuse petgraph::visit::{\n GraphBase, IntoNeig"
},
{
"path": "libeir_ir/src/graph/mod.rs",
"chars": 282,
"preview": "pub use petgraph::visit::IntoNeighborsDirected;\npub use petgraph::Direction;\n\nmod block_graph;\npub use block_graph::{Blo"
},
{
"path": "libeir_ir/src/ir_construct_macro.rs",
"chars": 3509,
"preview": "#![allow(unused_macros)]\n\nmacro_rules! build_ir {\n ($module:ident : $name:ident / $arity:expr => $body:tt) => {\n "
},
{
"path": "libeir_ir/src/lib.rs",
"chars": 2157,
"preview": "#![feature(specialization, raw, allocator_api)]\n//#![deny(warnings)]\n\nuse std::cmp::Ordering;\nuse std::fmt::{Display, Fo"
},
{
"path": "libeir_ir/src/module.rs",
"chars": 4136,
"preview": "use std::collections::BTreeMap;\nuse std::ops::{Index, IndexMut};\n\nuse cranelift_entity::{entity_impl, PrimaryMap};\n\nuse "
},
{
"path": "libeir_ir/src/operation/binary_construct.rs",
"chars": 7340,
"preview": "//! # Binary construction construct\n//! Binary construction is represented as several intrinsics that interact\n//! to re"
},
{
"path": "libeir_ir/src/operation/case.rs",
"chars": 7979,
"preview": "use std::any::TypeId;\n\nuse libeir_diagnostics::SourceSpan;\nuse libeir_intern::Symbol;\nuse meta_table::{impl_meta_entry, "
},
{
"path": "libeir_ir/src/operation/mod.rs",
"chars": 3117,
"preview": "use std::ops::Deref;\n\nuse std::any::TypeId;\nuse std::fmt::{Debug, Formatter, Result as FmtResult};\nuse std::raw::TraitOb"
},
{
"path": "libeir_ir/src/operation/receive.rs",
"chars": 8804,
"preview": "//! # Receive construct\n//! A receive statement is represented as several intrinsics that\n//! interact to represent the "
},
{
"path": "libeir_ir/src/pattern/fmt.rs",
"chars": 1860,
"preview": "use std::fmt;\nuse super::PatternNode;\n\nimpl fmt::Display for PatternNode {\n fn fmt(&self, f: &mut fmt::Formatter) -> "
},
{
"path": "libeir_ir/src/pattern/mod.rs",
"chars": 29129,
"preview": "use std::collections::HashMap;\n\nuse cranelift_entity::{entity_impl, EntityList, ListPool, PrimaryMap};\n\nuse libeir_diagn"
},
{
"path": "libeir_ir/src/text/ast/mod.rs",
"chars": 6402,
"preview": "use libeir_diagnostics::SourceSpan;\nuse libeir_intern::Ident;\n\nuse crate::constant::Integer;\nuse crate::{BasicType, BinO"
},
{
"path": "libeir_ir/src/text/ast/raise.rs",
"chars": 1685,
"preview": "use std::collections::BTreeMap;\n\nuse libeir_intern::Ident;\n\nuse crate::Function;\nuse crate::{Block, Value};\n//use crate:"
},
{
"path": "libeir_ir/src/text/dot_printer.rs",
"chars": 1650,
"preview": "use std::marker::PhantomData;\n\nuse super::printer as pr;\nuse super::printer::{FormatState, FunctionFormatData};\nuse crat"
},
{
"path": "libeir_ir/src/text/lower/location.rs",
"chars": 1512,
"preview": "use crate::text::parse_dyn::{DynParserError, ParseCtx};\nuse libeir_intern::Symbol;\nuse libeir_util_number::ToPrimitive;\n"
},
{
"path": "libeir_ir/src/text/lower/mod.rs",
"chars": 20987,
"preview": "use std::collections::HashMap;\n\nuse libeir_diagnostics::{Diagnostic, Label, SourceSpan, ToDiagnostic};\nuse libeir_intern"
},
{
"path": "libeir_ir/src/text/mod.rs",
"chars": 1691,
"preview": "//pub mod printer;\n//pub use printer::{ ToEirText, ToEirTextFun, ToEirTextContext };\n\npub mod printer;\n\npub mod dot_prin"
},
{
"path": "libeir_ir/src/text/parse_dyn/mod.rs",
"chars": 14493,
"preview": "use libeir_diagnostics::{Diagnostic, Label, SourceSpan, ToDiagnostic};\nuse libeir_intern::{Ident, Symbol};\nuse snafu::Sn"
},
{
"path": "libeir_ir/src/text/parser/errors.rs",
"chars": 3835,
"preview": "use snafu::Snafu;\nuse std::path::PathBuf;\n\nuse libeir_diagnostics::{Diagnostic, Label, SourceIndex, SourceSpan, ToDiagno"
},
{
"path": "libeir_ir/src/text/parser/grammar.lalrpop",
"chars": 12293,
"preview": "//-*- mode: rust -*-\n\nuse libeir_diagnostics::{SourceIndex, SourceSpan, Diagnostic, Label as DiagLabel};\nuse libeir_inte"
},
{
"path": "libeir_ir/src/text/parser/lexer.rs",
"chars": 11753,
"preview": "#![allow(\n dead_code,\n unreachable_code,\n unused_mut,\n unused_variables,\n unused_macros\n)]\n\nuse std::coll"
},
{
"path": "libeir_ir/src/text/parser/mod.rs",
"chars": 13339,
"preview": "use std::sync::Arc;\n\nuse libeir_diagnostics::{CodeMap, SourceIndex};\nuse libeir_intern::Ident;\nuse libeir_util_parse::{\n"
},
{
"path": "libeir_ir/src/text/printer/constant.rs",
"chars": 4277,
"preview": "use pretty::{Arena, DocAllocator, RefDoc};\n\nuse crate::{AtomicTerm, Const, ConstKind, ConstantContainer};\n\npub fn consta"
},
{
"path": "libeir_ir/src/text/printer/mod.rs",
"chars": 21654,
"preview": "#![allow(unused)]\n\nuse std::collections::BTreeMap;\nuse std::error::Error;\nuse std::fmt::Write;\nuse std::marker::PhantomD"
},
{
"path": "libeir_ir/src/text/printer/operation.rs",
"chars": 17810,
"preview": "use log::warn;\nuse pretty::{DocAllocator, RefDoc};\n\nuse crate::binary::{BinaryEntrySpecifier, Endianness};\nuse crate::tr"
},
{
"path": "libeir_ir/src/text/printer.old.rs",
"chars": 20547,
"preview": "#![allow(clippy::write_with_newline)]\n\nuse std::io::{ Write, Error as IoError };\n\nuse crate::{ Module, Function, Functio"
},
{
"path": "libeir_ir/src/traits/mod.rs",
"chars": 146,
"preview": "mod op_branches;\npub use op_branches::OpBranches;\n\nmod printer;\npub use printer::{FormatOpCtx, OpPrinter};\n\nmod parser;\n"
},
{
"path": "libeir_ir/src/traits/op_branches.rs",
"chars": 641,
"preview": "use crate::{Block, Function, Value};\nuse meta_table::impl_cast_from;\n\n/// When an operation implements this trait, it ha"
},
{
"path": "libeir_ir/src/traits/parser.rs",
"chars": 259,
"preview": "use crate::text::ast::DynToken;\nuse crate::text::LowerContext;\nuse crate::Block;\n\npub trait OpParser: Send + Sync {\n "
},
{
"path": "libeir_ir/src/traits/printer.rs",
"chars": 386,
"preview": "use crate::{Block, DynValue};\nuse meta_table::impl_cast_from;\nuse pretty::RefDoc;\n\npub trait FormatOpCtx<'doc> {\n fn "
},
{
"path": "libeir_lowerutils/Cargo.toml",
"chars": 355,
"preview": "[package]\nname = \"libeir_lowerutils\"\nversion = \"0.1.0\"\nauthors = [\"Hans Elias B. Josephsen <me@hansihe.com>\"]\nedition = "
},
{
"path": "libeir_lowerutils/src/lib.rs",
"chars": 696,
"preview": "use std::collections::{BTreeMap, BTreeSet};\n\nuse libeir_ir::{Block, Function, Value};\nuse libeir_ir::{CallKind, OpKind};"
},
{
"path": "libeir_lowerutils/src/tests.rs",
"chars": 599,
"preview": "use libeir_ir::parse_function_unwrap;\n\n#[test]\nfn simple_function() {\n let fun = parse_function_unwrap(\n \"\na'f"
},
{
"path": "libeir_passes/Cargo.toml",
"chars": 952,
"preview": "[package]\nname = \"libeir_passes\"\nversion = \"0.1.0\"\nauthors = [\"Hans Elias B. Josephsen <me@hansihe.com>\"]\nedition = \"201"
},
{
"path": "libeir_passes/src/compile_pattern/erlang_pattern_provider.rs",
"chars": 15419,
"preview": "use cranelift_entity::{entity_impl, EntityList, ListPool, PrimaryMap};\nuse libeir_util_pattern_compiler::{ExpandedClause"
},
{
"path": "libeir_passes/src/compile_pattern/lower_cfg.rs",
"chars": 11789,
"preview": "use bumpalo::Bump;\n\nuse libeir_ir::pattern::{PatternClause, PatternContainer, PatternNode};\nuse libeir_ir::FunctionBuild"
},
{
"path": "libeir_passes/src/compile_pattern/mod.rs",
"chars": 5505,
"preview": "use bumpalo::Bump;\nuse hashbrown::HashMap;\n\nuse fnv::FnvBuildHasher;\ntype BFnvHashMap<'bump, K, V> = HashMap<K, V, FnvBu"
},
{
"path": "libeir_passes/src/compile_pattern/tests.rs",
"chars": 1,
"preview": "\n"
},
{
"path": "libeir_passes/src/dummy_location.rs",
"chars": 1,
"preview": "\n"
},
{
"path": "libeir_passes/src/lib.rs",
"chars": 2398,
"preview": "#![deny(warnings)]\n#![feature(allocator_api)]\n\nuse log::{info, trace};\n\nuse libeir_ir::{FunctionBuilder, Module};\n\npub m"
},
{
"path": "libeir_passes/src/naive_inline_closures/mod.rs",
"chars": 3757,
"preview": "use std::collections::BTreeSet;\n\nuse libeir_ir::FunctionBuilder;\nuse libeir_ir::{Block, OpKind};\nuse libeir_ir::{MangleT"
},
{
"path": "libeir_passes/src/naive_inline_closures/tests.rs",
"chars": 2136,
"preview": "use libeir_ir::{parse_function_unwrap, StandardFormatConfig};\n\nuse crate::FunctionPass;\n\n#[test]\nfn inline_basic_functio"
},
{
"path": "libeir_passes/src/simplify_cfg/analyze/call.rs",
"chars": 583,
"preview": "use libeir_ir::Block;\n\nuse super::AnalysisContext;\n\npub(super) fn propagate(ctx: &mut AnalysisContext, block: Block) -> "
},
{
"path": "libeir_passes/src/simplify_cfg/analyze/if_bool.rs",
"chars": 828,
"preview": "use libeir_ir::Block;\n\nuse super::AnalysisContext;\n\npub(super) fn propagate(ctx: &mut AnalysisContext, block: Block) -> "
},
{
"path": "libeir_passes/src/simplify_cfg/analyze/mod.rs",
"chars": 20481,
"preview": "use std::collections::{BTreeMap, BTreeSet, VecDeque};\n\nuse bumpalo::Bump;\n\nuse libeir_util_datastructures::pooled_entity"
},
{
"path": "libeir_passes/src/simplify_cfg/analyze/unpack_value_list.rs",
"chars": 1248,
"preview": "use libeir_ir::{Block, PrimOpKind};\n\nuse super::AnalysisContext;\n\npub(super) fn propagate(ctx: &mut AnalysisContext, blo"
},
{
"path": "libeir_passes/src/simplify_cfg/chain_graph/mod.rs",
"chars": 34707,
"preview": "use log::trace;\n\nuse std::collections::{BTreeMap, BTreeSet};\n\nuse cranelift_entity::{entity_impl, PrimaryMap};\nuse libei"
},
{
"path": "libeir_passes/src/simplify_cfg/chain_graph/synthesis/compound.rs",
"chars": 1441,
"preview": "use log::trace;\n\nuse super::super::ChainGraph;\nuse super::{Synthesis, SynthesisStrategy};\nuse libeir_ir::{Function, Live"
},
{
"path": "libeir_passes/src/simplify_cfg/chain_graph/synthesis/mod.rs",
"chars": 15227,
"preview": "#![allow(dead_code)]\n\nuse std::collections::BTreeMap;\n\nuse super::{Chain, ChainGraph, Node};\nuse cranelift_entity::{enti"
},
{
"path": "libeir_passes/src/simplify_cfg/chain_graph/synthesis/simple.rs",
"chars": 2892,
"preview": "use log::trace;\n\nuse std::collections::BTreeSet;\n\nuse cranelift_entity::EntityList;\nuse libeir_ir::{Function, LiveValues"
},
{
"path": "libeir_passes/src/simplify_cfg/chain_graph/synthesis/single.rs",
"chars": 2401,
"preview": "use super::super::{Chain, ChainGraph};\nuse super::{Synthesis, SynthesisStrategy};\nuse libeir_ir::{Function, LiveValues};"
},
{
"path": "libeir_passes/src/simplify_cfg/chain_graph/synthesis/terminating_target.rs",
"chars": 2348,
"preview": "use log::trace;\n\nuse libeir_ir::{Function, LiveValues};\n\nuse super::super::ChainGraph;\nuse super::single::can_subsitute;"
},
{
"path": "libeir_passes/src/simplify_cfg/mod.rs",
"chars": 6293,
"preview": "#![warn(warnings)]\n\nuse std::collections::BTreeMap;\n\nuse log::{debug, trace};\n\nuse bumpalo::Bump;\nuse fnv::FnvBuildHashe"
},
{
"path": "libeir_passes/src/simplify_cfg/rewrite.rs",
"chars": 12202,
"preview": "use log::trace;\n\nuse std::collections::BTreeMap;\n\nuse libeir_ir::{Block, FunctionBuilder, Value};\nuse libeir_ir::{Mangle"
},
{
"path": "libeir_passes/src/simplify_cfg/tests.rs",
"chars": 23638,
"preview": "use super::SimplifyCfgPass;\nuse crate::FunctionPass;\n\nuse libeir_ir::{parse_function_map_unwrap, parse_function_unwrap, "
},
{
"path": "libeir_passes/src/util.rs",
"chars": 1580,
"preview": "use std::collections::{BTreeMap, BTreeSet};\n\n#[derive(Debug)]\npub struct EdgeSet<T: Copy + Ord>(pub BTreeMap<T, T>);\nimp"
},
{
"path": "libeir_passes/src/validate.rs",
"chars": 669,
"preview": "use super::FunctionPass;\n\nuse libeir_ir::{FunctionBuilder, ValidationError};\n\nuse log::error;\n\npub struct ValidatePass {"
},
{
"path": "libeir_syntax_core/Cargo.toml",
"chars": 355,
"preview": "[package]\nname = \"libeir_syntax_core\"\nversion = \"0.1.0\"\nauthors = [\"Hans Elias B. Josephsen <me@hansihe.com>\"]\nedition ="
},
{
"path": "libeir_syntax_core/build.rs",
"chars": 418,
"preview": "//extern crate peg; \nextern crate lalrpop;\n\nfn main() {\n lalrpop::Configuration::new()\n "
},
{
"path": "libeir_syntax_core/src/ast.rs",
"chars": 5188,
"preview": "use eir::{ Atom, Variable };\n\n#[derive(Debug, Copy, Clone)]\npub enum MapExactAssoc {\n Exact,\n Assoc,\n}\n\n#[derive(D"
},
{
"path": "libeir_syntax_core/src/lexer.rs",
"chars": 17982,
"preview": "use regex::Regex;\nuse std::str::CharIndices;\nuse lazy_static::lazy_static;\n\nlazy_static! {\n static ref TEST: Regex = "
},
{
"path": "libeir_syntax_core/src/lib.rs",
"chars": 92,
"preview": "pub use eir::Atom;\nuse eir::FunctionIdent;\n\nmod lexer;\nmod parser;\nmod ast;\nmod lower_hir;\n\n"
},
{
"path": "libeir_syntax_core/src/lower_hir.rs",
"chars": 14223,
"preview": "use ::std::collections::HashSet;\n\nuse ::{ Atom };\nuse ::ir::{ Module, AVariable, AFunctionName, FunctionDefinition,\n "
},
{
"path": "libeir_syntax_core/src/parser/grammar.lalrpop",
"chars": 9736,
"preview": "//-*- mode: rust -*-\n\nuse crate::ast::{ Module, Annotated, FunctionName, Constant,\nFunction, FunctionDefinition, Express"
},
{
"path": "libeir_syntax_core/src/parser/grammar.rs",
"chars": 668295,
"preview": "// auto-generated: \"lalrpop 0.16.3\"\n// sha256: dc56de9177595febc2b12f8c47a9639b9cb9f823fc7527e3133dcd8cafc3efb\nuse crate"
},
{
"path": "libeir_syntax_core/src/parser/mod.rs",
"chars": 400,
"preview": "use crate::ast::{ Annotated, Module };\nuse crate::lexer::{ Tokenizer, Tok };\n\nmod grammar;\n\npub fn parse<'input>(text: &"
},
{
"path": "libeir_syntax_erl/.gitignore",
"chars": 30,
"preview": "/target\n**/*.rs.bk\nCargo.lock\n"
},
{
"path": "libeir_syntax_erl/Cargo.toml",
"chars": 1219,
"preview": "[package]\nname = \"libeir_syntax_erl\"\nversion = \"0.1.0\"\nauthors = [\"Paul Schoenfelder <paulschoenfelder@gmail.com>\", \"Luk"
},
{
"path": "libeir_syntax_erl/build.rs",
"chars": 246,
"preview": "extern crate lalrpop;\n\nfn main() {\n lalrpop::Configuration::new()\n .use_cargo_dir_conventions()\n .proce"
},
{
"path": "libeir_syntax_erl/src/abstr/lower.rs",
"chars": 32466,
"preview": "use libeir_diagnostics::SourceSpan;\nuse libeir_intern::Ident;\nuse libeir_ir::ToPrimitive;\nuse libeir_ir::binary::BinaryE"
},
{
"path": "libeir_syntax_erl/src/abstr/mod.rs",
"chars": 59,
"preview": "mod lower;\npub use lower::lower;\n\n#[cfg(test)]\nmod test {}\n"
},
{
"path": "libeir_syntax_erl/src/evaluator.rs",
"chars": 11608,
"preview": "use std::cmp::Ordering;\nuse std::collections::BTreeMap;\nuse std::hash::{Hash, Hasher};\n\nuse snafu::{ResultExt, Snafu};\n\n"
},
{
"path": "libeir_syntax_erl/src/lexer/errors.rs",
"chars": 3731,
"preview": "use std::hash::{Hash, Hasher};\n\nuse snafu::Snafu;\n\nuse libeir_diagnostics::{Diagnostic, Label, SourceIndex, SourceSpan, "
},
{
"path": "libeir_syntax_erl/src/lexer/lexer.rs",
"chars": 30335,
"preview": "use std::ops::Range;\nuse std::str::FromStr;\n\nuse libeir_diagnostics::{ByteOffset, SourceIndex, SourceSpan};\n\nuse libeir_"
},
{
"path": "libeir_syntax_erl/src/lexer/mod.rs",
"chars": 695,
"preview": "//! A fairly basic lexer for Erlang\n\npub use libeir_intern::symbol::{symbols, SYMBOL_TABLE};\npub use libeir_intern::symb"
},
{
"path": "libeir_syntax_erl/src/lexer/token.rs",
"chars": 17576,
"preview": "use std::convert::TryFrom;\nuse std::fmt;\nuse std::hash::{Hash, Hasher};\nuse std::mem;\n\nuse libeir_diagnostics::{SourceIn"
},
{
"path": "libeir_syntax_erl/src/lib.rs",
"chars": 920,
"preview": "//#![deny(warnings)]\n#![feature(trait_alias, or_patterns, never_type)]\n\nmod abstr;\nmod evaluator;\nmod lexer;\nmod lower;\n"
},
{
"path": "libeir_syntax_erl/src/lower/errors.rs",
"chars": 9346,
"preview": "use libeir_diagnostics::{Diagnostic, Label, SourceIndex, SourceSpan, ToDiagnostic};\n\nuse crate::parser::binary::TypeName"
},
{
"path": "libeir_syntax_erl/src/lower/exception_handler_stack.rs",
"chars": 1419,
"preview": "use libeir_diagnostics::SourceSpan;\nuse libeir_ir::{Block, FunctionBuilder, Value};\n\npub struct ExceptionHandlerStack {\n"
},
{
"path": "libeir_syntax_erl/src/lower/expr/binary.rs",
"chars": 6231,
"preview": "pub use libeir_ir::binary::{BinaryEntrySpecifier, Endianness};\nuse libeir_ir::{\n operation::binary_construct::{\n "
},
{
"path": "libeir_syntax_erl/src/lower/expr/binary_expr.rs",
"chars": 5514,
"preview": "use libeir_ir::{Block as IrBlock, FunctionBuilder, Value as IrValue};\n\nuse libeir_intern::{Ident, Symbol};\n\nuse crate::p"
},
{
"path": "libeir_syntax_erl/src/lower/expr/case.rs",
"chars": 5089,
"preview": "use libeir_ir::operation::case::Case as CaseOp;\nuse libeir_ir::{Block as IrBlock, FunctionBuilder, Value as IrValue};\n\nu"
},
{
"path": "libeir_syntax_erl/src/lower/expr/catch.rs",
"chars": 9984,
"preview": "use libeir_ir::operation::case::{Case, CaseBuilder};\nuse libeir_ir::{Block as IrBlock, FunctionBuilder, Value as IrValue"
},
{
"path": "libeir_syntax_erl/src/lower/expr/comprehension.rs",
"chars": 15035,
"preview": "use snafu::Snafu;\n\nuse libeir_ir::binary::BinaryEntrySpecifier;\nuse libeir_ir::constant::NilTerm;\nuse libeir_ir::operati"
},
{
"path": "libeir_syntax_erl/src/lower/expr/literal.rs",
"chars": 1510,
"preview": "use libeir_ir::constant::{AtomTerm, BinaryTerm, Const, ConstantContainer, NilTerm};\nuse libeir_ir::{Block as IrBlock, Fu"
},
{
"path": "libeir_syntax_erl/src/lower/expr/map.rs",
"chars": 2786,
"preview": "use libeir_ir::{\n constant::EmptyMap, Block as IrBlock, FunctionBuilder, MapPutUpdate, Value as IrValue,\n};\n\nuse libe"
},
{
"path": "libeir_syntax_erl/src/lower/expr/mod.rs",
"chars": 14695,
"preview": "use libeir_ir::constant::NilTerm;\nuse libeir_ir::operation::case::Case;\nuse libeir_ir::{Block as IrBlock, FunctionBuilde"
},
{
"path": "libeir_syntax_erl/src/lower/expr/receive.rs",
"chars": 4438,
"preview": "use libeir_intern::Ident;\nuse libeir_ir::{\n operation::case::Case,\n operation::receive::{ReceiveDone, ReceiveStart"
},
{
"path": "libeir_syntax_erl/src/lower/expr/record.rs",
"chars": 5982,
"preview": "use libeir_diagnostics::SourceSpan;\nuse libeir_ir::{BinOp as IrBinOp, Block as IrBlock, FunctionBuilder, Value as IrValu"
},
{
"path": "libeir_syntax_erl/src/lower/mod.rs",
"chars": 10917,
"preview": "use std::sync::Arc;\n\nuse libeir_ir::operation::case::Case;\nuse libeir_ir::{\n Block as IrBlock, FunctionBuilder, IntoV"
},
{
"path": "libeir_syntax_erl/src/lower/pattern/mod.rs",
"chars": 8868,
"preview": "use std::collections::HashMap;\n\nuse libeir_diagnostics::SourceSpan;\nuse libeir_ir::pattern::{PatternClause, PatternConta"
},
{
"path": "libeir_syntax_erl/src/lower/pattern/tree/from_expr.rs",
"chars": 12956,
"preview": "use either::Either;\nuse std::convert::TryInto;\n\nuse cranelift_entity::EntityList;\n\nuse libeir_ir::{\n AtomicTerm, BigI"
},
{
"path": "libeir_syntax_erl/src/lower/pattern/tree/lower.rs",
"chars": 6577,
"preview": "use std::collections::{BTreeMap, HashMap};\n\nuse either::Either;\n\nuse libeir_intern::Ident;\nuse libeir_ir::pattern::Patte"
},
{
"path": "libeir_syntax_erl/src/lower/pattern/tree/merge.rs",
"chars": 7717,
"preview": "//! Merges And nodes in the pattern tree\n\nuse std::collections::{BTreeMap, BTreeSet};\n\nuse libeir_ir::FunctionBuilder;\n\n"
},
{
"path": "libeir_syntax_erl/src/lower/pattern/tree/mod.rs",
"chars": 3969,
"preview": "//! Small IR used to do linting and transformations on patterns\n//! before they are lowered to Eir.\n\nuse std::collection"
},
{
"path": "libeir_syntax_erl/src/lower/pattern/tree/promote_values.rs",
"chars": 9107,
"preview": "//! Resolves values, promotes nodes to values, applies constraints\n\nuse either::Either;\nuse std::collections::{BTreeSet,"
},
{
"path": "libeir_syntax_erl/src/lower/scope.rs",
"chars": 5236,
"preview": "use std::collections::{HashMap, HashSet};\n\nuse libeir_util_datastructures::hashmap_stack::HashMapStack;\n\nuse libeir_ir::"
},
{
"path": "libeir_syntax_erl/src/lower/tests.rs",
"chars": 2874,
"preview": "use std::sync::Arc;\n\nuse crate::ast::*;\nuse crate::*;\n\nuse crate::lower::lower_module;\nuse crate::parser::ParseConfig;\n\n"
},
{
"path": "libeir_syntax_erl/src/parser/ast/attributes.rs",
"chars": 7801,
"preview": "use std::fmt;\nuse std::hash::{Hash, Hasher};\n\nuse libeir_diagnostics::SourceSpan;\n\nuse super::{Expr, Ident, Name, Partia"
},
{
"path": "libeir_syntax_erl/src/parser/ast/expr.rs",
"chars": 22145,
"preview": "use std::cmp::Ordering;\n\nuse libeir_diagnostics::SourceSpan;\nuse libeir_util_number::{Float, Integer, Number};\nuse libei"
},
{
"path": "libeir_syntax_erl/src/parser/ast/functions.rs",
"chars": 19011,
"preview": "use std::cmp::Ordering;\nuse std::fmt;\nuse std::hash::{Hash, Hasher};\n\nuse libeir_diagnostics::{Diagnostic, Label, Source"
},
{
"path": "libeir_syntax_erl/src/parser/ast/mod.rs",
"chars": 3042,
"preview": "mod attributes;\nmod expr;\nmod functions;\nmod module;\nmod types;\n\nuse libeir_diagnostics::{SourceIndex, SourceSpan};\n\npub"
},
{
"path": "libeir_syntax_erl/src/parser/ast/module.rs",
"chars": 66563,
"preview": "use std::collections::btree_map::Entry;\nuse std::collections::BTreeMap;\nuse std::collections::{HashMap, HashSet};\n\nuse l"
},
{
"path": "libeir_syntax_erl/src/parser/ast/types.rs",
"chars": 9654,
"preview": "use std::collections::HashSet;\n\nuse lazy_static::lazy_static;\n\nuse libeir_diagnostics::SourceSpan;\nuse libeir_util_numbe"
},
{
"path": "libeir_syntax_erl/src/parser/binary.rs",
"chars": 9938,
"preview": "use snafu::Snafu;\npub use libeir_ir::binary::{BinaryEntrySpecifier, Endianness};\nuse libeir_diagnostics::{SourceSpan, To"
},
{
"path": "libeir_syntax_erl/src/parser/errors.rs",
"chars": 4245,
"preview": "use std::convert::From;\n\nuse libeir_diagnostics::*;\nuse libeir_util_parse::SourceError;\nuse snafu::Snafu;\n\nuse crate::le"
},
{
"path": "libeir_syntax_erl/src/parser/grammar.lalrpop",
"chars": 38025,
"preview": "//-*- mode: rust -*-\nuse libeir_diagnostics::*;\n\nuse libeir_util_number::{Integer, ToPrimitive, Float};\n\nuse libeir_ir::"
},
{
"path": "libeir_syntax_erl/src/parser/macros.rs",
"chars": 6549,
"preview": "/// Construct a keyword list AST from a list of expressions, e.g.:\n///\n/// kwlist!(tuple!(atom!(key), var!(Value)))\n"
},
{
"path": "libeir_syntax_erl/src/parser/mod.rs",
"chars": 28584,
"preview": "/// Used in the grammar for easy span creation\nmacro_rules! span {\n ($l:expr, $r:expr) => {\n SourceSpan::new($"
},
{
"path": "libeir_syntax_erl/src/preprocessor/directive.rs",
"chars": 6124,
"preview": "use std::fmt;\n\nuse libeir_diagnostics::SourceSpan;\n\nuse crate::lexer::{AtomToken, LexicalToken, SymbolToken, Token};\n\nus"
},
{
"path": "libeir_syntax_erl/src/preprocessor/directives.rs",
"chars": 29327,
"preview": "use std::collections::VecDeque;\nuse std::fmt;\nuse std::path::{Component, PathBuf};\n\nuse snafu::{ResultExt, Snafu};\n\nuse "
},
{
"path": "libeir_syntax_erl/src/preprocessor/errors.rs",
"chars": 11748,
"preview": "use std;\nuse std::path::PathBuf;\n\nuse itertools::Itertools;\nuse snafu::Snafu;\n\nuse libeir_diagnostics::*;\nuse libeir_int"
},
{
"path": "libeir_syntax_erl/src/preprocessor/macros.rs",
"chars": 6544,
"preview": "use std::collections::HashMap;\nuse std::fmt;\n\nuse libeir_diagnostics::SourceSpan;\n\nuse crate::lexer::{DelayedSubstitutio"
},
{
"path": "libeir_syntax_erl/src/preprocessor/mod.rs",
"chars": 593,
"preview": "mod directive;\nmod errors;\n//mod evaluator;\nmod macros;\nmod preprocessor;\nmod token_reader;\nmod token_stream;\n\npub mod d"
},
{
"path": "libeir_syntax_erl/src/preprocessor/preprocessor.rs",
"chars": 19698,
"preview": "use std::collections::{BTreeMap, HashMap, VecDeque};\nuse std::convert::TryFrom;\nuse std::path::PathBuf;\nuse std::sync::A"
},
{
"path": "libeir_syntax_erl/src/preprocessor/token_reader.rs",
"chars": 10230,
"preview": "use std::collections::VecDeque;\nuse std::convert::TryFrom;\nuse std::fmt::Display;\nuse std::fs;\nuse std::path::Path;\nuse "
},
{
"path": "libeir_syntax_erl/src/preprocessor/token_stream.rs",
"chars": 1210,
"preview": "use std::collections::VecDeque;\n\nuse crate::lexer::{Lexed, Lexer};\nuse libeir_util_parse::Source;\n\npub struct TokenStrea"
},
{
"path": "libeir_syntax_erl/src/preprocessor/types.rs",
"chars": 11323,
"preview": "use std::fmt;\nuse std::hash::{Hash, Hasher};\nuse std::mem;\n\nuse libeir_diagnostics::SourceSpan;\n\nuse crate::lexer::{Atom"
},
{
"path": "libeir_syntax_erl/src/util/binary/mod.rs",
"chars": 35,
"preview": "mod r#static;\npub use r#static::*;\n"
}
]
// ... and 139 more files (download for full content)
About this extraction
This page contains the full source code of the eirproject/eir GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 339 files (3.2 MB), approximately 842.8k tokens, and a symbol index with 3985 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.