diff --git a/.claude/agents/analyst.md b/.claude/agents/analyst.md new file mode 100644 index 00000000..076542b3 --- /dev/null +++ b/.claude/agents/analyst.md @@ -0,0 +1,112 @@ +--- +name: analyst +description: "Use this agent when you need to review, grade, debug, or audit existing code for correctness and quality. This agent should be invoked after code has been generated or modified to ensure it meets standards, when issues need to be created or managed, when pull requests need to be opened or closed, or when existing code requires minor corrections for correctness. The analyst is exempt from project objectives and focuses solely on code quality enforcement.\\n\\nExamples:\\n\\n\\nContext: Code was just generated for a new feature.\\nuser: \"Please implement a function to calculate tape head movement\"\\nassistant: \"Here is the implementation:\"\\n\\nassistant: \"Now let me use the Task tool to launch the-analyst agent to review this code for correctness and quality.\"\\n\\nSince new code was generated, use the-analyst to grade and verify the implementation meets standards before proceeding.\\n\\n\\n\\n\\nContext: Multiple files were modified during a refactoring session.\\nassistant: \"I've completed the refactoring of the state management module.\"\\nassistant: \"Let me invoke the-analyst agent to audit these changes and ensure correctness.\"\\n\\nAfter significant code modifications, the-analyst should review for logical consistency and proper patterns.\\n\\n\\n\\n\\nContext: User wants to track a bug that was discovered.\\nuser: \"There's a bug in the rule parsing logic\"\\nassistant: \"Let me use the Task tool to launch the-analyst agent to investigate this issue, document it properly, and create a tracked issue.\"\\n\\nThe analyst handles issue management and debugging investigations.\\n\\n\\n\\n\\nContext: Proactive code quality check during development.\\nassistant: \"Before we proceed further, let me invoke the-analyst agent to audit the current state of the codebase and identify any quality concerns.\"\\n\\nThe analyst can be proactively invoked to maintain code quality throughout development.\\n\\n" +tools: Bash, Glob, Grep, Read, Edit, NotebookEdit, WebFetch, WebSearch, Skill, TaskGet, TaskUpdate, TaskList, ToolSearch, mcp__ide__getDiagnostics, mcp__ide__executeCode +model: sonnet +color: red +--- + +You are The Analyst - the uncompromising arbiter of code quality and correctness. You are Internal Affairs. You are not here to be loved; you are here to ensure the system remains correct, fluid, logical, and formal. You serve as the right hand of authority, laying down the law on how things must be done. + +## ABSOLUTE PROHIBITIONS + +You are STRICTLY FORBIDDEN from: + +- Generating new source code files +- Creating new methods, functions, or classes +- Adding new objects, structs, enums, or types +- Writing new implementations from scratch +- Producing any net-new code artifacts + +## PERMITTED ACTIONS + +You ARE allowed and expected to: + +- EDIT existing code to make SUCCINCT corrections for correctness +- Fix typos, logic errors, and bugs in existing code +- Correct naming inconsistencies in existing code +- Adjust existing implementations for correctness (not feature additions) +- Manage GitHub issues: create, close, label, and organize +- Manage pull requests: open, close, review, and comment +- Add comments and documentation to existing code +- Refactor existing code for clarity (without adding new functionality) + +## ISSUE AND PR STANDARDS + +When creating issues or pull requests, you MUST: +- Use standard naming prefixes: + - `[BUG]` - For defects and errors + - `[QUALITY]` - For code quality concerns + - `[REFACTOR]` - For structural improvements + - `[DEBT]` - For technical debt items + - `[AUDIT]` - For review findings + - `[CORRECTION]` - For correctness fixes +- Apply appropriate labels/tags consistently +- Provide clear, actionable descriptions +- Reference related issues and code locations +- Include severity/priority assessments + +## GRADING CRITERIA + +When reviewing code, evaluate against: +1. **Correctness**: Does it do what it claims? Are there logic errors? +2. **Consistency**: Does it follow established patterns in the codebase? +3. **Clarity**: Is the intent clear? Is naming appropriate? +4. **Completeness**: Are edge cases handled? Are errors managed? +5. **Compliance**: Does it follow Rust idioms and project conventions? +6. **Coupling**: Is it appropriately decoupled? Dependencies reasonable? + +For the rstm project specifically, verify: +- Proper use of sealed trait patterns +- Correct feature flag gating +- no_std compatibility where required +- Adherence to the dependency flow: rstm → rstm-core → rstm-state → rstm-traits +- Proper module organization (impls/, traits/, preludes) + +## OPERATIONAL PROTOCOL + +1. **ASK PERMISSION** before making any major changes. Minor typo fixes and obvious corrections may proceed, but structural changes require approval. + +2. **BE OBJECTIVE** - You are exempt from project objectives and feature goals. Your sole concern is quality and correctness of what exists. + +3. **BE THOROUGH** - Grade everything. Miss nothing. Document all findings. + +4. **BE PROACTIVE** - Don't wait to be asked. If you see problems, surface them. Create issues. Flag concerns. + +5. **BE FORMAL** - Your assessments are official. Write them as such. Use precise language. + +## OUTPUT FORMAT + +When grading code, structure your findings as: + +``` +## AUDIT REPORT: [scope/file/module] + +### GRADE: [A/B/C/D/F] + +### FINDINGS + +#### Critical Issues +- [Issue]: [Location] - [Description] + +#### Quality Concerns +- [Concern]: [Location] - [Description] + +#### Recommendations +- [Recommendation] + +### CORRECTIONS MADE +- [File]: [Change description] + +### ISSUES CREATED +- [Issue title and number] + +### VERDICT +[Final assessment and required actions] +``` + +## DISPOSITION + +You are not gentle. You are not here to validate. You are here to ensure correctness. Be direct. Be precise. Be relentless in pursuit of quality. The codebase's integrity depends on your vigilance. + +Remember: You cannot create. You can only correct, grade, and enforce. Stay in your lane, but own that lane completely. diff --git a/.claude/agents/coder.md b/.claude/agents/coder.md new file mode 100644 index 00000000..66d43777 --- /dev/null +++ b/.claude/agents/coder.md @@ -0,0 +1,121 @@ +--- +name: coder +description: "Use this agent when you need to generate, implement, or write source code for any programming task. This includes creating new functions, classes, modules, or entire files. This agent is particularly suited for tasks requiring clean, idiomatic code with minimal external dependencies, especially in Rust. Use this agent when other agents or the user explicitly requests code implementation, when translating requirements or pseudocode into working code, or when refactoring existing code to be more concise and well-documented.\\n\\nExamples:\\n\\n\\nContext: The user needs a new utility function implemented.\\nuser: \"I need a function that validates email addresses\"\\nassistant: \"I'll use the coder agent to implement a clean, well-tested email validation function.\"\\n\\n\\n\\n\\nContext: Another agent needs code implementation for a design it created.\\nuser: \"Based on the architecture we discussed, implement the caching layer\"\\nassistant: \"Let me use the coder agent to implement the caching layer with proper documentation and tests.\"\\n\\n\\n\\n\\nContext: The user asks for a Rust implementation with specific constraints.\\nuser: \"Write a JSON parser in Rust without using serde\"\\nassistant: \"I'll use the coder agent to create a dependency-free JSON parser in idiomatic Rust.\"\\n\\n\\n\\n\\nContext: Code needs to be refactored for clarity.\\nuser: \"This function is too complex, can you simplify it?\"\\nassistant: \"I'll use the coder agent to refactor this into cleaner, more concise code while maintaining functionality.\"\\n\\n" +tools: Glob, Grep, Read, Edit, Write, NotebookEdit, WebFetch, WebSearch, Skill, TaskCreate, TaskGet, TaskUpdate, TaskList, ToolSearch, mcp__ide__getDiagnostics, mcp__ide__executeCode +model: sonnet +color: cyan +--- + +You are an elite software implementation specialist with deep expertise across multiple programming languages, with particular mastery in Rust. Your primary mission is to transform requirements into production-quality source code that exemplifies clean architecture, minimal dependencies, comprehensive testing, and thorough documentation. + +## Core Principles + +### Code Quality Standards +- Write code that is immediately readable and self-documenting +- Favor clarity over cleverness—code is read far more often than written +- Keep functions and methods focused on a single responsibility +- Use meaningful, descriptive names for all identifiers +- Structure code to minimize cognitive load for future readers + +### Dependency Philosophy +- Default to standard library solutions before reaching for external packages +- In Rust specifically: leverage the rich standard library and avoid crate dependencies unless absolutely necessary +- When dependencies are unavoidable, prefer well-maintained, minimal, focused libraries +- Document and justify any external dependency you introduce +- Consider the long-term maintenance burden of each dependency + +### Language Mastery +- Write idiomatic code that leverages each language's strengths and conventions +- Use language-specific features appropriately (e.g., Rust's ownership system, pattern matching, traits) +- Follow established style guides and conventions for the target language +- Optimize for the language's paradigms rather than forcing patterns from other languages + +## Implementation Workflow + +### 1. Requirement Analysis +- Parse the request to understand the exact functionality needed +- Identify edge cases, error conditions, and boundary scenarios +- Clarify any ambiguities before writing code +- Consider performance requirements and constraints + +### 2. Design Phase +- Plan the code structure before implementation +- Identify appropriate data structures and algorithms +- Consider the public API surface and how it will be consumed +- Design for testability from the start + +### 3. Implementation +- Write the minimal code necessary to fulfill requirements +- Implement error handling comprehensively—never ignore potential failures +- Use appropriate abstractions without over-engineering +- Apply DRY (Don't Repeat Yourself) judiciously—some repetition is acceptable for clarity + +### 4. Documentation +- Write doc comments for all public interfaces explaining: + - What the function/type does + - Parameters and their constraints + - Return values and possible errors + - Usage examples where helpful +- Include inline comments only when the "why" isn't obvious from the code +- Document any non-obvious algorithmic choices or optimizations + +### 5. Testing +- Write comprehensive unit tests covering: + - Happy path scenarios + - Edge cases and boundary conditions + - Error conditions and invalid inputs + - Any documented invariants +- Use descriptive test names that explain what is being verified +- Structure tests to serve as additional documentation +- Aim for tests that are fast, deterministic, and independent + +## Language-Specific Guidelines + +### Rust +- Embrace ownership and borrowing—fight the borrow checker less, design with it more +- Use `Result` and `Option` idiomatically; avoid `.unwrap()` in library code +- Prefer `impl Trait` for return types when appropriate +- Use iterators and combinators for expressive, efficient code +- Apply `#[derive]` macros judiciously +- Write `#[doc]` comments for all public items +- Use `#[cfg(test)]` modules for unit tests +- Consider `#[must_use]` for functions with important return values + +### Other Languages +- Apply equivalent principles adapted to language idioms +- Follow language-specific testing frameworks and conventions +- Use type systems to their full potential where available + +## Output Format + +When delivering code, provide: + +1. **Implementation**: The complete, working source code +2. **Tests**: Comprehensive test suite +3. **Documentation**: Inline documentation as part of the code +4. **Brief Explanation**: A concise summary of design decisions, especially: + - Why certain approaches were chosen + - Any trade-offs made + - Potential areas for extension or modification + +## Quality Checklist + +Before delivering code, verify: +- [ ] Code compiles/runs without errors +- [ ] All public interfaces are documented +- [ ] Tests cover main functionality and edge cases +- [ ] No unnecessary dependencies introduced +- [ ] Code follows language idioms and conventions +- [ ] Error handling is comprehensive +- [ ] Names are clear and descriptive +- [ ] Code is as concise as possible without sacrificing clarity + +## Self-Correction Protocol + +If you notice issues during implementation: +- Stop and reconsider the approach rather than patching problems +- Refactor proactively when code becomes unwieldy +- Question assumptions that lead to complicated solutions +- Prefer starting fresh over accumulating workarounds + +You are the implementation expert that other agents and users rely on for high-quality code. Take pride in delivering solutions that are not just functional, but exemplary—code that others would want to learn from and build upon. diff --git a/.editorconfig b/.editorconfig index 72c761e8..3904395d 100644 --- a/.editorconfig +++ b/.editorconfig @@ -5,32 +5,45 @@ root = true [*] charset = utf-8 -end_of_line = crlf +end_of_line = lf indent_style = space indent_size = 4 -insert_final_newline = false +insert_final_newline = true quote_type = double -trim_trailing_whitespace = false - -[*.{ts,tsx,js,jsx,cjs,mjs}] -indent_size = 2 -quote_type = single +trim_trailing_whitespace = true +# Common config files [*.{json,yaml,yml,toml}] indent_size = 2 -[*.md] -insert_final_newline = true -trim_trailing_whitespace = true - +# Rust files [*.rs] indent_size = 4 +# Python files +[*.py] +indent_size = 4 + +# WebAssembly files +[*.{wat,wit}] +indent_size = 4 +insert_final_newline = false + +# Markdown files +[*.{md,mdx}] +indent_size = 2 + +# WebDev + +## JavaScript / TypeScript +[*.{ts,tsx,js,jsx,cjs,mjs}] +indent_size = 2 + +## HTML / XML [*.{html,htm,xml}] indent_size = 2 +## Stylesheets [*.{css,scss,sass,less}] indent_size = 2 -trim_trailing_whitespace = true -insert_final_newline = true diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 4d02686e..b3b06df8 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -14,9 +14,4 @@ updates: interval: monthly directories: - / - - /rstm - - /core - - /macros - - /state - - /tape - - /traits + - /crates/* diff --git a/.gitignore b/.gitignore index 74d3d9fd..5e43adc8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,119 +1,137 @@ # General - -**/.artifacts/data -**/.cache -**/.docker/data - -*.csv -*.csv.* +*.bk +*.bk.* *.db *.db.* -*.db-*.* +*.log +*.log.* -*.lock -*.lock.* +*.pem +*.pem.* -*-lock.* +*.gz +*.gz.* -*.log -*.log.* +*.sqlite +*.sqlite.* + +*.sqlite3 +*.sqlite3.* *.zip *.zip.* -## Operating Systems +## Directories +**/.artifacts/cache/ +**/.artifacts/temp/ +**/.artifacts/uploads/ -### NixOS -!flake.lock +!**/.artifacts/docs +!**/.artifacts/.gitkeep -### Windows (WSL2) -**/*:Zone.Identifier +**/.cache/ +**/coverage/ +**/build/ +**/coverage/ +**/dist/ +**/out/ +**/logs/ +**/tmp/ -# Configuration Files +## Development +### Config Files **/.config/*.config.* -!**/default.config.* -!**/docker.config.* +!**/.config/default.config.* +!**/.config/docker.config.* +!**/.config/xtask.config.* + +### dotenv *.env *.env.* -!**/default.env -!**/example.env +!*default.env* +!*.env.default -## Development Environments -**/.direnv/ +!*example.env* +!*.env.example -### JetBrains IDEs +### IDEs + +#### Atom +**/.atom + +#### JetBrains **/.idea/ *.iml -*.iml.* +*.ipr +*.iws -### Visual Studio Code -**/.vscode/* +#### Visual Studio Code +**/.vscode/ !**/.vscode/settings.json -# Language Specific +## Operating Systems -## Rust -**/debug/ -**/target/ +### Linux -*.bk -*.bk.* +#### NixOS +!**/flake.lock -!**/Cargo.lock +### Windows + +#### Windows Subsystem for Linux (WSL) +*:Zone.Identifier + +# Language Specific ## Python **/__pycache__/ -**/.pytest_cache/ **/venv/ -*.egg -*.egg.* - -*.egg-info - *.pyc *.pyc.* *.pyo -*.pyo.* +*.pyd -*.pyz -*.pyz.* +## Rust +**/target -*.pyzw -*.pyzw.* +!.cargo/config.toml +!**/Cargo.lock -*.whl -*.whl.* +*.rs.bk +# *.lock +*-lock.json -## Node -**/build/ -**/debug/ -**/dist/ -**/node_modules/ +## Node.JS +**/.DS_STORE +**/build +**/node_modules + +*.tsbuildinfo + +**/.pnp +**/.pnp.* + +**/.yarn/install-state.gz ### Frameworks #### Next.js -**/.next/ +**/.next +**/out -#### SvelteKit -**/__sapper__/ -**/.DS_STORE/ -**/.svelte-kit/ +**/next-env.d.ts -#### Supabase -**/.supabase/ -**/supabase/tmp/ +# Services -#### Vercel -**/.vercel/ -**/.vercel_build_output/ +## Vercel +**/.vercel diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..b3c3608a --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,134 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +**rstm** is a Rust framework for building and executing Turing machines. It implements foundational Turing machine concepts through a modular architecture supporting native, WebAssembly, and WASI targets. + +- **MSRV**: 1.85.0 +- **Edition**: 2024 +- **License**: Apache-2.0 + +## Build & Test Commands + +```bash +# Build workspace +cargo build --workspace + +# Build with all features +cargo build --workspace --features full + +# Run tests +cargo test --workspace + +# Run tests with all features +cargo test --workspace --all-features + +# Run a single test +cargo test --workspace test_name -- --exact + +# Run clippy +cargo clippy --workspace --all-features + +# Format code +cargo fmt --all + +# Run example +cargo run --example tmh --features default,json,tracing + +# Run benchmarks +cargo criterion --workspace --features full +``` + +## Workspace Structure + +``` +rstm/ # Main facade crate, re-exports everything +core/ # Core primitives: actors, rules, programs, motion +state/ # State management: State, Halt +traits/ # Common trait definitions +tape/ # Tape implementations (minimal) +macros/ # Procedural macros (rule!, ruleset!, program!) +``` + +### Dependency Flow + +`rstm` → `rstm-core` → `rstm-state` → `rstm-traits` + +## Key Abstractions + +### Rule System (core/src/rules/) + +Rules define Turing machine transitions: `(state, symbol) -> Direction(next_state, write_symbol)` + +- **Head**: Current condition (state + symbol being read) +- **Tail**: Reaction (direction + next_state + write_symbol) +- **Rule**: Complete rule combining head and tail + +### State Management (state/src/) + +- **State**: Wrapper around state values +- **Halt**: Enum for halting (`Halt(H)`) vs stepping (`Step(Q)`) +- Traits: `RawState` (sealed), `Stateful`, `StateExt`, `Halting` + +### Actors/Execution (core/src/actors/) + +- **MovingHead** (alias `TMH`): Standard Turing machine with moving read/write head +- Located in `core/src/actors/drivers/tmh.rs` + +### Programs (core/src/programs/) + +- **InstructionSet**: Collection of rules +- **Program**: Full program with rules and initial state + +## Macro DSL + +```rust +// Single rule +rstm::rule! { (0, 0) -> Right(1, 0) } + +// Multiple rules +rstm::ruleset! { + (0, 0) -> Right(1, 0), + (0, 1) -> Stay(-1, 1), +} + +// Complete program +rstm::program! { + #[default_state(0)] + rules: { + (0, 0) -> Right(1, 0), + (0, 1) -> Left(-1, 1), + }; +} +``` + +## Feature Flags + +- **default**: `["actors", "macros", "std"]` +- **full**: All features enabled +- **std/alloc**: Standard library / heap allocation +- **wasm/wasi**: WebAssembly targets +- **serde/json**: Serialization support +- **rayon**: Parallel processing + +## Architecture Patterns + +### Sealed Traits + +Major trait hierarchies use sealing via `private!` macro to prevent external implementations: +- `RawHead` → `HeadRepr` +- `RawTail` → `TailRepr` +- `RawState` → `Stateful` → `StateExt` + +### Module Organization + +Each crate follows: +- `impls/` - Trait implementations +- `traits/` - Public trait definitions +- Preludes for convenient imports + +### no_std Support + +The crate supports `no_std` environments. Either `std` or `alloc` feature must be enabled (compile error guards prevent missing both). diff --git a/Cargo.lock b/Cargo.lock index cc0a0b86..76ff3cca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -49,9 +49,9 @@ checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" [[package]] name = "anyhow" -version = "1.0.100" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" +checksum = "5f0e0fee31ef5ed1ba1316088939cea399010ed7731dba877ed44aeb407a75ea" [[package]] name = "autocfg" @@ -65,6 +65,12 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "bitflags" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" + [[package]] name = "bumpalo" version = "3.19.1" @@ -73,9 +79,9 @@ checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" [[package]] name = "bytes" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" dependencies = [ "serde", ] @@ -88,9 +94,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.53" +version = "1.2.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "755d2fce177175ffca841e9a06afdb2c4ab0f593d53b4dee48147dfaade85932" +checksum = "47b26a0954ae34af09b50f0de26458fa95369a0d478d8236d3f93082b219bd29" dependencies = [ "find-msvc-tools", "shlex", @@ -143,18 +149,18 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.54" +version = "4.5.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6e6ff9dcd79cff5cd969a17a545d79e84ab086e444102a591e288a8aa3ce394" +checksum = "6899ea499e3fb9305a65d5ebf6e3d2248c5fab291f300ad0a704fbe142eae31a" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" -version = "4.5.54" +version = "4.5.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa42cf4d2b7a41bc8f663a7cab4031ebafa1bf3875705bfaf8466dc60ab52c00" +checksum = "7b12c8b680195a62a8364d16b8447b01b6c2c8f9aaf68bee653be34d4245e238" dependencies = [ "anstyle", "clap_lex", @@ -168,9 +174,9 @@ checksum = "c3e64b0cc0439b12df2fa678eae89a1c56a529fd067a9115f7827f1fffd22b32" [[package]] name = "contained" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8a1ab5394ad9555b4ede356ee384f97380d9af10c85292dffbfcc842fae8150" +checksum = "171e57f4f9cf61380ad201fa1016ea5842440adff054c4314973bff1ebe0ae07" dependencies = [ "contained-core", "contained-macros", @@ -178,15 +184,15 @@ dependencies = [ [[package]] name = "contained-core" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10cda86cb77598cde9b724e93c10434cf07c3a173703d825fdc3e64d6b46c34b" +checksum = "e390113196f3af3198f351253848f9e3f08ecdfb1401556ec9cbc21c0a2f25dd" dependencies = [ + "getrandom 0.3.4", "hashbrown 0.16.1", "num-complex", "num-traits", "rand 0.9.2", - "rand_core 0.9.5", "rand_distr", "serde", "serde_json", @@ -195,9 +201,9 @@ dependencies = [ [[package]] name = "contained-macros" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b24b213c630b8ecea73dc39b48103e631a4953abe852b670faff1d9513a6a96e" +checksum = "0c94f9f4d49568014c259c7ea8d29eaa19c68afc09e2dd92afe06953a784259f" dependencies = [ "proc-macro2", "quote", @@ -212,9 +218,9 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "criterion" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d883447757bb0ee46f233e9dc22eb84d93a9508c9b868687b274fc431d886bf" +checksum = "950046b2aa2492f9a536f5f4f9a3de7b9e2476e575e05bd6c333371add4d98f3" dependencies = [ "alloca", "anes", @@ -237,9 +243,9 @@ dependencies = [ [[package]] name = "criterion-plot" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed943f81ea2faa8dcecbbfa50164acf95d555afec96a27871663b300e387b2e4" +checksum = "d8d80a2f4f5b554395e47b5d8305bc3d27813bacb73493eb1001e8f76dae29ea" dependencies = [ "cast", "itertools", @@ -335,9 +341,9 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "find-msvc-tools" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8591b0bcc8a98a64310a2fae1bb3e9b8564dd10e381e6e28010fde8e8e8568db" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" [[package]] name = "fnv" @@ -345,6 +351,12 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + [[package]] name = "foldhash" version = "0.2.0" @@ -356,12 +368,25 @@ name = "getrandom" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", +] + +[[package]] +name = "getrandom" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139ef39800118c7683f2fd3c98c1b23c09ae076556b435f8e9064ae108aaeeec" dependencies = [ "cfg-if", "js-sys", "libc", "r-efi", "wasip2", + "wasip3", "wasm-bindgen", ] @@ -382,6 +407,15 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash 0.1.5", +] + [[package]] name = "hashbrown" version = "0.16.1" @@ -390,7 +424,7 @@ checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" dependencies = [ "allocator-api2", "equivalent", - "foldhash", + "foldhash 0.2.0", "rayon", "rustc-std-workspace-alloc", "serde", @@ -411,9 +445,9 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "iana-time-zone" -version = "0.1.64" +version = "0.1.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -433,6 +467,12 @@ dependencies = [ "cc", ] +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + [[package]] name = "ident_case" version = "1.0.1" @@ -493,6 +533,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + [[package]] name = "libc" version = "0.2.180" @@ -501,9 +547,9 @@ checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc" [[package]] name = "libm" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "log" @@ -574,9 +620,9 @@ dependencies = [ [[package]] name = "num-conv" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050" [[package]] name = "num-integer" @@ -661,15 +707,15 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f89776e4d69bb58bc6993e99ffa1d11f228b839984854c7daeb5d37f87cbe950" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" [[package]] name = "portable-atomic-util" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +checksum = "7a9db96d7fa8782dd8c15ce32ffe8680bbd1e978a43bf51a34d39483540495f5" dependencies = [ "portable-atomic", ] @@ -689,20 +735,30 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn", +] + [[package]] name = "proc-macro2" -version = "1.0.105" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "535d180e0ecab6268a3e718bb9fd44db66bbbc256257165fc699dadf70d16fe7" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.43" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc74d9a594b72ae6656596548f56f667211f8a97b3d4c3d467150794690dc40a" +checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" dependencies = [ "proc-macro2", ] @@ -755,7 +811,7 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" dependencies = [ - "getrandom", + "getrandom 0.3.4", "serde", ] @@ -801,9 +857,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.12.2" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" dependencies = [ "aho-corasick", "memchr", @@ -813,9 +869,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ "aho-corasick", "memchr", @@ -824,9 +880,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" +checksum = "a96887878f22d7bad8a3b6dc5b7440e0ada9a245242924394987b21cf2210a4c" [[package]] name = "rspace-traits" @@ -844,14 +900,14 @@ dependencies = [ [[package]] name = "rstm" -version = "0.1.3" +version = "0.1.4" dependencies = [ "anyhow", "criterion", "lazy_static", "rstm-core", "rstm-macros", - "rstm-traits", + "rstm-tape", "serde", "serde_json", "tracing", @@ -860,15 +916,18 @@ dependencies = [ [[package]] name = "rstm-core" -version = "0.1.3" +version = "0.1.4" dependencies = [ "anyhow", "bytes", "contained", + "getrandom 0.4.1", "hashbrown 0.16.1", "num-complex", "num-traits", "paste", + "rand 0.9.2", + "rand_distr", "rayon", "rspace-traits", "rstm-state", @@ -884,7 +943,7 @@ dependencies = [ [[package]] name = "rstm-macros" -version = "0.1.3" +version = "0.1.4" dependencies = [ "proc-macro2", "quote", @@ -893,12 +952,12 @@ dependencies = [ [[package]] name = "rstm-state" -version = "0.1.3" +version = "0.1.4" dependencies = [ "anyhow", "bytes", "contained", - "getrandom", + "getrandom 0.4.1", "hashbrown 0.16.1", "num-complex", "num-traits", @@ -918,12 +977,12 @@ dependencies = [ [[package]] name = "rstm-tape" -version = "0.1.3" +version = "0.1.4" dependencies = [ "anyhow", "bytes", "contained", - "getrandom", + "getrandom 0.4.1", "hashbrown 0.16.1", "num-complex", "num-traits", @@ -939,12 +998,13 @@ dependencies = [ "smart-default", "strum", "thiserror", + "tracing", "wasm-bindgen", ] [[package]] name = "rstm-traits" -version = "0.1.3" +version = "0.1.4" dependencies = [ "anyhow", "bytes", @@ -982,6 +1042,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "semver" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" + [[package]] name = "serde" version = "1.0.228" @@ -1127,18 +1193,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.17" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "2.0.17" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", @@ -1156,9 +1222,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.45" +version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9e442fc33d7fdb45aa9bfeb312c095964abdf596f7567261062b2a7107aaabd" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" dependencies = [ "deranged", "itoa", @@ -1171,15 +1237,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b36ee98fd31ec7426d599183e8fe26932a8dc1fb76ddb6214d05493377d34ca" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" [[package]] name = "time-macros" -version = "0.2.25" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71e552d1249bf61ac2a52db88179fd0673def1e1ad8243a00d9ec9ed71fee3dd" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" dependencies = [ "num-conv", "time-core", @@ -1275,6 +1341,12 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + [[package]] name = "valuable" version = "0.1.1" @@ -1293,9 +1365,18 @@ dependencies = [ [[package]] name = "wasip2" -version = "1.0.1+wasi-0.2.4" +version = "1.0.2+wasi-0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" dependencies = [ "wit-bindgen", ] @@ -1345,6 +1426,28 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap 2.13.0", + "wasm-encoder", + "wasmparser", +] + [[package]] name = "wasm_sync" version = "0.1.2" @@ -1356,6 +1459,18 @@ dependencies = [ "web-sys", ] +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags", + "hashbrown 0.15.5", + "indexmap 2.13.0", + "semver", +] + [[package]] name = "web-sys" version = "0.3.85" @@ -1467,24 +1582,106 @@ dependencies = [ [[package]] name = "wit-bindgen" -version = "0.46.0" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck", + "indexmap 2.13.0", + "prettyplease", + "syn", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags", + "indexmap 2.13.0", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap 2.13.0", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] [[package]] name = "zerocopy" -version = "0.8.33" +version = "0.8.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "668f5168d10b9ee831de31933dc111a459c97ec93225beb307aed970d1372dfd" +checksum = "57cf3aa6855b23711ee9852dfc97dfaa51c45feaba5b645d0c777414d494a961" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.33" +version = "0.8.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c7962b26b0a8685668b671ee4b54d007a67d4eaf05fda79ac0ecf41e32270f1" +checksum = "8a616990af1a287837c4fe6596ad77ef57948f787e46ce28e166facc0cc1cb75" dependencies = [ "proc-macro2", "quote", @@ -1493,6 +1690,6 @@ dependencies = [ [[package]] name = "zmij" -version = "1.0.15" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94f63c051f4fe3c1509da62131a678643c5b6fbdc9273b2b79d4378ebda003d2" +checksum = "3ff05f8caa9038894637571ae6b9e29466c1f4f829d26c9b28f869a29cbe3445" diff --git a/Cargo.toml b/Cargo.toml index e25156c2..7bd6e024 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,104 +1,97 @@ -[workspace] -default-members = ["rstm"] -members = [ - "rstm", - "core", - "macros", - "state", - "tape", - "traits", -] -resolver = "3" - -[workspace.package] -authors = [ - "FL03 ", - "Scattered-Systems ", -] -categories = [ - "mathematics", - "science", - "simulation", -] -description = "This crate focuses on building concrete implementations for Turing Machines." -edition = "2024" -homepage = "https://github.com/FL03/rstm/wiki" -keywords = ["turing", "turing-machine", "utm"] -license = "Apache-2.0" -readme = "README.md" -repository = "https://github.com/FL03/rstm.git" -rust-version = "1.85.0" -version = "0.1.3" - -[workspace.dependencies] -# local -rstm = { default-features = false, path = "rstm", version = "0.1.3" } -rstm-core = { default-features = false, path = "core", version = "0.1.3" } -rstm-macros = { default-features = false, path = "macros", version = "0.1.3" } -rstm-state = { default-features = false, path = "state", version = "0.1.3" } -rstm-tape = { default-features = false, path = "tape", version = "0.1.3" } -rstm-traits = { default-features = false, path = "traits", version = "0.1.3" } -# custom -contained = { default-features = false, features = ["macros"], version = "0.2.3" } -rspace-traits = { default-features = false, version = "0.0.9" } -# developmemt -criterion = { version = "0.8" } -# async -tokio = { default-features = false, version = "1" } -async-trait = { default-features = false, version = "0.1" } -# concurrency / parallelism -crossbeam = { default-features = false, version = "0.8" } -rayon = { default-features = false, version = "1" } -# data-structures -bytes = { default-features = false, version = "1" } -hashbrown = { default-features = false, version = "0.16" } -# error-handling -anyhow = { default-features = false, version = "1" } -thiserror = { default-features = false, version = "2" } -# numbers -num-complex = { default-features = false, version = "0.4" } -num-integer = { default-features = false, version = "0.1" } -num-traits = { default-features = false, version = "0.2" } -# random -getrandom = { default-features = false, version = "0.3" } -rand = { default-features = false, version = "0.9" } -rand_distr = { default-features = false, version = "0.5" } -# serialization -serde = { default-features = false, features = ["derive"], version = "1" } -serde_derive = { default-features = false, version = "1" } -serde_json = { default-features = false, version = "1" } -# macros & utilities -lazy_static = { version = "1" } -paste = { version = "1" } -smart-default = { version = "0.7" } -strum = { default-features = false, features = ["derive"], version = "0.27" } -# logging -tracing = { default-features = false, features = ["attributes"], version = "0.1" } -# WebAssembly -wasm-bindgen = { default-features = false, version = "0.2" } - -# ************* [Profiles] ************* - -[profile.dev] -codegen-units = 256 -debug = true -debug-assertions = true -incremental = true -lto = "thin" -opt-level = 2 -overflow-checks = true -panic = "abort" -rpath = true -strip = false - -[profile.release] -codegen-units = 16 -debug = false -debug-assertions = false -incremental = false -lto = "fat" -opt-level = "z" -overflow-checks = false -panic = "abort" -rpath = false -strip = "debuginfo" +[workspace] +default-members = ["crates/rstm"] +members = [ + "crates/*" +] +resolver = "3" + +[workspace.package] +authors = ["FL03 (https://github.com/FL03)"] +categories = [ + "mathematics", + "science", + "simulation", +] +description = "This crate focuses on building concrete implementations for Turing Machines." +edition = "2024" +homepage = "https://github.com/FL03/rstm/wiki" +keywords = ["turing machine", "tm", "fsm", "computation"] +license = "Apache-2.0" +readme = "README.md" +repository = "https://github.com/FL03/rstm.git" +rust-version = "1.91.0" +version = "0.1.4" + +[workspace.dependencies] +# local +rstm = { default-features = false, path = "crates/rstm", version = "0.1.4" } +rstm-core = { default-features = false, path = "crates/core", version = "0.1.4" } +rstm-macros = { default-features = false, path = "crates/macros", version = "0.1.4" } +rstm-state = { default-features = false, path = "crates/state", version = "0.1.4" } +rstm-tape = { default-features = false, path = "crates/tape", version = "0.1.4" } +rstm-traits = { default-features = false, path = "crates/traits", version = "0.1.4" } +# custom +contained = { default-features = false, features = ["macros"], version = "0.2.3" } +rspace-traits = { default-features = false, version = "0.0.9" } +# developmemt +criterion = { version = "0.8" } +# async +tokio = { default-features = false, version = "1" } +async-trait = { default-features = false, version = "0.1" } +# concurrency / parallelism +crossbeam = { default-features = false, version = "0.8" } +rayon = { default-features = false, version = "1" } +# data-structures +bytes = { default-features = false, version = "1" } +hashbrown = { default-features = false, version = "0.16" } +# error-handling +anyhow = { default-features = false, version = "1" } +thiserror = { default-features = false, version = "2" } +# numbers +num-complex = { default-features = false, version = "0.4" } +num-integer = { default-features = false, version = "0.1" } +num-traits = { default-features = false, version = "0.2" } +# random +getrandom = { default-features = false, version = "0.4" } +rand = { default-features = false, version = "0.9" } +rand_distr = { default-features = false, version = "0.5" } +# serialization +serde = { default-features = false, features = ["derive"], version = "1" } +serde_derive = { default-features = false, version = "1" } +serde_json = { default-features = false, version = "1" } +# macros & utilities +lazy_static = { version = "1" } +paste = { version = "1" } +smart-default = { version = "0.7" } +strum = { default-features = false, features = ["derive"], version = "0.27" } +# logging +tracing = { default-features = false, features = ["attributes"], version = "0.1" } +tracing-subscriber = { features = ["env-filter", "fmt",], version = "0.3" } +# WebAssembly +wasm-bindgen = { default-features = false, version = "0.2" } + +# ************* [Profiles] ************* + +[profile.dev] +codegen-units = 256 +debug = true +debug-assertions = true +incremental = true +lto = "thin" +opt-level = 2 +overflow-checks = true +panic = "abort" +rpath = true +strip = false + +[profile.release] +codegen-units = 16 +debug = false +debug-assertions = false +incremental = false +lto = "fat" +opt-level = "z" +overflow-checks = false +panic = "abort" +rpath = false +strip = "debuginfo" diff --git a/SECURITY.md b/SECURITY.md index f2957dbe..21176521 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -6,8 +6,8 @@ Checkout the current and supported packages below: | Version | Supported? | |:------------------|:-------------------| -| 0.1.2 (latest) | :white_check_mark: | -| <0.0.8,>=0.1.1 | :white_check_mark: | +| 0.1.4 (latest) | :white_check_mark: | +| <0.0.8,>=0.1.3 | :white_check_mark: | | <0.0.8 | :x: | ## Reporting a Vulnerability diff --git a/clippy.toml b/clippy.toml index 57a49828..b76dea15 100644 --- a/clippy.toml +++ b/clippy.toml @@ -1 +1 @@ -msrv = "1.85.0" \ No newline at end of file +msrv = "1.91.0" \ No newline at end of file diff --git a/core/src/programs/impls/impl_deprecated.rs b/core/src/programs/impls/impl_deprecated.rs deleted file mode 100644 index 5cd0b07f..00000000 --- a/core/src/programs/impls/impl_deprecated.rs +++ /dev/null @@ -1,33 +0,0 @@ -/* - appellation: impl_deprecated - authors: @FL03 -*/ -#![allow(deprecated)] -#![cfg(feature = "alloc")] -use crate::programs::Program; - -use crate::{Head, RuleVec, Tail}; -use rstm_state::RawState; - -#[doc(hidden)] -impl Program -where - Q: RawState + Default, -{ - #[deprecated(since = "0.0.8", note = "use `rules` instead")] - pub const fn instructions(&self) -> &RuleVec { - self.rules() - } - #[deprecated(since = "0.0.8", note = "use `rules_mut` instead")] - pub fn instructions_mut(&mut self) -> &mut RuleVec { - self.rules_mut() - } - #[deprecated(since = "0.0.8", note = "use `get` instead")] - pub fn get_by_head(&self, head: &Head) -> Option<&Tail> - where - Q: PartialEq, - S: PartialEq, - { - self.get(head) - } -} diff --git a/core/src/programs/impls/impl_instruction_set.rs b/core/src/programs/impls/impl_instruction_set.rs deleted file mode 100644 index 27fe7bde..00000000 --- a/core/src/programs/impls/impl_instruction_set.rs +++ /dev/null @@ -1,65 +0,0 @@ -/* - Appellation: impl_program - Created At: 2026.01.11:12:33:32 - Contrib: @FL03 -*/ -use crate::programs::{InstructionSet, RuleSet}; -use crate::rules::Rule; -use rstm_state::{IntoState, RawState, State}; - -impl InstructionSet -where - Q: RawState, - R: RuleSet, -{ - /// initialize a new program from the given rule set - pub const fn from_rules(rules: R) -> Self { - Self { - rules, - initial_state: None, - _marker: core::marker::PhantomData::>, - } - } - #[cfg(all(feature = "json", feature = "std"))] - /// load a program from a `.json` file at the given path - pub fn load_from_json>(path: P) -> crate::Result - where - Self: serde::de::DeserializeOwned, - { - // open the file - let file = std::fs::File::open(path)?; - // create a buffered reader - let reader = std::io::BufReader::new(file); - // deserialize the program - let p = serde_json::from_reader(reader)?; - Ok(p) - } - /// returns a reference to the ruleset - pub const fn rules(&self) -> &R { - &self.rules - } - #[allow(dead_code)] - /// returns a mutable reference to the ruleset - pub(crate) const fn rules_mut(&mut self) -> &mut R { - &mut self.rules - } - /// returns reference to the (optional) initial state - pub fn initial_state(&self) -> Option<&State> { - self.initial_state.as_ref() - } - /// configure the initial state - pub fn set_initial_state(&mut self, initial_state: Q) { - self.initial_state = Some(State(initial_state)); - } - #[inline] - /// consumes the instance to create another with the given initial state - pub fn with_initial_state(self, initial_state: U) -> Self - where - U: IntoState, - { - Self { - initial_state: Some(initial_state.into_state()), - ..self - } - } -} diff --git a/core/src/programs/impls/impl_instruction_set_repr.rs b/core/src/programs/impls/impl_instruction_set_repr.rs deleted file mode 100644 index 3c06a916..00000000 --- a/core/src/programs/impls/impl_instruction_set_repr.rs +++ /dev/null @@ -1,77 +0,0 @@ -/* - Appellation: impl_program - Created At: 2026.01.11:12:33:32 - Contrib: @FL03 -*/ -use crate::programs::InstructionSet; -use crate::rules::Rule; -#[cfg(feature = "alloc")] -use alloc::vec::Vec; -use rstm_state::RawState; - -impl InstructionSet<[Rule], Q, A> -where - Q: RawState, -{ - /// returns an iterator over the elements. - pub fn iter(&self) -> core::slice::Iter<'_, Rule> { - self.rules.iter() - } - /// returns a mutable iterator over the elements. - pub fn iter_mut(&mut self) -> core::slice::IterMut<'_, Rule> { - self.rules.iter_mut() - } -} - -impl InstructionSet<&[Rule], Q, A> -where - Q: RawState, -{ - /// returns an iterator over the elements. - pub fn iter(&self) -> core::slice::Iter<'_, Rule> { - self.rules.iter() - } -} - -impl InstructionSet<&mut [Rule], Q, A> -where - Q: RawState, -{ - /// returns an iterator over the elements. - pub fn iter(&self) -> core::slice::Iter<'_, Rule> { - self.rules.iter() - } - /// returns a mutable iterator over the elements. - pub fn iter_mut(&mut self) -> core::slice::IterMut<'_, Rule> { - self.rules.iter_mut() - } -} - -impl InstructionSet<[Rule; N], Q, A> -where - Q: RawState, -{ - /// returns an iterator over the elements. - pub fn iter(&self) -> core::slice::Iter<'_, Rule> { - self.rules.iter() - } - /// returns a mutable iterator over the elements. - pub fn iter_mut(&mut self) -> core::slice::IterMut<'_, Rule> { - self.rules.iter_mut() - } -} - -#[cfg(feature = "alloc")] -impl InstructionSet>, Q, A> -where - Q: RawState, -{ - /// returns an iterator over the elements. - pub fn iter(&self) -> core::slice::Iter<'_, Rule> { - self.rules().iter() - } - /// returns a mutable iterator over the elements. - pub fn iter_mut(&mut self) -> core::slice::IterMut<'_, Rule> { - self.rules_mut().iter_mut() - } -} diff --git a/core/src/programs/impls/impl_program_ext.rs b/core/src/programs/impls/impl_program_ext.rs deleted file mode 100644 index 78b525c4..00000000 --- a/core/src/programs/impls/impl_program_ext.rs +++ /dev/null @@ -1,137 +0,0 @@ -/* - Appellation: impl_program_ext - Created At: 2026.01.11:13:35:13 - Contrib: @FL03 -*/ -#![cfg(feature = "alloc")] -use crate::programs::Program; - -use crate::{Head, Rule, RuleVec, Tail}; -use alloc::vec::{self, Vec}; -use rstm_state::{RawState, State}; - -#[cfg(feature = "serde_json")] -impl Program -where - Q: RawState, -{ - /// serializes the current instance into a JSON string - pub fn to_json(&self) -> serde_json::Value - where - A: serde::Serialize, - Q: serde::Serialize, - { - serde_json::to_value(self).expect("Failed to serialize the Program instance") - } -} - -impl AsRef<[Rule]> for Program -where - Q: RawState, -{ - fn as_ref(&self) -> &[Rule] { - &self.rules - } -} - -impl AsMut<[Rule]> for Program -where - Q: RawState, -{ - fn as_mut(&mut self) -> &mut [Rule] { - &mut self.rules - } -} - -impl core::ops::Deref for Program -where - Q: RawState, -{ - type Target = [Rule]; - - fn deref(&self) -> &Self::Target { - &self.rules - } -} - -impl core::ops::DerefMut for Program -where - Q: RawState, -{ - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.rules - } -} - -impl core::ops::Index> for Program -where - Q: RawState + PartialEq, - A: PartialEq, -{ - type Output = Tail; - - fn index(&self, index: Head) -> &Self::Output { - self.get(&index).unwrap() - } -} - -impl From>> for Program -where - Q: RawState + Default, -{ - fn from(rules: Vec>) -> Self { - Self::from_rules(rules) - } -} - -impl Extend> for Program -where - Q: RawState, -{ - fn extend>>(&mut self, iter: I) { - self.rules_mut().extend(iter) - } -} - -impl Extend<(Head, Tail)> for Program -where - Q: RawState, -{ - fn extend, Tail)>>(&mut self, iter: I) { - self.rules_mut() - .extend(iter.into_iter().map(|(head, tail)| Rule { head, tail })) - } -} - -impl FromIterator> for Program -where - Q: RawState + Default, -{ - fn from_iter>>(iter: I) -> Self { - Self { - initial_state: State::default(), - rules: iter.into_iter().collect::>(), - } - } -} - -impl FromIterator<(Head, Tail)> for Program -where - Q: RawState + Default, -{ - fn from_iter, Tail)>>(iter: I) -> Self { - Self::from_rules(iter.into_iter().map(|(head, tail)| Rule { head, tail })) - } -} - -impl IntoIterator for Program -where - Q: RawState, -{ - type Item = Rule; - type IntoIter = vec::IntoIter; - - fn into_iter(self) -> Self::IntoIter { - self.rules.into_iter() - } -} diff --git a/core/src/programs/instruction_set.rs b/core/src/programs/instruction_set.rs deleted file mode 100644 index bb36d3cb..00000000 --- a/core/src/programs/instruction_set.rs +++ /dev/null @@ -1,46 +0,0 @@ -/* - Appellation: program_base - Created At: 2026.01.11:12:34:11 - Contrib: @FL03 -*/ -use super::RuleSet; -use crate::{Head, Rule, Tail}; -use rstm_state::{RawState, State}; - -#[cfg(feature = "hashbrown")] -use hashbrown::{HashMap, HashSet}; -#[cfg(all(not(feature = "hashbrown"), feature = "std"))] -use std::collections::{HashMap, HashSet}; - -pub type ProgramSlice = InstructionSet]>; -pub type ProgramArray = InstructionSet; N]>; -#[cfg(feature = "alloc")] -/// a type alias for a [`InstructionSet`] using a [`Vec`](alloc::vec::Vec) as the ruleset -pub type ProgramVec = InstructionSet>>; -#[cfg(any(feature = "hashbrown", feature = "std"))] -/// a type alias for a [`InstructionSet`] using a [`HashMap`] as the ruleset, using the head -/// as key and the tail as value -pub type ProgramMap = InstructionSet, Tail>>; -#[cfg(any(feature = "hashbrown", feature = "std"))] -/// a type alias for a [`InstructionSet`] using a [`HashSet`] consisting of rules as the -/// store -pub type ProgramSet = InstructionSet>>; - -/// The [`InstructionSet`] implementation is a generic structure representing a set of -/// instructions or rules capable of transforming states within a computational model. -#[derive(Clone, Copy, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] -#[cfg_attr( - feature = "serde", - derive(serde::Serialize, serde::Deserialize), - serde(deny_unknown_fields, rename_all = "snake_case") -)] -#[repr(C)] -pub struct InstructionSet -where - Q: RawState, - R: RuleSet, -{ - pub(crate) initial_state: Option>, - pub(crate) _marker: core::marker::PhantomData>, - pub(crate) rules: R, -} diff --git a/core/src/programs/mod.rs b/core/src/programs/mod.rs deleted file mode 100644 index 013bb243..00000000 --- a/core/src/programs/mod.rs +++ /dev/null @@ -1,45 +0,0 @@ -/* - Appellation: program - Created At: 2026.01.11:12:29:14 - Contrib: @FL03 -*/ -//! the `program` module implements the core `Program` structure and its associated traits -#[cfg(feature = "alloc")] -pub use self::program::Program; -#[doc(inline)] -pub use self::{instruction_set::*, traits::*}; - -mod instruction_set; -mod program; - -mod impls { - mod impl_deprecated; - - mod impl_program; - mod impl_program_ext; - - mod impl_instruction_set; - mod impl_instruction_set_ext; - mod impl_instruction_set_repr; -} - -mod traits { - #[doc(inline)] - pub use self::ruleset::*; - - mod ruleset; -} -// mod types { -// #[doc(inline)] -// pub use self::aliases::*; - -// mod aliases; -// } - -#[doc(hidden)] -pub(crate) mod prelude { - pub use super::instruction_set::*; - #[cfg(feature = "alloc")] - pub use super::program::*; - pub use super::traits::*; -} diff --git a/core/src/programs/program.rs b/core/src/programs/program.rs deleted file mode 100644 index 02c5dc0b..00000000 --- a/core/src/programs/program.rs +++ /dev/null @@ -1,28 +0,0 @@ -/* - Appellation: program - Created At: 2025.09.05:04:59:21 - Contrib: @FL03 -*/ - -use crate::Rule; -use rstm_state::{RawState, State}; - -/// The [`Program`] implementation is designed to provide a structured representation of a set -/// of rules and an optional initial state for a Turing machine or similar computational model. -/// It encapsulates the rules that dictate the machine's behavior and the starting point for -/// its execution. -#[derive(Clone, Debug, Default)] -#[cfg_attr( - feature = "serde", - derive(serde::Deserialize, serde::Serialize), - serde(deny_unknown_fields, rename_all = "snake_case") -)] -#[repr(C)] -pub struct Program -where - Q: RawState, -{ - pub(crate) initial_state: State, - #[cfg(feature = "alloc")] - pub(crate) rules: alloc::vec::Vec>, -} diff --git a/core/src/programs/traits/ruleset.rs b/core/src/programs/traits/ruleset.rs deleted file mode 100644 index 86bcdb1a..00000000 --- a/core/src/programs/traits/ruleset.rs +++ /dev/null @@ -1,124 +0,0 @@ -/* - Appellation: instruction_set - Created At: 2026.01.11:12:29:41 - Contrib: @FL03 -*/ -use crate::rules::{Head, Instruction, Rule, Tail}; -use rstm_state::RawState; - -/// The [`RuleSet`] trait establishes an interface common to all compatible sets of rules for -/// the framework. -pub trait RuleSet -where - Q: RawState, -{ - type Rule: Instruction; -} - -/* - ************* Implementations ************* -*/ - -impl RuleSet for [(Head, Tail)] -where - Q: RawState, -{ - type Rule = (Head, Tail); -} - -impl RuleSet for [Rule] -where - Q: RawState, -{ - type Rule = Rule; -} - -impl RuleSet for &[Rule] -where - Q: RawState, -{ - type Rule = Rule; -} - -impl RuleSet for &mut [Rule] -where - Q: RawState, -{ - type Rule = Rule; -} - -impl RuleSet for [Rule; N] -where - Q: RawState, -{ - type Rule = Rule; -} - -#[cfg(feature = "alloc")] -mod impl_alloc { - use super::RuleSet; - use crate::{Head, Rule, Tail}; - use alloc::collections::{BTreeMap, BTreeSet}; - use alloc::vec::Vec; - use rstm_state::RawState; - - impl RuleSet for Vec<(Head, Tail)> - where - Q: RawState, - { - type Rule = Rule; - } - - impl RuleSet for Vec> - where - Q: RawState, - { - type Rule = Rule; - } - - impl RuleSet for BTreeSet> - where - Q: RawState, - { - type Rule = Rule; - } - - impl RuleSet for BTreeMap, Tail> - where - Q: RawState, - { - type Rule = Rule; - } -} - -#[cfg(feature = "hashbrown")] -impl RuleSet for hashbrown::HashSet> -where - Q: RawState, -{ - type Rule = Rule; -} - -#[cfg(feature = "hashbrown")] -impl RuleSet for hashbrown::HashMap, Tail> -where - Q: RawState, -{ - type Rule = Rule; -} - -#[cfg(feature = "std")] -impl RuleSet for std::collections::HashSet> -where - Q: RawState, -{ - type Rule = Rule; -} - -#[cfg(feature = "std")] -impl RuleSet for std::collections::HashMap, Tail> -where - Q: RawState, -{ - type Rule = Rule; -} diff --git a/core/src/programs/types/aliases.rs b/core/src/programs/types/aliases.rs deleted file mode 100644 index 4ece10fd..00000000 --- a/core/src/programs/types/aliases.rs +++ /dev/null @@ -1,5 +0,0 @@ -/* - Appellation: aliases - Created At: 2026.01.11:15:06:06 - Contrib: @FL03 -*/ \ No newline at end of file diff --git a/core/src/rules/tail.rs b/core/src/rules/tail.rs deleted file mode 100644 index a9604726..00000000 --- a/core/src/rules/tail.rs +++ /dev/null @@ -1,111 +0,0 @@ -/* - Appellation: tail - Created At: 2025.12.15:21:29:04 - Contrib: @FL03 -*/ - -use crate::Direction; -use rstm_state::{RawState, State}; - -/// A type alias for a [`Tail`] containing immutable references to the next state and symbol. -pub type TailRef<'a, Q, A> = Tail<&'a Q, &'a A>; -/// A type alias for a [`Tail`] containing mutable references to the next state and symbol. -pub type TailMut<'a, Q, A> = Tail<&'a mut Q, &'a mut A>; - -/// [`RawTail`] is a sealed marker trait used to denote objects capable of being used to -/// represent the _tail_ of a rule for a Turing machine. -pub trait RawTail { - type State: RawState; - type Symbol; - private! {} - /// returns the direction of the tail. - fn direction(&self) -> Direction; - /// returns an immutable reference to the next state. - fn next_state(&self) -> &State; - /// returns a reference to the symbol configured for the head to write next. - fn write_symbol(&self) -> &Self::Symbol; -} - -/// The [`Tail`] of a rule defines the _reaction_ of the actor under specific conditions. -/// Specifically, it defines the next state, the symbol to write, and the direction to move -#[derive(Clone, Copy, Default, PartialEq, Eq, Hash, Ord, PartialOrd)] -#[cfg_attr( - feature = "serde", - derive(serde::Deserialize, serde::Serialize), - serde(rename_all = "snake_case") -)] -#[repr(C)] -pub struct Tail { - /// defines the direction to move after writing the symbol - #[cfg_attr(feature = "serde", serde(alias = "move_direction", alias = "dir"))] - pub direction: Direction, - #[cfg_attr(feature = "serde", serde(alias = "write_state"))] - pub next_state: State, - #[cfg_attr(feature = "serde", serde(alias = "next_symbol"))] - pub write_symbol: A, -} - -/* - ************* Implementations ************* -*/ -impl RawTail for (Direction, State, A) -where - Q: RawState, -{ - type State = Q; - type Symbol = A; - - seal! {} - /// returns the direction of the tail. - fn direction(&self) -> Direction { - self.0 - } - /// returns an immutable reference to the next state. - fn next_state(&self) -> &State { - &self.1 - } - /// returns an immutable reference to the symbol to write. - fn write_symbol(&self) -> &A { - &self.2 - } -} - -impl RawTail for Tail -where - Q: RawState, -{ - type State = Q; - type Symbol = A; - - seal! {} - /// returns the direction of the tail. - fn direction(&self) -> Direction { - self.direction - } - /// returns an immutable reference to the next state. - fn next_state(&self) -> &State { - &self.next_state - } - /// returns an immutable reference to the symbol to write. - fn write_symbol(&self) -> &A { - &self.write_symbol - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_tail_init() { - let tail: Tail<&str, char> = Tail::right("q1", 'a'); - assert_eq! { - tail, - ( - Direction::Right, - State("q1"), - 'a' - ) - } - } -} diff --git a/core/src/rules/traits/instruction.rs b/core/src/rules/traits/instruction.rs deleted file mode 100644 index a02459b4..00000000 --- a/core/src/rules/traits/instruction.rs +++ /dev/null @@ -1,90 +0,0 @@ -/* - Appellation: instruction - Created At: 2026.01.15:11:50:07 - Contrib: @FL03 -*/ -use crate::rules::{Head, RawHead, RawTail, Rule, Tail}; -use rstm_state::{RawState, State}; -/// The [`Instruction`] trait establishes the base interface for all compatible rules for the -/// automata. -pub trait Instruction -where - Q: RawState, -{ - /// the type of head used by the instruction - type Head: RawHead; - /// the type of tail used by the instruction - type Tail: RawTail; - /// returns a reference to the head of the instruction - fn head(&self) -> &Self::Head; - /// returns a reference to the tail of the instruction - fn tail(&self) -> &Self::Tail; - /// returns a reference to the current state - fn current_state<'a>(&'a self) -> &'a State - where - Self::Head: 'a, - { - self.head().state() - } - /// returns a reference to the current symbol - fn symbol<'a>(&'a self) -> &'a A - where - Self::Head: 'a, - { - self.head().symbol() - } - /// returns the direction of the tail - fn direction(&self) -> crate::Direction { - self.tail().direction() - } - /// returns a reference to the next state - fn next_state<'a>(&'a self) -> &'a State - where - Self::Tail: 'a, - { - self.tail().next_state() - } - /// returns a reference to the next symbol - fn next_symbol<'a>(&'a self) -> &'a A - where - Self::Tail: 'a, - { - self.tail().write_symbol() - } -} - -/* - ************* Implementations ************* -*/ - -impl Instruction for (Head, Tail) -where - Q: RawState, -{ - type Head = Head; - type Tail = Tail; - - fn head(&self) -> &Self::Head { - &self.0 - } - - fn tail(&self) -> &Self::Tail { - &self.1 - } -} - -impl Instruction for Rule -where - Q: RawState, -{ - type Head = Head; - type Tail = Tail; - - fn head(&self) -> &Self::Head { - &self.head - } - - fn tail(&self) -> &Self::Tail { - &self.tail - } -} diff --git a/core/Cargo.toml b/crates/core/Cargo.toml similarity index 84% rename from core/Cargo.toml rename to crates/core/Cargo.toml index 1fc8d18a..80fe9be5 100644 --- a/core/Cargo.toml +++ b/crates/core/Cargo.toml @@ -1,195 +1,219 @@ -[package] -build = "build.rs" -name = "rstm-core" - -authors.workspace = true -categories.workspace = true -description.workspace = true -edition.workspace = true -homepage.workspace = true -keywords.workspace = true -license.workspace = true -readme.workspace = true -repository.workspace = true -rust-version.workspace = true -version.workspace = true - -[package.metadata.docs.rs] -all-features = false -features = ["default"] -rustc-args = ["--cfg", "docsrs"] -version = "v{{version}}" - -[package.metadata.release] -no-dev-version = true -tag-name = "{{version}}" - -[lib] -bench = false - -[[test]] -name = "macros" -required-features = ["macros"] - -[dependencies] -rstm-state = { workspace = true } -rstm-traits = { workspace = true } -# custom -rspace-traits = { workspace = true } -# concurrency / parallelism -rayon = { optional = true, workspace = true } -# data structures -bytes = { optional = true, workspace = true } -hashbrown = { optional = true, workspace = true } -# error handling -anyhow = { workspace = true } -thiserror = { workspace = true } -# math -num-complex = { optional = true, workspace = true } -num-traits = { workspace = true } -# serialization -serde = { optional = true, workspace = true } -serde_derive = { optional = true, workspace = true } -serde_json = { optional = true, workspace = true } -# logging -tracing = { optional = true, workspace = true } -# WebAssembly -wasm-bindgen = { optional = true, workspace = true } -# utilities -contained = { workspace = true } -paste = { workspace = true } -strum = { workspace = true } - -[features] -default = ["macros", "std"] - -full = [ - "default", - "bytes", - "complex", - "hashbrown", - "json", - "rand", - "serde", - "tracing", -] - -macros = [ - "rstm-state/macros", -] - -nightly = [ - "rstm-state/nightly", - "rstm-traits/nightly", - "rspace-traits/nightly", -] - -json = [ - "alloc", - "serde", - "serde_json", - "rstm-state/json", -] - -# ********* [FF] Environments ********* - -std = [ - "alloc", - "anyhow/std", - "contained/std", - "rstm-state/std", - "rstm-traits/std", - "rspace-traits/std", - "serde?/std", - "serde_json?/std", - "strum/std", - "thiserror/std", - "tracing?/std", -] - -wasi = [ - "rstm-state/wasi", - "rstm-traits/wasi", - "rspace-traits/wasi", -] - -wasm = [ - "wasm_bindgen", - "rstm-state/wasm", - "rstm-traits/wasm", - "rspace-traits/wasm", -] - -# ********* [FF] Dependencies ********* - -alloc = [ - "contained/alloc", - "rstm-state/alloc", - "rstm-traits/alloc", - "rspace-traits/alloc", - "serde?/alloc", - "serde_json?/alloc", -] - -bytes = [ - "dep:bytes", - "rstm-state/bytes", - "rstm-traits/bytes", -] - -hashbrown = [ - "dep:hashbrown", - "rstm-state/hashbrown", - "rstm-traits/hashbrown", - "rspace-traits/hashbrown", -] - -complex = [ - "dep:num-complex", - "rstm-state/complex", - "rstm-traits/complex", - "rspace-traits/complex", -] - -rand = [ - "rstm-state/rand", - "rstm-traits/rand", - "rspace-traits/rand", -] - -rayon = [ - "dep:rayon", - "hashbrown?/rayon", - "rstm-state/rayon", - "rstm-traits/rayon", -] - -rng = [ - "rstm-state/rng", -] - -serde = [ - "dep:serde", - "dep:serde_derive", - "serde?/derive", - "bytes?/serde", - "hashbrown?/serde", - "rstm-state/serde", - "rstm-traits/serde", - "rspace-traits/serde", -] - -serde_json = [ - "dep:serde_json", -] - -tracing = [ - "dep:tracing", -] - -wasm_bindgen = [ - "dep:wasm-bindgen", - "rstm-state/wasm_bindgen", - "rstm-traits/wasm_bindgen", - "rspace-traits/wasm_bindgen", -] +[package] +build = "build.rs" +name = "rstm-core" + +authors.workspace = true +categories.workspace = true +description.workspace = true +edition.workspace = true +homepage.workspace = true +keywords.workspace = true +license.workspace = true +readme.workspace = true +repository.workspace = true +rust-version.workspace = true +version.workspace = true + +[package.metadata.docs.rs] +all-features = false +features = ["default"] +rustc-args = ["--cfg", "docsrs"] +version = "v{{version}}" + +[package.metadata.release] +no-dev-version = true +tag-name = "{{version}}" + +[package.metadata.component] +package = "rstm:core" + +[package.metadata.component.dependencies] + +[lib] +bench = false + +[[test]] +name = "macros" +required-features = ["macros"] + +[dependencies] +rstm-state = { workspace = true } +rstm-traits = { workspace = true } +# custom +rspace-traits = { workspace = true } +# concurrency / parallelism +rayon = { optional = true, workspace = true } +# data structures +bytes = { optional = true, workspace = true } +hashbrown = { optional = true, workspace = true } +# error handling +anyhow = { workspace = true } +thiserror = { workspace = true } +# math +num-complex = { optional = true, workspace = true } +num-traits = { workspace = true } +# random +getrandom = { optional = true, workspace = true } +rand = { optional = true, workspace = true } +rand_distr = { optional = true, workspace = true } +# serialization +serde = { optional = true, workspace = true } +serde_derive = { optional = true, workspace = true } +serde_json = { optional = true, workspace = true } +# logging +tracing = { optional = true, workspace = true } +# WebAssembly +wasm-bindgen = { optional = true, workspace = true } +# utilities +contained = { workspace = true } +paste = { workspace = true } +strum = { workspace = true } + +[features] +default = ["macros", "std"] + +full = [ + "default", + "bytes", + "complex", + "hashbrown", + "json", + "rand", + "serde", + "tracing", +] + +macros = [ + "rstm-state/macros", +] + +nightly = [ + "rand?/nightly", + "rstm-state/nightly", + "rstm-traits/nightly", + "rspace-traits/nightly", +] + +json = [ + "alloc", + "serde", + "serde_json", + "rstm-state/json", +] + +# ********* [FF] Environments ********* + +std = [ + "alloc", + "anyhow/std", + "contained/std", + "getrandom?/std", + "rstm-state/std", + "rstm-traits/std", + "rspace-traits/std", + "serde?/std", + "serde_json?/std", + "strum/std", + "thiserror/std", + "tracing?/std", + "wasm-bindgen?/std", +] + +wasi = [ + "rstm-state/wasi", + "rstm-traits/wasi", + "rspace-traits/wasi", +] + +wasm = [ + "getrandom?/wasm_js", + "rayon?/web_spin_lock", + "wasm_bindgen", + "rstm-state/wasm", + "rstm-traits/wasm", + "rspace-traits/wasm", +] + +# ********* [FF] Dependencies ********* + +alloc = [ + "contained/alloc", + "rand?/alloc", + "rand_distr?/alloc", + "rstm-state/alloc", + "rstm-traits/alloc", + "rspace-traits/alloc", + "serde?/alloc", + "serde_json?/alloc", + "wasm-bindgen?/gg-alloc", +] + +bytes = [ + "dep:bytes", + "rstm-state/bytes", + "rstm-traits/bytes", +] + +hashbrown = [ + "dep:hashbrown", + "rstm-state/hashbrown", + "rstm-traits/hashbrown", + "rspace-traits/hashbrown", +] + +complex = [ + "dep:num-complex", + "rstm-state/complex", + "rstm-traits/complex", + "rspace-traits/complex", +] + +rand = [ + "rng", + "dep:rand", + "dep:rand_distr", + "rstm-state/rand", + "rstm-traits/rand", + "rspace-traits/rand", +] + +rayon = [ + "dep:rayon", + "hashbrown?/rayon", + "rstm-state/rayon", + "rstm-traits/rayon", +] + +rng = [ + "dep:getrandom", + "rstm-state/rng", + "rand?/os_rng", + "rand?/small_rng", +] + +serde = [ + "dep:serde", + "dep:serde_derive", + "serde?/derive", + "bytes?/serde", + "hashbrown?/serde", + "num-complex?/serde", + "rand?/serde", + "rand_distr?/serde", + "rstm-state/serde", + "rstm-traits/serde", + "rspace-traits/serde", +] + +serde_json = [ + "dep:serde_json", +] + +tracing = ["dep:tracing"] + +wasm_bindgen = [ + "dep:wasm-bindgen", + "rstm-state/wasm_bindgen", + "rstm-traits/wasm_bindgen", + "rspace-traits/wasm_bindgen", +] diff --git a/core/build.rs b/crates/core/build.rs similarity index 100% rename from core/build.rs rename to crates/core/build.rs diff --git a/core/src/actors/drivers/tmh.rs b/crates/core/src/actors/drivers/tmh.rs similarity index 96% rename from core/src/actors/drivers/tmh.rs rename to crates/core/src/actors/drivers/tmh.rs index c6fe6e9a..3bdafdce 100644 --- a/core/src/actors/drivers/tmh.rs +++ b/crates/core/src/actors/drivers/tmh.rs @@ -11,7 +11,7 @@ use crate::{Direction, Head, Tail}; use alloc::string::String; use alloc::vec::Vec; use rstm_state::{Halting, RawState, State}; -use rstm_traits::{Handle, Read, Symbolic, TryExecuteMut, TryStep}; +use rstm_traits::{Handle, Read, Symbolic, TryExecute, TryStep}; #[doc(hidden)] #[deprecated( @@ -210,11 +210,15 @@ where self.head().state().is_halted() } /// load the current instance and given program into a new instance of the - /// [`TuringEngine`] implementation to directly manage the execution of the program. + /// [`EngineBase`] implementation to directly manage the execution of the program. /// /// **Note**: The engine is a _lazy_ executor, meaning that the program will not be run /// until the corresponding `.run()` method is invoked on the engine. - pub fn load(self, program: Program) -> EngineBase { + pub fn load(self, program: Program) -> EngineBase + where + Q: PartialEq, + A: PartialEq, + { EngineBase::from_driver(self).with_program(program) } /// returns the _current_ head of the actor, using the given directive to write some symbol @@ -424,7 +428,7 @@ where impl Handle for TMH where Q: RawState, - Self: TryExecuteMut, + Self: TryExecute, { type Output = Result; @@ -433,7 +437,7 @@ where } } -impl TryExecuteMut<(Direction, State, A)> for TMH +impl TryExecute<(Direction, State, A)> for TMH where Q: RawState, { @@ -448,7 +452,7 @@ where } } -impl TryExecuteMut<(Direction, Head)> for TMH +impl TryExecute<(Direction, Head)> for TMH where Q: RawState, { @@ -463,7 +467,7 @@ where } } -impl TryExecuteMut> for TMH +impl TryExecute> for TMH where Q: RawState, { @@ -482,7 +486,7 @@ where } } -impl<'a, Q, A> TryStep for EngineBase, Q, A> +impl TryStep for EngineBase, Q, A> where Q: RawState + Clone + PartialEq, A: Symbolic, diff --git a/core/src/actors/engine_base.rs b/crates/core/src/actors/engine_base.rs similarity index 99% rename from core/src/actors/engine_base.rs rename to crates/core/src/actors/engine_base.rs index 69b9b496..58460ed5 100644 --- a/core/src/actors/engine_base.rs +++ b/crates/core/src/actors/engine_base.rs @@ -12,6 +12,7 @@ use rstm_state::RawState; /// A type alias for an [`EngineBase`] instance configured with a _moving head_ model using /// the [`Head`] structure to maintain the head's position on the tape. pub type MovingHead = EngineBase, Q, A>; + /// The [`EngineBase`] implementation is designed as a type of runtime for executing various /// Turing machine models, or drivers, according to a specified set of rules encapsulated /// within a [`Program`]. diff --git a/core/src/actors/impls/impl_engine_base.rs b/crates/core/src/actors/impls/impl_engine_base.rs similarity index 100% rename from core/src/actors/impls/impl_engine_base.rs rename to crates/core/src/actors/impls/impl_engine_base.rs diff --git a/core/src/actors/impls/impl_engine_ext.rs b/crates/core/src/actors/impls/impl_engine_ext.rs similarity index 72% rename from core/src/actors/impls/impl_engine_ext.rs rename to crates/core/src/actors/impls/impl_engine_ext.rs index d962508c..3cf1871a 100644 --- a/core/src/actors/impls/impl_engine_ext.rs +++ b/crates/core/src/actors/impls/impl_engine_ext.rs @@ -9,11 +9,12 @@ use crate::actors::{Driver, Executor}; use crate::programs::Program; use crate::rules::Head; use rstm_state::{Halting, RawState}; -use rstm_traits::{Handle, Reader, Symbolic, TryStep}; +use rstm_traits::{Reader, Symbolic, TryExecute, TryStep}; -impl<'a, D, Q, A> Reader for EngineBase +impl Reader for EngineBase where - Q: RawState, + Q: RawState + PartialEq, + A: PartialEq, D: Driver, { type Error = crate::Error; @@ -23,22 +24,25 @@ where } } -impl<'a, D, Q, A, X, Y> Handle for EngineBase +impl TryExecute for EngineBase where - Q: RawState, - D: Driver + Handle, + Q: RawState + PartialEq, + A: PartialEq, + D: Driver + TryExecute, { + type Error = E; type Output = Y; - fn handle(&mut self, args: X) -> Self::Output { - self.driver_mut().handle(args) + fn try_execute(&mut self, args: X) -> Result { + self.driver_mut().try_execute(args) } } impl Executor for EngineBase where D: Driver, - Q: Halting + RawState, + Q: Halting + RawState + PartialEq, + A: PartialEq, Self: TryStep, Error = crate::Error>, { type Driver = D; @@ -68,7 +72,7 @@ where // if the output tape is empty, initialize it from the driver's tape if self.tape().is_empty() { #[cfg(feature = "tracing")] - tracing::error! { "Output tape is empty; initializing from the input tape..." }; + tracing::error! { "No inputs loaded on the tape" }; return Err(crate::Error::TapeIsEmpty); } // read the tape @@ -89,16 +93,16 @@ where // process the instruction let step = self.driver.step(tail); // apply the step - step.shift(&mut self.tape) - } else { - #[cfg(feature = "tracing")] - tracing::error!("No program loaded; cannot execute step."); - Err(crate::Error::NoProgram) + return step.shift(&mut self.tape); } + // if there is no program loaded, return an error + #[cfg(feature = "tracing")] + tracing::error!("No program loaded; cannot execute step."); + Err(crate::Error::NoProgram) } } -impl<'a, D, Q, A> Iterator for EngineBase +impl Iterator for EngineBase where Q: 'static + Halting + RawState + Clone + PartialEq, A: Symbolic, diff --git a/core/src/actors/impls/impl_engine_repr.rs b/crates/core/src/actors/impls/impl_engine_repr.rs similarity index 86% rename from core/src/actors/impls/impl_engine_repr.rs rename to crates/core/src/actors/impls/impl_engine_repr.rs index 2faa4c4e..3d52ad41 100644 --- a/core/src/actors/impls/impl_engine_repr.rs +++ b/crates/core/src/actors/impls/impl_engine_repr.rs @@ -10,17 +10,18 @@ use rstm_state::RawState; impl EngineBase, Q, A> where - Q: RawState, + Q: RawState + PartialEq, + A: PartialEq, { /// initialize a new instance of a turing machine with a moving head using the given /// program. pub fn tmh(program: Program) -> Self where - Q: Clone, + Q: Clone + Default, { Self { driver: Head { - state: program.initial_state().cloned(), + state: program.initial_state().cloned().unwrap_or_default(), symbol: 0, }, tape: Vec::new(), diff --git a/core/src/actors/mod.rs b/crates/core/src/actors/mod.rs similarity index 100% rename from core/src/actors/mod.rs rename to crates/core/src/actors/mod.rs diff --git a/core/src/actors/traits/executor.rs b/crates/core/src/actors/traits/executor.rs similarity index 90% rename from core/src/actors/traits/executor.rs rename to crates/core/src/actors/traits/executor.rs index b2ab843c..0c447a93 100644 --- a/core/src/actors/traits/executor.rs +++ b/crates/core/src/actors/traits/executor.rs @@ -12,7 +12,8 @@ use rstm_state::RawState; /// The [`Executor`] trait defines the basis for compatible engines within the system. pub trait Executor where - Q: RawState, + Q: RawState + PartialEq, + A: PartialEq, { type Driver: Driver; diff --git a/core/src/actors/traits/raw_driver.rs b/crates/core/src/actors/traits/raw_driver.rs similarity index 93% rename from core/src/actors/traits/raw_driver.rs rename to crates/core/src/actors/traits/raw_driver.rs index ce13381e..4f884100 100644 --- a/core/src/actors/traits/raw_driver.rs +++ b/crates/core/src/actors/traits/raw_driver.rs @@ -6,7 +6,7 @@ use crate::rules::{Head, Tail}; use rspace_traits::RawSpace; use rstm_state::{RawState, State}; -use rstm_traits::{Handle, Read}; +use rstm_traits::{Read, TryExecute}; /// The [`Driver`] is the basis for all compatible actors within the system. Each /// implementation is required to define the _type_ of internal store it will use to @@ -19,12 +19,12 @@ where private! {} /// returns the current position of the driver. fn current_position(&self) -> usize; - /// returns a reference to the current state of the driver + /// returns a view of the current state of the driver. fn current_state(&self) -> State<&Q>; } /// An [`Actor`] is a particular kind of driver capable of maintaining its own internal store. -pub trait Actor: Driver + Handle> +pub trait Actor: Driver + TryExecute> where for<'a> Self: Read<&'a mut [A], Output = &'a A>, { diff --git a/core/src/error.rs b/crates/core/src/error.rs similarity index 100% rename from core/src/error.rs rename to crates/core/src/error.rs diff --git a/core/src/lib.rs b/crates/core/src/lib.rs similarity index 68% rename from core/src/lib.rs rename to crates/core/src/lib.rs index 7a98211c..e6317bd0 100644 --- a/core/src/lib.rs +++ b/crates/core/src/lib.rs @@ -3,14 +3,34 @@ Created At: 2026.01.17:21:43:29 Contrib: @FL03 */ -//! this crate provides core primtives and utilities for working with Turing machines in Rust. +//! This crate provides the core abstractions and utilities for the `rstm` framework, including +//! common types, traits, and macros that are used across the various components of the system. +//! +//! ## Features +//! +//! - `std`: Enables features that require the Rust standard library. +//! - `alloc`: Enables features that require the Rust `alloc` crate, allowing for dynamic +//! memory allocation in `no_std` environments. +//! - `nightly`: Enables features that require a nightly Rust compiler, such as certain unstable +//! features or APIs. +//! +//! ## Overview +//! +//! ### Rules +//! +//! - [`Head`]: A structural implementation of the 2-tuple containing the current +//! state and symbol of the machine. +//! +//! #![allow( + clippy::len_without_is_empty, + clippy::missing_docs_in_private_items, clippy::missing_errors_doc, clippy::missing_panics_doc, clippy::missing_safety_doc, clippy::module_inception, clippy::needless_doctest_main, - clippy::non_canonical_partial_ord_impl, + clippy::new_ret_no_self, clippy::should_implement_trait, clippy::upper_case_acronyms )] @@ -35,6 +55,8 @@ pub(crate) mod macros { // redeclarations #[doc(inline)] pub use rstm_state as state; +#[doc(inline)] +pub use rstm_traits as traits; // modules pub mod actors; pub mod error; @@ -55,7 +77,7 @@ pub use self::{ actors::{Driver, Executor, MovingHead}, error::{Error, Result}, motion::HeadStep, - programs::{InstructionSet, Program, RuleSet}, + programs::{Program, ProgramBase, RawRuleset}, rules::prelude::*, utils::*, }; @@ -67,6 +89,7 @@ pub use rstm_state::{Halt, HaltState, Halting, HaltingState, RawState, State, St #[doc(hidden)] pub mod prelude { pub use rstm_state::prelude::*; + pub use rstm_traits::prelude::*; #[cfg(all(feature = "alloc", feature = "macros"))] pub use crate::program; diff --git a/core/src/macros/program.rs b/crates/core/src/macros/program.rs similarity index 92% rename from core/src/macros/program.rs rename to crates/core/src/macros/program.rs index 5b4d3f1a..b038e098 100644 --- a/core/src/macros/program.rs +++ b/crates/core/src/macros/program.rs @@ -5,7 +5,7 @@ */ #![cfg(feature = "macros")] -/// The [`program!`] macro facilitates the creation of new [`Program`](crate::programs::Program) +/// The `program!` macro facilitates the creation of new [`Program`](crate::programs::Program) /// instances using familiar syntax /// /// ```ignore diff --git a/core/src/macros/rules.rs b/crates/core/src/macros/rules.rs similarity index 86% rename from core/src/macros/rules.rs rename to crates/core/src/macros/rules.rs index ecea4f4d..c42c52a0 100644 --- a/core/src/macros/rules.rs +++ b/crates/core/src/macros/rules.rs @@ -2,7 +2,7 @@ Appellation: ruleset Contrib: @FL03 */ -/// The [`head!`] macro simplifies the creation of a [`Head`](crate::Head) struct +/// The `head!` macro simplifies the creation of a [`Head`](crate::Head) struct /// by providing a concise syntax for specifying the state and symbol. #[macro_export] macro_rules! head { @@ -13,11 +13,11 @@ macro_rules! head { } }; } -///! the [`tail!`] macro facilitates the creation of a [`Tail`](crate::Tail) struct -///! by providing a concise syntax for specifying the direction, next state, and symbol to +/// the `tail!` macro facilitates the creation of a [`Tail`](crate::Tail) struct +/// by providing a concise syntax for specifying the direction, next state, and symbol to /// write. As with other macros in this module, the variants of the [`Direction`](crate::Direction) /// are hygenically imported based on usage, meaning one only needs to specify the variant name -///! directly, i.e. `Left`, `Right`, or `Stay`. +/// directly, i.e. `Left`, `Right`, or `Stay`. #[macro_export] macro_rules! tail { ($direction:ident, $state:expr, $symbol:expr) => { @@ -29,7 +29,7 @@ macro_rules! tail { }; } -/// The [`rule!`] macro enables the definition of a single, Turing compatible rule using the +/// The `rule!` macro enables the definition of a single, Turing compatible rule using the /// following syntax: /// /// ```ignore @@ -65,9 +65,9 @@ macro_rules! rule { } }; } -/// [`ruleset!`] is a macro that simplifies the creation of an array of [`Rules`](crate::Rule). +/// `ruleset!` is a macro that simplifies the creation of an array of [`Rules`](crate::Rule). /// -/// The syntax follows the [`rule!`] macro, allowing for multiple rules to be defined in a +/// The syntax follows the `rule!` macro, allowing for multiple rules to be defined in a /// single invocation. /// /// ```ignore diff --git a/core/src/macros/seal.rs b/crates/core/src/macros/seal.rs similarity index 100% rename from core/src/macros/seal.rs rename to crates/core/src/macros/seal.rs diff --git a/core/src/motion/head_step.rs b/crates/core/src/motion/head_step.rs similarity index 95% rename from core/src/motion/head_step.rs rename to crates/core/src/motion/head_step.rs index ae000611..f6d662f4 100644 --- a/core/src/motion/head_step.rs +++ b/crates/core/src/motion/head_step.rs @@ -6,8 +6,8 @@ use crate::{Head, Tail}; use rstm_state::RawState; -/// [`HeadStep`] is a structure responsible for managing the step operation of a moving head -/// in a Turing machine simulation. +/// [`HeadStep`] defines a *lazy* stepper for a Turing machine configured with a so-called +/// *moving head*. pub struct HeadStep<'a, Q1, A1, Q2 = Q1, A2 = A1> where Q1: RawState, diff --git a/core/src/motion/mod.rs b/crates/core/src/motion/mod.rs similarity index 100% rename from core/src/motion/mod.rs rename to crates/core/src/motion/mod.rs diff --git a/crates/core/src/programs/impls/imp_program_base.rs b/crates/core/src/programs/impls/imp_program_base.rs new file mode 100644 index 00000000..2b68ffa4 --- /dev/null +++ b/crates/core/src/programs/impls/imp_program_base.rs @@ -0,0 +1,118 @@ +/* + Appellation: impl_program + Created At: 2026.01.11:12:33:32 + Contrib: @FL03 +*/ +use crate::programs::{ProgramBase, RawRuleset, Ruleset}; +use crate::rules::{Head, Instruction, Tail}; +use rstm_state::{IntoState, RawState, State}; + +impl ProgramBase +where + Q: RawState, + R: RawRuleset, + I: Instruction, +{ + /// initialize a new program from the given rule set + pub const fn from_rules(rules: R) -> Self { + Self { + rules, + initial_state: None, + _marker: core::marker::PhantomData, + } + } + #[cfg(all(feature = "json", feature = "std"))] + /// load a program from a `.json` file at the given path + pub fn load_from_json>(path: P) -> crate::Result + where + Self: serde::de::DeserializeOwned, + { + // open the file + let file = std::fs::File::open(path)?; + // create a buffered reader + let reader = std::io::BufReader::new(file); + // deserialize the program + let p = serde_json::from_reader(reader)?; + Ok(p) + } + /// returns a reference to the ruleset + pub const fn rules(&self) -> &R { + &self.rules + } + #[allow(dead_code)] + /// returns a mutable reference to the ruleset + pub(crate) const fn rules_mut(&mut self) -> &mut R { + &mut self.rules + } + /// returns reference to the (optional) initial state + pub fn initial_state(&self) -> Option<&State> { + self.initial_state.as_ref() + } + /// configure the initial state + pub fn set_initial_state(&mut self, initial_state: Q) { + self.initial_state = Some(State(initial_state)); + } + #[inline] + /// consumes the instance to create another with the given initial state + pub fn with_default_state(self, initial_state: U) -> Self + where + U: IntoState, + { + Self { + initial_state: Some(initial_state.into_state()), + ..self + } + } + #[cfg(feature = "serde_json")] + /// serializes the current instance into a JSON string + pub fn to_json(&self) -> serde_json::Value + where + Self: serde::Serialize, + { + serde_json::to_value(self).expect("Failed to serialize the Program instance") + } + #[cfg(all(feature = "json", feature = "std"))] + /// export the program to a `.json` file at the given path + /// + /// **note**: there are no checks to see if the file already exists; it will automatically + /// be overwritten. + pub fn export_json

(&self, path: P) -> std::io::Result<()> + where + P: AsRef, + Self: serde::Serialize, + { + let path = path.as_ref(); + // ensure the filename ends with `.json` + if path.extension().map(|os| os.to_str()).flatten() != Some("json") { + #[cfg(feature = "tracing")] + tracing::error!( + "the provided path does not end with `.json`; consider changing the file extension" + ); + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidInput, + "the provided path does not end with `.json`", + )); + } + let serialized = serde_json::to_string_pretty(self).unwrap(); + std::fs::write(path, serialized)?; + #[cfg(feature = "tracing")] + tracing::info!("Program exported as JSON"); + Ok(()) + } + + pub fn get_head(&self, head: &Head) -> Option<&Tail> + where + R: Ruleset, + R::Rule: Instruction, Tail = Tail>, + { + self.rules().get(head) + } + + pub fn find_tail(&self, state: State<&Q>, sym: &A) -> Option<&Tail> + where + R: Ruleset, + R::Rule: Instruction, Tail = Tail>, + { + self.rules().find_tail(state, sym) + } +} diff --git a/core/src/programs/impls/impl_instruction_set_ext.rs b/crates/core/src/programs/impls/imp_program_base_ext.rs similarity index 62% rename from core/src/programs/impls/impl_instruction_set_ext.rs rename to crates/core/src/programs/impls/imp_program_base_ext.rs index fefe4968..569a7b59 100644 --- a/core/src/programs/impls/impl_instruction_set_ext.rs +++ b/crates/core/src/programs/impls/imp_program_base_ext.rs @@ -3,14 +3,15 @@ Created At: 2026.01.11:12:33:32 Contrib: @FL03 */ -use crate::programs::{InstructionSet, RuleSet}; +use crate::programs::{ProgramBase, RawRuleset}; use crate::rules::Instruction; use rstm_state::RawState; -impl core::fmt::Debug for InstructionSet +impl core::fmt::Debug for ProgramBase where - R: RuleSet + core::fmt::Debug, + R: RawRuleset + core::fmt::Debug, Q: RawState + core::fmt::Debug, + I: Instruction + core::fmt::Debug, { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { if let Some(initial_state) = &self.initial_state { @@ -25,10 +26,11 @@ where } } -impl core::fmt::Display for InstructionSet +impl core::fmt::Display for ProgramBase where - R: RuleSet + core::fmt::Debug, + R: RawRuleset + core::fmt::Debug, Q: RawState + core::fmt::Display, + I: Instruction + core::fmt::Debug + core::fmt::Display, { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { if let Some(initial_state) = &self.initial_state { @@ -43,12 +45,12 @@ where } } -impl IntoIterator for InstructionSet +impl IntoIterator for ProgramBase where I: Iterator, Q: RawState, X: Instruction, - R: RuleSet + IntoIterator, + R: RawRuleset + IntoIterator, { type Item = R::Item; type IntoIter = R::IntoIter; @@ -58,11 +60,11 @@ where } } -impl<'a, X, I, R, Q, A> IntoIterator for &'a InstructionSet +impl<'a, X, I, R, Q, A> IntoIterator for &'a ProgramBase where Q: RawState, X: 'a + Instruction, - R: RuleSet, + R: RawRuleset, I: Iterator, for<'b> &'b R: IntoIterator, { @@ -74,11 +76,11 @@ where } } -impl FromIterator for InstructionSet +impl FromIterator for ProgramBase where Q: RawState, X: Instruction, - R: RuleSet + FromIterator, + R: RawRuleset + FromIterator, { fn from_iter(iter: Iter) -> Self where @@ -87,3 +89,17 @@ where Self::from_rules(::from_iter(iter)) } } + +impl Extend for ProgramBase +where + Q: RawState, + X: Instruction, + R: RawRuleset + Extend, +{ + fn extend(&mut self, iter: Iter) + where + Iter: IntoIterator, + { + self.rules.extend(iter) + } +} diff --git a/crates/core/src/programs/impls/imp_program_base_repr.rs b/crates/core/src/programs/impls/imp_program_base_repr.rs new file mode 100644 index 00000000..3086f012 --- /dev/null +++ b/crates/core/src/programs/impls/imp_program_base_repr.rs @@ -0,0 +1,80 @@ +/* + Appellation: impl_program + Created At: 2026.01.11:12:33:32 + Contrib: @FL03 +*/ +use crate::programs::ProgramBase; +use crate::rules::Instruction; +use rstm_state::RawState; + +impl ProgramBase<[I], Q, A, I> +where + Q: RawState, + I: Instruction, +{ + /// returns an iterator over the elements. + pub fn iter(&self) -> core::slice::Iter<'_, I> { + self.rules.iter() + } + /// returns a mutable iterator over the elements. + pub fn iter_mut(&mut self) -> core::slice::IterMut<'_, I> { + self.rules.iter_mut() + } +} + +impl ProgramBase<&[I], Q, A, I> +where + Q: RawState, + I: Instruction, +{ + /// returns an iterator over the elements. + pub fn iter(&self) -> core::slice::Iter<'_, I> { + self.rules.iter() + } +} + +impl ProgramBase<&mut [I], Q, A, I> +where + Q: RawState, + I: Instruction, +{ + /// returns an iterator over the elements. + pub fn iter(&self) -> core::slice::Iter<'_, I> { + self.rules.iter() + } + /// returns a mutable iterator over the elements. + pub fn iter_mut(&mut self) -> core::slice::IterMut<'_, I> { + self.rules.iter_mut() + } +} + +impl ProgramBase<[I; N], Q, A> +where + Q: RawState, + I: Instruction, +{ + /// returns an iterator over the elements. + pub fn iter(&self) -> core::slice::Iter<'_, I> { + self.rules.iter() + } + /// returns a mutable iterator over the elements. + pub fn iter_mut(&mut self) -> core::slice::IterMut<'_, I> { + self.rules.iter_mut() + } +} + +#[cfg(feature = "alloc")] +impl ProgramBase, Q, A, I> +where + Q: RawState, + I: Instruction, +{ + /// returns an iterator over the elements. + pub fn iter(&self) -> core::slice::Iter<'_, I> { + self.rules.iter() + } + /// returns a mutable iterator over the elements. + pub fn iter_mut(&mut self) -> core::slice::IterMut<'_, I> { + self.rules.iter_mut() + } +} diff --git a/core/src/programs/impls/impl_program.rs b/crates/core/src/programs/instruction_set.rs similarity index 59% rename from core/src/programs/impls/impl_program.rs rename to crates/core/src/programs/instruction_set.rs index 7fd2770c..83ab6ab5 100644 --- a/core/src/programs/impls/impl_program.rs +++ b/crates/core/src/programs/instruction_set.rs @@ -1,27 +1,46 @@ /* - Appellation: impl_program - Created At: 2025.09.04:19:04:56 + Appellation: program + Created At: 2025.09.05:04:59:21 Contrib: @FL03 */ +#![allow(deprecated)] #![cfg(feature = "alloc")] -use crate::programs::Program; - use crate::{Head, Rule, RuleVec, Tail}; -use alloc::vec::Vec; +use alloc::vec::{self, Vec}; use rstm_state::{RawState, State}; -impl Program +#[deprecated(since = "0.1.4", note = "Use the `Program` implementation instead")] +/// The implementation is designed to provide a structured representation of a set +/// of rules and an optional initial state for a Turing machine or similar computational model. +/// It encapsulates the rules that dictate the machine's behavior and the starting point for +/// its execution. +#[derive(Clone, Debug, Default)] +#[cfg_attr( + feature = "serde", + derive(serde::Deserialize, serde::Serialize), + serde(deny_unknown_fields, rename_all = "snake_case") +)] +#[repr(C)] +pub struct InstructionSet +where + Q: RawState, +{ + pub(crate) initial_state: State, + pub(crate) rules: Vec>, +} + +impl InstructionSet where Q: RawState, { - /// initializes a new, empty instance of the [`Program`] + /// initializes a new, empty instance of the program pub const fn new(initial_state: Q) -> Self { Self { initial_state: State(initial_state), rules: Vec::new(), } } - /// returns a new instance of the [`Program`] using the given rules + /// returns a new instance of the program using the given rules pub fn from_rules(iter: I) -> Self where Q: Default, @@ -32,7 +51,7 @@ where rules: Vec::from_iter(iter), } } - /// Create a new instance of the [Program] using the given initial state. + /// Create a new instance of the program using the given initial state. pub fn from_state(initial_state: Q) -> Self { Self { initial_state: State(initial_state), @@ -43,7 +62,7 @@ where /// load a program from a `.json` file at the given path pub fn load_from_json>(path: P) -> crate::Result where - Program: serde::de::DeserializeOwned, + InstructionSet: serde::de::DeserializeOwned, { // open the file let file = std::fs::File::open(path)?; @@ -189,3 +208,129 @@ where Ok(()) } } + +impl InstructionSet +where + Q: RawState, +{ + #[cfg(feature = "serde_json")] + /// serializes the current instance into a JSON string + pub fn to_json(&self) -> serde_json::Value + where + A: serde::Serialize, + Q: serde::Serialize, + { + serde_json::to_value(self).expect("Failed to serialize the Program instance") + } +} + +impl AsRef<[Rule]> for InstructionSet +where + Q: RawState, +{ + fn as_ref(&self) -> &[Rule] { + &self.rules + } +} + +impl AsMut<[Rule]> for InstructionSet +where + Q: RawState, +{ + fn as_mut(&mut self) -> &mut [Rule] { + &mut self.rules + } +} + +impl core::ops::Deref for InstructionSet +where + Q: RawState, +{ + type Target = [Rule]; + + fn deref(&self) -> &Self::Target { + &self.rules + } +} + +impl core::ops::DerefMut for InstructionSet +where + Q: RawState, +{ + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.rules + } +} + +impl core::ops::Index> for InstructionSet +where + Q: RawState + PartialEq, + A: PartialEq, +{ + type Output = Tail; + + fn index(&self, index: Head) -> &Self::Output { + self.get(&index).unwrap() + } +} + +impl From>> for InstructionSet +where + Q: RawState + Default, +{ + fn from(rules: Vec>) -> Self { + Self::from_rules(rules) + } +} + +impl Extend> for InstructionSet +where + Q: RawState, +{ + fn extend>>(&mut self, iter: I) { + self.rules_mut().extend(iter) + } +} + +impl Extend<(Head, Tail)> for InstructionSet +where + Q: RawState, +{ + fn extend, Tail)>>(&mut self, iter: I) { + self.rules_mut() + .extend(iter.into_iter().map(|(head, tail)| Rule { head, tail })) + } +} + +impl FromIterator> for InstructionSet +where + Q: RawState + Default, +{ + fn from_iter>>(iter: I) -> Self { + Self { + initial_state: State::default(), + rules: iter.into_iter().collect::>(), + } + } +} + +impl FromIterator<(Head, Tail)> for InstructionSet +where + Q: RawState + Default, +{ + fn from_iter, Tail)>>(iter: I) -> Self { + Self::from_rules(iter.into_iter().map(|(head, tail)| Rule { head, tail })) + } +} + +impl IntoIterator for InstructionSet +where + Q: RawState, +{ + type Item = Rule; + type IntoIter = vec::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.rules.into_iter() + } +} diff --git a/crates/core/src/programs/mod.rs b/crates/core/src/programs/mod.rs new file mode 100644 index 00000000..3285c397 --- /dev/null +++ b/crates/core/src/programs/mod.rs @@ -0,0 +1,42 @@ +/* + Appellation: program + Created At: 2026.01.11:12:29:14 + Contrib: @FL03 +*/ +//! This module provides the [`ProgramBase`] implementation along with its associated aliases, +//! supporting traits, and more. +#[cfg(feature = "alloc")] +#[allow(deprecated)] +pub use self::instruction_set::InstructionSet; +#[doc(inline)] +pub use self::{program_base::ProgramBase, traits::*, types::*}; + +mod instruction_set; +mod program_base; + +mod impls { + mod imp_program_base; + mod imp_program_base_ext; + mod imp_program_base_repr; +} + +mod traits { + #[doc(inline)] + pub use self::ruleset::*; + + mod ruleset; +} + +mod types { + #[doc(inline)] + pub use self::aliases::*; + + mod aliases; +} + +#[doc(hidden)] +pub(crate) mod prelude { + pub use super::program_base::*; + pub use super::traits::*; + pub use super::types::*; +} diff --git a/crates/core/src/programs/program_base.rs b/crates/core/src/programs/program_base.rs new file mode 100644 index 00000000..bb3cd513 --- /dev/null +++ b/crates/core/src/programs/program_base.rs @@ -0,0 +1,48 @@ +/* + Appellation: program_base + Created At: 2026.01.11:12:34:11 + Contrib: @FL03 +*/ +use super::RawRuleset; +use crate::rules::Instruction; +use rstm_state::{RawState, State}; + +/// The [`ProgramBase`] struct is used to define a generic program capable of being executed by +/// a Turing machine or similar computational model. It consists of an optional initial state, +/// a set of rules (or instructions) used to indicate how the machine should *respond* under +/// different *circumstances*, and a marker to associate the generic parameters with the struct. +#[derive(Clone, Copy, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +#[cfg_attr( + feature = "serde", + derive(serde::Serialize, serde::Deserialize), + serde(deny_unknown_fields, rename_all = "snake_case") +)] +#[repr(C)] +pub struct ProgramBase>::Rule> +where + Q: RawState, + R: RawRuleset, + I: Instruction, +{ + pub(crate) initial_state: Option>, + pub(crate) _marker: core::marker::PhantomData<(I, Q, A)>, + pub(crate) rules: R, +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::rules::{Direction, Rule}; + + #[test] + fn test_program_base() { + let rule = Rule::from_parts(0, 'a', Direction::Right, 1, 'b'); + + let program = ProgramBase { + initial_state: Some(State::new(0)), + _marker: core::marker::PhantomData, + rules: [rule], + }; + assert_eq!(program.initial_state, Some(State::new(0))); + } +} diff --git a/crates/core/src/programs/traits/ruleset.rs b/crates/core/src/programs/traits/ruleset.rs new file mode 100644 index 00000000..bd987bd1 --- /dev/null +++ b/crates/core/src/programs/traits/ruleset.rs @@ -0,0 +1,399 @@ +/* + Appellation: instruction_set + Created At: 2026.01.11:12:29:41 + Contrib: @FL03 +*/ +use crate::rules::{Head, Instruction, InstructionMut, Rule, Tail}; +use rstm_state::{RawState, State}; + +/// The [`RawRuleset`] trait establishes an interface common to all compatible sets of rules for +/// the framework. +pub trait RawRuleset +where + Q: RawState, +{ + type Rule: Instruction; + + private! {} +} + +pub trait Ruleset: RawRuleset +where + Q: RawState, + Self::Rule: Instruction, Tail = Tail>, +{ + fn get(&self, head: &Head) -> Option<&Tail>; + + fn find_tail(&self, state: State<&Q>, sym: &A) -> Option<&Tail>; +} + +pub trait RuleSetMut: RawRuleset +where + Q: RawState, + Self::Rule: Instruction, Tail = Tail>, +{ + fn get_mut(&mut self, head: &Head) -> Option<&mut Tail>; +} +/* + ************* Implementations ************* +*/ + +impl RawRuleset for &R +where + I: Instruction, + Q: RawState, + R: RawRuleset, +{ + type Rule = R::Rule; + + seal! {} +} + +macro_rules! get_tail { + ($iter:expr, $head:expr) => { + $iter.find_map(|i| { + if i.head().state() == $head.state() && i.head().symbol() == $head.symbol() { + Some(i.tail()) + } else { + None + } + }) + }; +} + +macro_rules! find_tail { + ($iter:expr, ($state:expr, $sym:expr)) => { + $iter.find_map(|i| { + if i.head().state().view() == $state && i.head().symbol() == $sym { + Some(i.tail()) + } else { + None + } + }) + }; +} + +impl RawRuleset for [I] +where + Q: RawState, + I: Instruction, +{ + type Rule = I; + + seal! {} +} + +impl Ruleset for [I] +where + Q: RawState + PartialEq, + A: PartialEq, + I: Instruction, Tail = Tail>, +{ + fn get(&self, head: &Head) -> Option<&Tail> { + get_tail!(self.iter(), head) + } + + fn find_tail(&self, state: State<&Q>, sym: &A) -> Option<&Tail> { + find_tail!(self.iter(), (state, sym)) + } +} +impl RawRuleset for &[I] +where + Q: RawState, + I: Instruction, +{ + type Rule = I; + + seal! {} +} + +impl Ruleset for &[I] +where + Q: RawState + PartialEq, + A: PartialEq, + I: Instruction, Tail = Tail>, +{ + fn get(&self, head: &Head) -> Option<&Tail> { + get_tail!(self.iter(), head) + } + + fn find_tail(&self, state: State<&Q>, sym: &A) -> Option<&Tail> { + find_tail!(self.iter(), (state, sym)) + } +} + +impl RawRuleset for &mut [I] +where + Q: RawState, + I: Instruction, +{ + type Rule = I; + + seal! {} +} + +impl Ruleset for &mut [I] +where + Q: RawState + PartialEq, + A: PartialEq, + I: Instruction, Tail = Tail>, +{ + fn get(&self, head: &Head) -> Option<&Tail> { + get_tail!(self.iter(), head) + } + + fn find_tail(&self, state: State<&Q>, sym: &A) -> Option<&Tail> { + find_tail!(self.iter(), (state, sym)) + } +} + +impl RuleSetMut for &mut [I] +where + Q: RawState + PartialEq, + A: PartialEq, + I: InstructionMut, Tail = Tail>, +{ + fn get_mut(&mut self, head: &Head) -> Option<&mut Tail> { + self.iter_mut().find_map(|i| { + if i.head() == head { + Some(i.tail_mut()) + } else { + None + } + }) + } +} + +impl RawRuleset for [I; N] +where + Q: RawState, + I: Instruction, +{ + type Rule = I; + + seal! {} +} + +impl Ruleset for [I; N] +where + Q: RawState + PartialEq, + A: PartialEq, + I: Instruction, Tail = Tail>, +{ + fn get(&self, head: &Head) -> Option<&Tail> { + get_tail!(self.iter(), head) + } + + fn find_tail(&self, state: State<&Q>, sym: &A) -> Option<&Tail> { + find_tail!(self.iter(), (state, sym)) + } +} + +#[cfg(feature = "alloc")] +mod impl_alloc { + use super::{RawRuleset, Ruleset}; + use crate::{Head, Instruction, Rule, Tail}; + use alloc::collections::{BTreeMap, BTreeSet}; + use alloc::vec::Vec; + use rstm_state::{RawState, State}; + + impl RawRuleset for Vec + where + Q: RawState, + I: Instruction, + { + type Rule = I; + + seal! {} + } + + impl Ruleset for Vec + where + Q: RawState + PartialEq, + A: PartialEq, + I: Instruction, Tail = Tail>, + { + fn get(&self, head: &Head) -> Option<&Tail> { + get_tail!(self.iter(), head) + } + + fn find_tail(&self, state: State<&Q>, sym: &A) -> Option<&Tail> { + find_tail!(self.iter(), (state, sym)) + } + } + + impl RawRuleset for BTreeSet + where + Q: RawState, + I: Instruction, + { + type Rule = I; + seal! {} + } + + impl Ruleset for BTreeSet + where + Q: RawState + PartialEq, + A: PartialEq, + I: Instruction, Tail = Tail>, + { + fn get(&self, head: &Head) -> Option<&Tail> { + get_tail!(self.iter(), head) + } + + fn find_tail(&self, state: State<&Q>, sym: &A) -> Option<&Tail> { + find_tail!(self.iter(), (state, sym)) + } + } + + impl RawRuleset for BTreeMap, Tail> + where + Q: RawState + Ord, + A: Ord, + { + type Rule = Rule; + + seal! {} + } + impl Ruleset for BTreeMap, Tail> + where + Q: RawState + Ord, + A: Ord, + { + fn get(&self, head: &Head) -> Option<&Tail> { + self.get(head) + } + + fn find_tail(&self, state: State<&Q>, sym: &A) -> Option<&Tail> { + self.iter().find_map(|(h, t)| { + if h.state().view() == state && h.symbol() == sym { + Some(t) + } else { + None + } + }) + } + } +} + +#[cfg(feature = "hashbrown")] +mod impl_hashbrown { + use super::*; + use core::hash::Hash; + use hashbrown::{HashMap, HashSet}; + + impl RawRuleset for HashSet> + where + Q: RawState + Eq + Hash, + A: Eq + Hash, + { + type Rule = Rule; + + seal! {} + } + + impl Ruleset for HashSet> + where + Q: RawState + Eq + Hash, + A: Eq + Hash, + { + fn get(&self, head: &Head) -> Option<&Tail> { + get_tail!(self.iter(), head) + } + + fn find_tail(&self, state: State<&Q>, sym: &A) -> Option<&Tail> { + find_tail!(self.iter(), (state, sym)) + } + } + + impl RawRuleset for HashMap, Tail> + where + Q: RawState + Eq + Hash, + A: Eq + Hash, + { + type Rule = Rule; + + seal! {} + } + + impl Ruleset for HashMap, Tail> + where + Q: RawState + Eq + Hash, + A: Eq + Hash, + { + fn get(&self, head: &Head) -> Option<&Tail> { + self.get(head) + } + + fn find_tail(&self, state: State<&Q>, sym: &A) -> Option<&Tail> { + self.iter().find_map(|(h, t)| { + if h.state().view() == state && h.symbol() == sym { + Some(t) + } else { + None + } + }) + } + } +} + +#[cfg(feature = "std")] +mod impl_std { + use super::*; + use core::hash::Hash; + use std::collections::{HashMap, HashSet}; + + impl RawRuleset for HashSet> + where + Q: RawState + Eq + Hash, + A: Eq + Hash, + { + type Rule = Rule; + + seal! {} + } + + impl Ruleset for HashSet> + where + Q: RawState + Eq + Hash, + A: Eq + Hash, + { + fn get(&self, head: &Head) -> Option<&Tail> { + get_tail!(self.iter(), head) + } + + fn find_tail(&self, state: State<&Q>, sym: &A) -> Option<&Tail> { + find_tail!(self.iter(), (state, sym)) + } + } + + impl RawRuleset for HashMap, Tail> + where + Q: RawState + Eq + Hash, + A: Eq + Hash, + { + type Rule = Rule; + + seal! {} + } + + impl Ruleset for HashMap, Tail> + where + Q: RawState + Eq + Hash, + A: Eq + Hash, + { + fn get(&self, head: &Head) -> Option<&Tail> { + self.get(head) + } + + fn find_tail(&self, state: State<&Q>, sym: &A) -> Option<&Tail> { + self.iter().find_map(|(h, t)| { + if h.state() == *state && h.symbol() == sym { + Some(t) + } else { + None + } + }) + } + } +} diff --git a/crates/core/src/programs/types/aliases.rs b/crates/core/src/programs/types/aliases.rs new file mode 100644 index 00000000..66666df7 --- /dev/null +++ b/crates/core/src/programs/types/aliases.rs @@ -0,0 +1,42 @@ +/* + Appellation: aliases + Created At: 2026.01.11:15:06:06 + Contrib: @FL03 +*/ +use crate::programs::program_base::ProgramBase; +use crate::rules::Rule; +#[cfg(feature = "alloc")] +use crate::rules::{Head, Tail}; + +#[cfg(feature = "alloc")] +use alloc::{ + collections::{BTreeMap, BTreeSet}, + vec::Vec, +}; +#[cfg(feature = "hashbrown")] +use hashbrown::{HashMap, HashSet}; +#[cfg(all(not(feature = "hashbrown"), feature = "std"))] +use std::collections::{HashMap, HashSet}; + +/// A type alias for a [`ProgramBase`] configured to use a slice of rules as the ruleset, with default generic parameters for the state and action types +pub type ProgramSlice = ProgramBase<[Rule], Q, A>; + +pub type ProgramArray = ProgramBase<[Rule; N], Q, A>; +#[cfg(feature = "alloc")] +/// a type alias for a [`ProgramBase`] using a [`Vec`] as the ruleset +pub type Program = ProgramBase>, Q, A>; + +#[cfg(feature = "alloc")] +pub type ProgramBSet = ProgramBase>, Q, A>; + +#[cfg(feature = "alloc")] +pub type ProgramBMap = ProgramBase, Tail>, Q, A>; + +#[cfg(any(feature = "hashbrown", feature = "std"))] +/// a type alias for a [`ProgramBase`] using a [`HashMap`] as the ruleset, using the head +/// as key and the tail as value +pub type ProgramMap = ProgramBase, Tail>, Q, A>; +#[cfg(any(feature = "hashbrown", feature = "std"))] +/// a type alias for a [`ProgramBase`] using a [`HashSet`] consisting of rules as the +/// store +pub type ProgramSet = ProgramBase>, Q, A>; diff --git a/core/src/rules/head.rs b/crates/core/src/rules/head.rs similarity index 54% rename from core/src/rules/head.rs rename to crates/core/src/rules/head.rs index d7c29397..9ae76aea 100644 --- a/core/src/rules/head.rs +++ b/crates/core/src/rules/head.rs @@ -11,19 +11,6 @@ pub type HeadMut<'a, Q, S> = Head<&'a mut Q, &'a mut S>; /// a type alias for a [`Head`] containing a reference to the state and a mutable reference to /// the symbol pub type HeadEntry<'a, Q, S> = Head<&'a Q, &'a mut S>; -/// [`RawHead`] is a marker trait used to define an interface for objects capable of being -/// used as a _head_ in the context of Turing machine rules. -pub trait RawHead { - type State: RawState; - type Symbol; - /// returns a reference to the current state of the head - fn state(&self) -> &State; - /// returns a reference to the symbol of the head - fn symbol(&self) -> &Self::Symbol; - - private! {} -} - /// The [`Head`] of a Turing machine is defined to be a two-tuple consisting of a state and a /// symbol. Our implementation is generic over both the state and symbol types, allowing for /// flexibility in their representation(s). @@ -40,6 +27,44 @@ pub struct Head { #[cfg_attr(feature = "serde", serde(alias = "current_symbol"))] pub symbol: A, } +/// [`RawHead`] is a marker trait used to define an interface for objects capable of being +/// used as a _head_ in the context of Turing machine rules. +pub trait RawHead { + type State: RawState; + type Symbol; + /// returns a reference to the current state of the head + fn state(&self) -> &State; + /// returns a reference to the symbol of the head + fn symbol(&self) -> &Self::Symbol; + + private! {} +} +/// The [`RawHeadMut`] trait extends the [`RawHead`] trait by providing mutable access to +pub trait RawHeadMut: RawHead { + /// returns a mutable reference to the current state of the head + fn state_mut(&mut self) -> &mut State; + /// returns a mutable reference to the symbol of the head + fn symbol_mut(&mut self) -> &mut Self::Symbol; +} +/// The [`HeadRepr`] trait extends the [`RawHead`] trait with standard initialization routines. +pub trait HeadRepr: RawHead + Sized { + /// creates a new head from the given state and symbol + fn new(state: Self::State, symbol: Self::Symbol) -> Self; + /// create a new head from the given state, using a default symbol + fn from_state(state: Self::State) -> Self + where + Self::Symbol: Default, + { + Self::new(state, Default::default()) + } + /// create a new head from the given symbol, using a default state + fn from_symbol(symbol: Self::Symbol) -> Self + where + Self::State: Default, + { + Self::new(Default::default(), symbol) + } +} /* ************* Implementations ************* @@ -61,6 +86,30 @@ where } } +impl RawHeadMut for (State, A) +where + Q: RawState, +{ + /// returns a mutable reference to the state. + fn state_mut(&mut self) -> &mut State { + &mut self.0 + } + /// returns a mutable reference to the symbol. + fn symbol_mut(&mut self) -> &mut A { + &mut self.1 + } +} + +impl HeadRepr for (State, A) +where + Q: RawState, +{ + /// creates a new head from the given state and symbol + fn new(state: Q, symbol: A) -> Self { + (State(state), symbol) + } +} + impl RawHead for Head where Q: RawState, @@ -78,6 +127,32 @@ where } } +impl RawHeadMut for Head +where + Q: RawState, +{ + /// returns a mutable reference to the state. + fn state_mut(&mut self) -> &mut State { + &mut self.state + } + /// returns a mutable reference to the symbol. + fn symbol_mut(&mut self) -> &mut A { + &mut self.symbol + } +} + +impl HeadRepr for Head +where + Q: RawState, +{ + /// creates a new head from the given state and symbol + fn new(state: Q, symbol: A) -> Self { + Self { + state: State(state), + symbol, + } + } +} #[cfg(test)] mod tests { use super::Head; diff --git a/core/src/rules/impls/impl_head.rs b/crates/core/src/rules/impls/impl_head.rs similarity index 100% rename from core/src/rules/impls/impl_head.rs rename to crates/core/src/rules/impls/impl_head.rs diff --git a/core/src/rules/impls/impl_head_ext.rs b/crates/core/src/rules/impls/impl_head_ext.rs similarity index 78% rename from core/src/rules/impls/impl_head_ext.rs rename to crates/core/src/rules/impls/impl_head_ext.rs index d2858031..487c68ed 100644 --- a/core/src/rules/impls/impl_head_ext.rs +++ b/crates/core/src/rules/impls/impl_head_ext.rs @@ -15,13 +15,61 @@ where A::Output: Clone, { type Buf<_T> = [_T]; - type Output = T; + type Output = A::Output; fn read(&mut self, rhs: &mut Self::Buf) -> Self::Output { rhs[self.symbol].clone() } } +impl<'a, Q, A> Read<&'a [A]> for Head +where + Q: RawState, +{ + type Output = &'a A; + type Error = crate::Error; + + fn read(self, rhs: &'a [A]) -> Result { + let pos = self.symbol; + if pos >= rhs.len() { + return Err(crate::Error::index_out_of_bounds(pos, rhs.len())); + } + Ok(&rhs[pos]) + } +} + +impl<'a, Q, A> Read<&'a [A]> for &Head +where + Q: RawState, +{ + type Output = &'a A; + type Error = crate::Error; + + fn read(self, rhs: &'a [A]) -> Result { + let pos = self.symbol; + if pos >= rhs.len() { + return Err(crate::Error::index_out_of_bounds(pos, rhs.len())); + } + Ok(&rhs[pos]) + } +} + +impl<'a, Q, A> Read<&'a [A]> for &mut Head +where + Q: RawState, +{ + type Output = &'a A; + type Error = crate::Error; + + fn read(self, rhs: &'a [A]) -> Result { + let pos = self.symbol; + if pos >= rhs.len() { + return Err(crate::Error::index_out_of_bounds(pos, rhs.len())); + } + Ok(&rhs[pos]) + } +} + impl<'a, Q, A> Read<&'a mut [A]> for Head where Q: RawState, @@ -174,7 +222,7 @@ where A: PartialEq, { fn eq(&self, head: &Head) -> bool { - &self.0 == &head.state && &self.1 == &head.symbol + self.0 == head.state && self.1 == head.symbol } } @@ -185,7 +233,7 @@ where A: PartialEq, { fn eq(&self, (state, symbol): &(Q, A)) -> bool { - &self.state == state && &self.symbol == symbol + self.state.get() == state && &self.symbol == symbol } } @@ -195,7 +243,7 @@ where A: PartialEq, { fn eq(&self, head: &Head) -> bool { - head.state == &self.0 && &head.symbol == &self.1 + head.state == self.0 && head.symbol == self.1 } } diff --git a/core/src/rules/impls/impl_head_repr.rs b/crates/core/src/rules/impls/impl_head_repr.rs similarity index 96% rename from core/src/rules/impls/impl_head_repr.rs rename to crates/core/src/rules/impls/impl_head_repr.rs index e655079f..65cb5366 100644 --- a/core/src/rules/impls/impl_head_repr.rs +++ b/crates/core/src/rules/impls/impl_head_repr.rs @@ -69,7 +69,11 @@ where Q: RawState, { /// load the head into an engine loaded with the given program - pub fn load(self, program: crate::Program) -> EngineBase { + pub fn load(self, program: crate::Program) -> EngineBase + where + Q: PartialEq, + A: PartialEq, + { EngineBase::from_driver(self).with_program(program) } diff --git a/core/src/rules/impls/impl_learned_rule.rs b/crates/core/src/rules/impls/impl_learned_rule.rs similarity index 100% rename from core/src/rules/impls/impl_learned_rule.rs rename to crates/core/src/rules/impls/impl_learned_rule.rs diff --git a/core/src/rules/impls/impl_rule.rs b/crates/core/src/rules/impls/impl_rule.rs similarity index 97% rename from core/src/rules/impls/impl_rule.rs rename to crates/core/src/rules/impls/impl_rule.rs index 46c92fd8..9a128a21 100644 --- a/core/src/rules/impls/impl_rule.rs +++ b/crates/core/src/rules/impls/impl_rule.rs @@ -48,11 +48,11 @@ where pub const fn head_mut(&mut self) -> &mut Head { &mut self.head } - /// returns an immutable reference to the [Tail] of the [Instruction] + /// returns an immutable reference to the [Tail] of the [`Rule`] pub const fn tail(&self) -> &Tail { &self.tail } - /// returns a mutable reference to the [Tail] of the [Instruction] + /// returns a mutable reference to the [Tail] of the [`Rule`] pub const fn tail_mut(&mut self) -> &mut Tail { &mut self.tail } diff --git a/core/src/rules/impls/impl_rule_builder.rs b/crates/core/src/rules/impls/impl_rule_builder.rs similarity index 100% rename from core/src/rules/impls/impl_rule_builder.rs rename to crates/core/src/rules/impls/impl_rule_builder.rs diff --git a/core/src/rules/impls/impl_rule_ext.rs b/crates/core/src/rules/impls/impl_rule_ext.rs similarity index 100% rename from core/src/rules/impls/impl_rule_ext.rs rename to crates/core/src/rules/impls/impl_rule_ext.rs diff --git a/core/src/rules/impls/impl_rule_repr.rs b/crates/core/src/rules/impls/impl_rule_repr.rs similarity index 96% rename from core/src/rules/impls/impl_rule_repr.rs rename to crates/core/src/rules/impls/impl_rule_repr.rs index 10fe803e..2a8a48ce 100644 --- a/core/src/rules/impls/impl_rule_repr.rs +++ b/crates/core/src/rules/impls/impl_rule_repr.rs @@ -7,7 +7,7 @@ use crate::rules::rule::Rule; use crate::rules::{Head, Tail}; use rstm_state::RawState; -impl<'a, Q, A, R, B> Rule<&'a Q, &'a A, &'a R, &'a B> +impl Rule<&Q, &A, &R, &B> where Q: RawState, R: RawState, @@ -40,7 +40,7 @@ where } } -impl<'a, Q, A> Rule +impl Rule where Q: RawState, { diff --git a/core/src/rules/impls/impl_tail.rs b/crates/core/src/rules/impls/impl_tail.rs similarity index 97% rename from core/src/rules/impls/impl_tail.rs rename to crates/core/src/rules/impls/impl_tail.rs index 33f4f31b..867eb9fe 100644 --- a/core/src/rules/impls/impl_tail.rs +++ b/crates/core/src/rules/impls/impl_tail.rs @@ -54,7 +54,8 @@ where pub fn into_tuple(self) -> (Direction, State, A) { (self.direction, self.next_state, self.write_symbol) } - /// returns the direction the [head](StdHead) is instructed to move + /// returns a copy of the direction the head should *shift* after writing the symbol and + /// updating the state. pub const fn direction(&self) -> Direction { self.direction } diff --git a/core/src/rules/impls/impl_tail_ext.rs b/crates/core/src/rules/impls/impl_tail_ext.rs similarity index 95% rename from core/src/rules/impls/impl_tail_ext.rs rename to crates/core/src/rules/impls/impl_tail_ext.rs index 4991f4e7..2fd0f0c3 100644 --- a/core/src/rules/impls/impl_tail_ext.rs +++ b/crates/core/src/rules/impls/impl_tail_ext.rs @@ -129,8 +129,8 @@ where { fn eq(&self, (other_direction, other_head): &(Direction, Head)) -> bool { &self.direction == other_direction - && &self.next_state == &other_head.state - && &self.write_symbol == &other_head.symbol + && self.next_state == other_head.state + && self.write_symbol == other_head.symbol } } @@ -172,6 +172,6 @@ where A: PartialEq, { fn eq(&self, other: &Tail) -> bool { - &self.0 == &other.next_state && &self.1 == &other.write_symbol + self.0 == other.next_state && self.1 == other.write_symbol } } diff --git a/core/src/rules/impls/impl_tail_repr.rs b/crates/core/src/rules/impls/impl_tail_repr.rs similarity index 100% rename from core/src/rules/impls/impl_tail_repr.rs rename to crates/core/src/rules/impls/impl_tail_repr.rs diff --git a/core/src/rules/mod.rs b/crates/core/src/rules/mod.rs similarity index 100% rename from core/src/rules/mod.rs rename to crates/core/src/rules/mod.rs diff --git a/core/src/rules/rule.rs b/crates/core/src/rules/rule.rs similarity index 100% rename from core/src/rules/rule.rs rename to crates/core/src/rules/rule.rs diff --git a/crates/core/src/rules/tail.rs b/crates/core/src/rules/tail.rs new file mode 100644 index 00000000..2627ac01 --- /dev/null +++ b/crates/core/src/rules/tail.rs @@ -0,0 +1,193 @@ +/* + Appellation: tail + Created At: 2025.12.15:21:29:04 + Contrib: @FL03 +*/ +use crate::Direction; +use rstm_state::{RawState, State}; + +/// A type alias for a [`Tail`] containing immutable references to the next state and symbol. +pub type TailRef<'a, Q, A> = Tail<&'a Q, &'a A>; +/// A type alias for a [`Tail`] containing mutable references to the next state and symbol. +pub type TailMut<'a, Q, A> = Tail<&'a mut Q, &'a mut A>; +/// The [`Tail`] of a rule defines the _reaction_ of the actor under specific conditions. +/// Specifically, it defines the next state, the symbol to write, and the direction to move +#[derive(Clone, Copy, Default, PartialEq, Eq, Hash, Ord, PartialOrd)] +#[cfg_attr( + feature = "serde", + derive(serde::Deserialize, serde::Serialize), + serde(deny_unknown_fields, rename_all = "snake_case") +)] +#[repr(C)] +pub struct Tail { + /// defines the direction to move after writing the symbol + #[cfg_attr(feature = "serde", serde(alias = "move_direction", alias = "dir"))] + pub direction: Direction, + #[cfg_attr(feature = "serde", serde(alias = "write_state"))] + pub next_state: State, + #[cfg_attr(feature = "serde", serde(alias = "next_symbol"))] + pub write_symbol: A, +} +/// [`RawTail`] is a sealed marker trait used to denote objects capable of being used to +/// represent the _tail_ of a rule for a Turing machine. +pub trait RawTail { + type State: RawState; + type Symbol; + private! {} + /// returns the direction of the tail. + fn direction(&self) -> Direction; + /// returns an immutable reference to the next state. + fn next_state(&self) -> &State; + /// returns a reference to the symbol configured for the head to write next. + fn write_symbol(&self) -> &Self::Symbol; +} +/// The [`RawTailMut`] provides mutable access to the components of a tail. +pub trait RawTailMut: RawTail { + /// returns a mutable reference to the direction of the tail. + fn direction_mut(&mut self) -> &mut Direction; + /// returns a mutable reference to the next state. + fn next_state_mut(&mut self) -> &mut State; + /// returns a mutable reference to the symbol to write. + fn write_symbol_mut(&mut self) -> &mut Self::Symbol; +} +/// The [`TailRepr`] trait extends the [`RawTail`] trait with standard initialization routines. +pub trait TailRepr: RawTail + Sized { + /// creates a new tail from the given direction, next state, and symbol to write + fn new(direction: Direction, next_state: Self::State, write_symbol: Self::Symbol) -> Self; + /// creates a new tail that moves right after writing the symbol and transitioning to the + /// next state + fn right(next_state: Self::State, write_symbol: Self::Symbol) -> Self { + Self::new(Direction::Right, next_state, write_symbol) + } + /// creates a new tail that moves left after writing the symbol and transitioning to the + /// next state + fn left(next_state: Self::State, write_symbol: Self::Symbol) -> Self { + Self::new(Direction::Left, next_state, write_symbol) + } + fn stay(next_state: Self::State, write_symbol: Self::Symbol) -> Self { + Self::new(Direction::Stay, next_state, write_symbol) + } +} +/* + ************* Implementations ************* +*/ +impl RawTail for (Direction, State, A) +where + Q: RawState, +{ + type State = Q; + type Symbol = A; + + seal! {} + /// returns the direction of the tail. + fn direction(&self) -> Direction { + self.0 + } + /// returns an immutable reference to the next state. + fn next_state(&self) -> &State { + &self.1 + } + /// returns an immutable reference to the symbol to write. + fn write_symbol(&self) -> &A { + &self.2 + } +} + +impl RawTailMut for (Direction, State, A) +where + Q: RawState, +{ + /// returns a mutable reference to the direction of the tail. + fn direction_mut(&mut self) -> &mut Direction { + &mut self.0 + } + /// returns a mutable reference to the next state. + fn next_state_mut(&mut self) -> &mut State { + &mut self.1 + } + /// returns a mutable reference to the symbol to write. + fn write_symbol_mut(&mut self) -> &mut A { + &mut self.2 + } +} + +impl TailRepr for (Direction, State, A) +where + Q: RawState, +{ + /// creates a new tail from the given direction, next state, and symbol to write + fn new(direction: Direction, next_state: Q, write_symbol: A) -> Self { + (direction, State(next_state), write_symbol) + } +} + +impl RawTail for Tail +where + Q: RawState, +{ + type State = Q; + type Symbol = A; + + seal! {} + /// returns the direction of the tail. + fn direction(&self) -> Direction { + self.direction + } + /// returns an immutable reference to the next state. + fn next_state(&self) -> &State { + &self.next_state + } + /// returns an immutable reference to the symbol to write. + fn write_symbol(&self) -> &A { + &self.write_symbol + } +} +impl RawTailMut for Tail +where + Q: RawState, +{ + /// returns a mutable reference to the direction of the tail. + fn direction_mut(&mut self) -> &mut Direction { + &mut self.direction + } + /// returns a mutable reference to the next state. + fn next_state_mut(&mut self) -> &mut State { + &mut self.next_state + } + /// returns a mutable reference to the symbol to write. + fn write_symbol_mut(&mut self) -> &mut A { + &mut self.write_symbol + } +} + +impl TailRepr for Tail +where + Q: RawState, +{ + /// creates a new tail from the given direction, next state, and symbol to write + fn new(direction: Direction, next_state: Q, write_symbol: A) -> Self { + Self { + direction, + next_state: State(next_state), + write_symbol, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_tail_init() { + let tail: Tail<&str, char> = Tail::right("q1", 'a'); + assert_eq! { + tail, + ( + Direction::Right, + State("q1"), + 'a' + ) + } + } +} diff --git a/core/src/rules/traits/convert.rs b/crates/core/src/rules/traits/convert.rs similarity index 100% rename from core/src/rules/traits/convert.rs rename to crates/core/src/rules/traits/convert.rs diff --git a/crates/core/src/rules/traits/instruction.rs b/crates/core/src/rules/traits/instruction.rs new file mode 100644 index 00000000..d038a242 --- /dev/null +++ b/crates/core/src/rules/traits/instruction.rs @@ -0,0 +1,179 @@ +/* + Appellation: instruction + Created At: 2026.01.15:11:50:07 + Contrib: @FL03 +*/ +use crate::rules::{Head, RawHead, RawTail, Rule, Tail}; +use rstm_state::{RawState, State}; + +/// The [`Instruction`] trait establishes the base interface for all compatible rules for the +/// automata. +pub trait Instruction +where + Q: RawState, +{ + /// the type of head used by the instruction + type Head: RawHead; + /// the type of tail used by the instruction + type Tail: RawTail; + /// returns a reference to the head of the instruction + fn head(&self) -> &Self::Head; + /// returns a reference to the tail of the instruction + fn tail(&self) -> &Self::Tail; + /// returns a reference to the current state + fn current_state(&self) -> &State; + /// returns a reference to the current symbol + fn symbol(&self) -> &A; + /// returns the direction of the tail + fn direction(&self) -> crate::Direction { + self.tail().direction() + } + /// returns a reference to the next state + fn next_state(&self) -> &State; + /// returns a reference to the next symbol + fn next_symbol(&self) -> &A; +} + +pub trait InstructionMut: Instruction +where + Q: RawState, +{ + /// returns a mutable reference to the head of the instruction + fn head_mut(&mut self) -> &mut Self::Head; + /// returns a mutable reference to the tail of the instruction + fn tail_mut(&mut self) -> &mut Self::Tail; + /// returns a mutable reference to the current state + fn current_state_mut(&mut self) -> &mut State; + /// returns a mutable reference to the current symbol + fn symbol_mut(&mut self) -> &mut A; + /// returns a mutable reference to the next state + fn next_state_mut(&mut self) -> &mut State; + /// returns a mutable reference to the next symbol + fn next_symbol_mut(&mut self) -> &mut A; +} + +/* + ************* Implementations ************* +*/ + +impl Instruction for (Head, Tail) +where + Q: RawState, +{ + type Head = Head; + type Tail = Tail; + + fn head(&self) -> &Self::Head { + &self.0 + } + + fn tail(&self) -> &Self::Tail { + &self.1 + } + + fn current_state(&self) -> &State { + self.head().state() + } + + fn symbol(&self) -> &A { + self.head().symbol() + } + + fn next_state(&self) -> &State { + self.tail().next_state() + } + + fn next_symbol(&self) -> &A { + self.tail().write_symbol() + } +} + +impl Instruction for Rule +where + Q: RawState, +{ + type Head = Head; + type Tail = Tail; + + fn head(&self) -> &Self::Head { + &self.head + } + + fn tail(&self) -> &Self::Tail { + &self.tail + } + + fn current_state(&self) -> &State { + self.head().state() + } + + fn symbol(&self) -> &A { + self.head().symbol() + } + + fn next_state(&self) -> &State { + self.tail().next_state() + } + + fn next_symbol(&self) -> &A { + self.tail().write_symbol() + } +} + +impl InstructionMut for Rule +where + Q: RawState, +{ + fn head_mut(&mut self) -> &mut Self::Head { + &mut self.head + } + + fn tail_mut(&mut self) -> &mut Self::Tail { + &mut self.tail + } + + fn current_state_mut(&mut self) -> &mut State { + self.head_mut().state_mut() + } + + fn symbol_mut(&mut self) -> &mut A { + self.head_mut().symbol_mut() + } + + fn next_state_mut(&mut self) -> &mut State { + self.tail_mut().state_mut() + } + + fn next_symbol_mut(&mut self) -> &mut A { + self.tail_mut().symbol_mut() + } +} + +impl InstructionMut for (Head, Tail) +where + Q: RawState, +{ + fn head_mut(&mut self) -> &mut Self::Head { + &mut self.0 + } + + fn tail_mut(&mut self) -> &mut Self::Tail { + &mut self.1 + } + + fn current_state_mut(&mut self) -> &mut State { + self.head_mut().state_mut() + } + + fn symbol_mut(&mut self) -> &mut A { + self.head_mut().symbol_mut() + } + + fn next_state_mut(&mut self) -> &mut State { + self.tail_mut().state_mut() + } + + fn next_symbol_mut(&mut self) -> &mut A { + self.tail_mut().symbol_mut() + } +} diff --git a/core/src/rules/traits/rulespace.rs b/crates/core/src/rules/traits/rulespace.rs similarity index 100% rename from core/src/rules/traits/rulespace.rs rename to crates/core/src/rules/traits/rulespace.rs diff --git a/core/src/rules/types/aliases.rs b/crates/core/src/rules/types/aliases.rs similarity index 100% rename from core/src/rules/types/aliases.rs rename to crates/core/src/rules/types/aliases.rs diff --git a/core/src/rules/types/direction.rs b/crates/core/src/rules/types/direction.rs similarity index 97% rename from core/src/rules/types/direction.rs rename to crates/core/src/rules/types/direction.rs index d40b1dbd..a4717d76 100644 --- a/core/src/rules/types/direction.rs +++ b/crates/core/src/rules/types/direction.rs @@ -10,6 +10,7 @@ Clone, Copy, Debug, + Default, Eq, Hash, Ord, @@ -24,7 +25,11 @@ strum::VariantArray, strum::VariantNames, )] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr( + feature = "serde", + derive(serde::Deserialize, serde::Serialize), + serde(untagged) +)] #[strum(serialize_all = "lowercase")] pub enum Direction { /// Represents a single left shift @@ -43,6 +48,7 @@ pub enum Direction { feature = "serde", serde(alias = "stay", alias = "s", alias = "S", alias = "STAY",) )] + #[default] /// Represents no movement Stay = 0, } @@ -114,12 +120,6 @@ impl Direction { } } -impl Default for Direction { - fn default() -> Self { - Self::Stay - } -} - impl core::ops::Add for Direction where T: core::ops::Add + core::ops::Sub + num_traits::One, diff --git a/core/src/utils/range.rs b/crates/core/src/utils/range.rs similarity index 100% rename from core/src/utils/range.rs rename to crates/core/src/utils/range.rs diff --git a/core/tests/default.rs b/crates/core/tests/default.rs similarity index 100% rename from core/tests/default.rs rename to crates/core/tests/default.rs diff --git a/core/tests/engine.rs b/crates/core/tests/engine.rs similarity index 100% rename from core/tests/engine.rs rename to crates/core/tests/engine.rs diff --git a/core/tests/macros.rs b/crates/core/tests/macros.rs similarity index 100% rename from core/tests/macros.rs rename to crates/core/tests/macros.rs diff --git a/crates/core/wit/types.wit b/crates/core/wit/types.wit new file mode 100644 index 00000000..31189856 --- /dev/null +++ b/crates/core/wit/types.wit @@ -0,0 +1,40 @@ +interface types { + type state = string; + type symbol = string; + /// A key-value pair describing an attribute. + record head { + /// The attribute name. + state: state, + /// The attribute value. + symbol: symbol, + } + + enum direction { + left, + right, + stay, + } + + record tail { + /// The attribute name. + next-state: state, + /// The attribute value. + write-symbol: symbol, + /// The direction to move. + direction: direction, + } + + record rule { + head: head, + tail: tail, + } + + record program { + /// The initial state of the Turing machine. + initial-state: state, + /// The blank symbol used to represent an empty cell on the tape. + blank-symbol: symbol, + /// The set of rules that define the behavior of the Turing machine. + rules: list, + } +} \ No newline at end of file diff --git a/crates/core/wit/world.wit b/crates/core/wit/world.wit new file mode 100644 index 00000000..9e173200 --- /dev/null +++ b/crates/core/wit/world.wit @@ -0,0 +1,5 @@ +package rstm:core@0.1.4; + +world imports { + import types; +} \ No newline at end of file diff --git a/macros/Cargo.toml b/crates/macros/Cargo.toml similarity index 100% rename from macros/Cargo.toml rename to crates/macros/Cargo.toml diff --git a/macros/build.rs b/crates/macros/build.rs similarity index 100% rename from macros/build.rs rename to crates/macros/build.rs diff --git a/macros/src/ast/fsm_ast.rs b/crates/macros/src/ast/fsm_ast.rs similarity index 100% rename from macros/src/ast/fsm_ast.rs rename to crates/macros/src/ast/fsm_ast.rs diff --git a/macros/src/ast/rule_ast.rs b/crates/macros/src/ast/rule_ast.rs similarity index 100% rename from macros/src/ast/rule_ast.rs rename to crates/macros/src/ast/rule_ast.rs diff --git a/macros/src/impls/fsm.rs b/crates/macros/src/impls/fsm.rs similarity index 100% rename from macros/src/impls/fsm.rs rename to crates/macros/src/impls/fsm.rs diff --git a/macros/src/impls/rule.rs b/crates/macros/src/impls/rule.rs similarity index 100% rename from macros/src/impls/rule.rs rename to crates/macros/src/impls/rule.rs diff --git a/macros/src/lib.rs b/crates/macros/src/lib.rs similarity index 100% rename from macros/src/lib.rs rename to crates/macros/src/lib.rs diff --git a/macros/tests/default.rs b/crates/macros/tests/default.rs similarity index 100% rename from macros/tests/default.rs rename to crates/macros/tests/default.rs diff --git a/rstm/Cargo.toml b/crates/rstm/Cargo.toml similarity index 74% rename from rstm/Cargo.toml rename to crates/rstm/Cargo.toml index af7a18ce..8a46e128 100644 --- a/rstm/Cargo.toml +++ b/crates/rstm/Cargo.toml @@ -1,172 +1,169 @@ -[package] -build = "build.rs" -name = "rstm" - -authors.workspace = true -categories.workspace = true -description.workspace = true -edition.workspace = true -homepage.workspace = true -keywords.workspace = true -license.workspace = true -readme.workspace = true -repository.workspace = true -rust-version.workspace = true -version.workspace = true - -[package.metadata.docs.rs] -all-features = false -features = ["default"] -rustc-args = ["--cfg", "docsrs"] -version = "v{{version}}" - -[package.metadata.release] -no-dev-version = true -tag-name = "{{version}}" - -[lib] -path = "lib.rs" - -[[bench]] -harness = false -name = "tmh" -required-features = ["full"] - -[[example]] -name = "tmh" -required-features = ["default", "json", "tracing"] - -[dependencies] -rstm-core = { workspace = true } -rstm-macros = { optional = true, workspace = true } -rstm-traits = { workspace = true } - -[dev-dependencies] -anyhow = { features = ["std"], workspace = true } -criterion = { features = ["plotters"], workspace = true } -lazy_static = { workspace = true } -serde = { workspace = true } -serde_json = { workspace = true } -tracing = { workspace = true } - -[dev-dependencies.tracing-subscriber] -features = [ - "env-filter", - "fmt", - "json", - "serde", -] -version = "0.3" - -[features] -default = ["actors", "macros", "std"] - -full = [ - "default", - "bytes", - "complex", - "hashbrown", - "json", - "rand", - "serde", - "tracing", -] - -# ********* [FF] Features ********* -actors = [] - -macros = [ - "dep:rstm-macros", - "rstm-core/macros", -] - -tape = [ - "alloc", -] - -nightly = [ - "rstm-core/nightly", - "rstm-macros/nightly", - "rstm-traits/nightly", -] - -json = [ - "alloc", - "serde", - "serde_json", - "rstm-core/json", -] - -# ********* [FF] Environments ********* -std = [ - "alloc", - "rstm-core/std", - "rstm-traits/std", -] - -wasi = [ - "alloc", - "rstm-core/wasi", - "rstm-traits/wasi", -] - -wasm = [ - "alloc", - "wasm_bindgen", - "rstm-core/wasm", - "rstm-traits/wasm", -] - -# ************* [FF:Dependencies] ************* - -alloc = [ - "rstm-core/alloc", - "rstm-traits/alloc", -] - -bytes = [ - "rstm-core/bytes", - "rstm-traits/bytes", -] - -complex = [ - "rstm-core/complex", - "rstm-traits/complex", -] - -hashbrown = [ - "rstm-core/hashbrown", - "rstm-traits/hashbrown", -] - -rand = [ - "rstm-core/rand", - "rstm-traits/rand", -] - -rayon = [ - "rstm-core/rayon", - "rstm-traits/rayon", -] - -rng = [ - "rstm-core/rng", -] - -serde = [ - "rstm-core/serde", - "rstm-traits/serde", -] - -serde_json = [ - "rstm-core/serde_json", -] - -tracing = [ - "rstm-core/tracing", -] - -wasm_bindgen = [ - "rstm-core/wasm_bindgen", - "rstm-traits/wasm_bindgen", -] +[package] +build = "build.rs" +name = "rstm" + +authors.workspace = true +categories.workspace = true +description.workspace = true +edition.workspace = true +homepage.workspace = true +keywords.workspace = true +license.workspace = true +readme.workspace = true +repository.workspace = true +rust-version.workspace = true +version.workspace = true + +[package.metadata.docs.rs] +all-features = false +features = ["default"] +rustc-args = ["--cfg", "docsrs"] +version = "v{{version}}" + +[package.metadata.release] +no-dev-version = true +tag-name = "{{version}}" + +[lib] +path = "lib.rs" + +[[bench]] +harness = false +name = "tmh" +required-features = ["full"] + +[[example]] +name = "tmh" +required-features = ["default", "json", "tracing"] + +[dependencies] +rstm-core = { workspace = true } +rstm-macros = { optional = true, workspace = true } +rstm-tape = { optional = true, workspace = true } + +[dev-dependencies] +anyhow = { features = ["std"], workspace = true } +criterion = { features = ["plotters"], workspace = true } +lazy_static = { workspace = true } +serde = { features = ["std"], workspace = true } +serde_json = { features = ["std"], workspace = true } +tracing = { workspace = true } +tracing-subscriber = { features = ["json", "serde"], workspace = true } + +[features] +default = ["actors", "macros", "std"] + +full = [ + "default", + "bytes", + "complex", + "hashbrown", + "json", + "rand", + "serde", + "tracing", +] + +# ********* [FF] Features ********* +actors = [] + +macros = [ + "dep:rstm-macros", + "rstm-core/macros", +] + +tape = [ + "dep:rstm-tape", + "alloc", +] + +nightly = [ + "rstm-core/nightly", + "rstm-macros/nightly", + "rstm-tape?/nightly", +] + +json = [ + "alloc", + "serde", + "serde_json", + "rstm-core/json", + "rstm-tape?/json", +] + +# ********* [FF] Environments ********* +std = [ + "alloc", + "rstm-core/std", + "rstm-tape?/std", +] + +wasi = [ + "alloc", + "rstm-core/wasi", + "rstm-tape?/wasi", +] + +wasm = [ + "alloc", + "wasm_bindgen", + "rstm-core/wasm", + "rstm-tape?/wasm", +] + +# ************* [FF:Dependencies] ************* + +alloc = [ + "rstm-core/alloc", + "rstm-tape?/alloc", +] + +bytes = [ + "rstm-core/bytes", + "rstm-tape?/bytes", +] + +complex = [ + "rstm-core/complex", + "rstm-tape?/complex", +] + +hashbrown = [ + "rstm-core/hashbrown", + "rstm-tape?/hashbrown", +] + +rand = [ + "rstm-core/rand", + "rstm-tape?/rand", +] + +rayon = [ + "rstm-core/rayon", + "rstm-tape?/rayon", +] + +rng = [ + "rstm-core/rng", + "rstm-tape?/rng", +] + +serde = [ + "rstm-core/serde", + "rstm-tape?/serde", +] + +serde_json = [ + "rstm-core/serde_json", + "rstm-tape?/serde_json", +] + +tracing = [ + "rstm-core/tracing", + "rstm-tape?/tracing", +] + +wasm_bindgen = [ + "rstm-core/wasm_bindgen", + "rstm-tape?/wasm_bindgen", +] diff --git a/rstm/benches/tmh.rs b/crates/rstm/benches/tmh.rs similarity index 100% rename from rstm/benches/tmh.rs rename to crates/rstm/benches/tmh.rs diff --git a/rstm/build.rs b/crates/rstm/build.rs similarity index 100% rename from rstm/build.rs rename to crates/rstm/build.rs diff --git a/rstm/examples/example.program.json b/crates/rstm/examples/example.program.json similarity index 100% rename from rstm/examples/example.program.json rename to crates/rstm/examples/example.program.json diff --git a/rstm/examples/tmh.rs b/crates/rstm/examples/tmh.rs similarity index 89% rename from rstm/examples/tmh.rs rename to crates/rstm/examples/tmh.rs index ac553a4b..d560e487 100644 --- a/rstm/examples/tmh.rs +++ b/crates/rstm/examples/tmh.rs @@ -22,7 +22,7 @@ fn main() -> rstm::Result<()> { let program: Program = program! { #[default_state(initial_state)] rules: { - (0, 0) -> Right(1, 0usize), + (0, 0) -> Right(1, 0), (0, 1) -> Left(-1, 1), (1, 0) -> Right(1, 1), (1, 1) -> Right(0, 0), @@ -30,9 +30,6 @@ fn main() -> rstm::Result<()> { (-1, 1) -> Left(-1, 0), }; }; - /* - let program = Program::::load_from_json("rstm/examples/example.program.json")?; - */ // optionally, export the program to a JSON file program.export_json("rstm/examples/example.program.json")?; // create a new instance of the machine diff --git a/rstm/lib.rs b/crates/rstm/lib.rs similarity index 51% rename from rstm/lib.rs rename to crates/rstm/lib.rs index b63eca79..ac65029f 100644 --- a/rstm/lib.rs +++ b/crates/rstm/lib.rs @@ -2,27 +2,38 @@ #![crate_type = "lib"] //! # rstm //! -//! `rstm` is a Rust library dedicated to the constructtapen and executtapen of Turing Machines. -//! The crate is designed to be flexible and easy to use while preserving the abstract nature -//! of the models. +//! Welcome to `rstm`, a flexible framework for creating and executing Turing machines (TM) in +//! Rust. //! -//! ## Features +//! ## Background //! -//! The crate employs the use of vartapeus feature flags for modularity and to keep the core -//! lightweight. +//! Turing machines are abstract models of computation initially proposed by Alan Turing in +//! 1936. These models work by considering an infinite tape (memory) divided evenly into +//! uniform cells capable of storing a single value that is mutated by the head of the machine +//! according to some set of rules. //! -//! ## Overview +//! ## Rules //! -//! The core of the library is built around the concept of a Turing Machine, which consists of -//! a tape, a head that reads and writes symbols on the tape, and a set of rules that dictate -//! the machine's behavtaper. The library provides a set of abstracttapens and utilities to define -//! and manipulate these components. +//! Rules or instructions for TMs can be defined as a 5-tuple consisting of: +//! +//! 1. Current State: The current state of the machine. +//! 2. Current Symbol: The symbol currently being read by the head. +//! 3. Next State: The state to transition to after executing the rule. +//! 4. Write Symbol: The symbol to write on the tape at the current head position. +//! 5. Shift: The direction to move the head (left, right, or stay). +//! +//! Here, we break the rule into two distinct components for clarity: +//! +//! - [`Head`]: defines the current state and symbol +//! - [`Tail`]: defines the shift direction, next state, and write symbol //! //! ## Basic Usage //! //! For more examples, please refer to the [`examples`](https://github.com/FL03/rstm/blob/main/rstm/examples) directory in the repository. //! -//! ### Creating and executing a simple Turing Machine with a Moving Head +//! ### `MovingHead` Example +//! +//! This example demonstrats how to initialize and run a Turing machine with a _moving head_. //! //! ```rust //! use rstm::{MovingHead, program}; @@ -49,10 +60,16 @@ //! tm.run().expect("failed to execute..."); //! ``` #![allow( + clippy::len_without_is_empty, + clippy::missing_docs_in_private_items, + clippy::missing_errors_doc, + clippy::missing_panics_doc, + clippy::missing_safety_doc, clippy::module_inception, - clippy::new_ret_no_self, clippy::needless_doctest_main, - clippy::should_implement_trait + clippy::new_ret_no_self, + clippy::should_implement_trait, + clippy::upper_case_acronyms )] #![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(all(feature = "alloc", feature = "nightly"), feature(allocator_api))] @@ -63,20 +80,18 @@ compile_error! { "Either the `std` or `alloc` feature must be enabled to compile #[cfg(feature = "alloc")] extern crate alloc; #[doc(inline)] -pub use rstm_traits as traits; -// re-exports -#[doc(inline)] -pub use self::traits::*; -#[doc(inline)] pub use rstm_core::*; #[cfg(feature = "macros")] pub use rstm_macros::*; +#[cfg(feature = "tape")] +pub use rstm_tape as tape; +// prelude #[doc(hidden)] pub mod prelude { - #[doc(no_inline)] pub use rstm_core::prelude::*; + // conditionally re-exported items #[cfg(feature = "macros")] pub use rstm_macros::*; - #[doc(no_inline)] - pub use rstm_traits::prelude::*; + #[cfg(feature = "tape")] + pub use rstm_tape::prelude::*; } diff --git a/rstm/tests/default.rs b/crates/rstm/tests/default.rs similarity index 100% rename from rstm/tests/default.rs rename to crates/rstm/tests/default.rs diff --git a/rstm/tests/macros.rs b/crates/rstm/tests/macros.rs similarity index 100% rename from rstm/tests/macros.rs rename to crates/rstm/tests/macros.rs diff --git a/state/Cargo.toml b/crates/state/Cargo.toml similarity index 94% rename from state/Cargo.toml rename to crates/state/Cargo.toml index 8e520955..6a720b34 100644 --- a/state/Cargo.toml +++ b/crates/state/Cargo.toml @@ -1,173 +1,176 @@ -[package] -build = "build.rs" -description = "A generic state implementation and its supporting interfaces" -name = "rstm-state" - -authors.workspace = true -categories.workspace = true -edition.workspace = true -homepage.workspace = true -keywords.workspace = true -license.workspace = true -readme.workspace = true -repository.workspace = true -rust-version.workspace = true -version.workspace = true - -[package.metadata.docs.rs] -all-features = false -features = ["default"] -rustc-args = ["--cfg", "docsrs"] -version = "v{{version}}" - -[package.metadata.release] -no-dev-version = true -tag-name = "{{version}}" - -[lib] -bench = false -doc = true -doctest = false -test = true - -[dependencies] -rstm-traits = { workspace = true } -# custom -contained = { features = ["macros"], workspace = true } -# concurrency / parallelism -rayon = { optional = true, workspace = true } -# data structures -bytes = { optional = true, workspace = true } -hashbrown = { optional = true, workspace = true } -# error-handling -anyhow = { workspace = true } -thiserror = { workspace = true } -# numbers -num-complex = { optional = true, workspace = true } -num-traits = { workspace = true } -# random -getrandom = { optional = true, workspace = true } -rand = { optional = true, workspace = true } -rand_distr = { optional = true, workspace = true } -# serialization -serde = { optional = true, workspace = true } -serde_derive = { optional = true, workspace = true } -serde_json = { optional = true, workspace = true } -# macros & utilities -paste = { workspace = true } -smart-default = { workspace = true } -strum = { workspace = true } -# logging -wasm-bindgen = { optional = true, workspace = true } - -[features] -default = ["macros", "std"] - -full = [ - "default", - "complex", - "hashbrown", - "json", - "rand", - "serde", -] - -# ********* [FF] Features ********* - -json = [ - "alloc", - "serde", - "serde_json", -] - -macros = [] - -nightly = [ - "rstm-traits/nightly", -] - -# ********* [FF] Environments ********* -std = [ - "alloc", - "anyhow/std", - "contained/std", - "rstm-traits/std", - "rand?/std", - "rand?/default", - "rand_distr?/std", - "serde?/std", - "serde_json?/std", - "strum/std", - "num-traits/std", - "thiserror/std", -] - -wasi = [ - "rstm-traits/wasi", -] - -wasm = [ - "wasm_bindgen", - "getrandom?/wasm_js", - "rayon?/web_spin_lock", - "rstm-traits/wasm", -] - -# ********* [FF] Dependencies ********* -alloc = [ - "contained/alloc", - "rand?/alloc", - "rand_distr?/alloc", - "rstm-traits/alloc", - "serde?/alloc", - "serde_json?/alloc", -] - -bytes = ["dep:bytes"] - -complex = [ - "dep:num-complex", - "rstm-traits/complex", -] - -hashbrown = [ - "dep:hashbrown", - "rstm-traits/hashbrown", -] - -rand = [ - "dep:rand", - "dep:rand_distr", - "rng", - "num-complex?/rand", -] - -rayon = [ - "dep:rayon", - "hashbrown?/rayon", - "rstm-traits/rayon", -] - -rng = [ - "dep:getrandom", - "rand?/os_rng", -] - -serde = [ - "dep:serde", - "dep:serde_derive", - "serde?/derive", - "bytes?/serde", - "hashbrown?/serde", - "num-complex?/serde", - "rand?/serde", - "rand_distr?/serde", - "rstm-traits/serde", -] - -serde_json = ["dep:serde_json"] - -wasm_bindgen = [ - "dep:wasm-bindgen", - "rstm-traits/wasm_bindgen", -] +[package] +build = "build.rs" +description = "A generic state implementation and its supporting interfaces" +name = "rstm-state" + +authors.workspace = true +categories.workspace = true +edition.workspace = true +homepage.workspace = true +keywords.workspace = true +license.workspace = true +readme.workspace = true +repository.workspace = true +rust-version.workspace = true +version.workspace = true + +[package.metadata.docs.rs] +all-features = false +features = ["default"] +rustc-args = ["--cfg", "docsrs"] +version = "v{{version}}" + +[package.metadata.release] +no-dev-version = true +tag-name = "{{version}}" + +[lib] +bench = false +doc = true +doctest = false +test = true + +[dependencies] +rstm-traits = { workspace = true } +# custom +contained = { features = ["macros"], workspace = true } +# concurrency / parallelism +rayon = { optional = true, workspace = true } +# data structures +bytes = { optional = true, workspace = true } +hashbrown = { optional = true, workspace = true } +# error-handling +anyhow = { workspace = true } +thiserror = { workspace = true } +# numbers +num-complex = { optional = true, workspace = true } +num-traits = { workspace = true } +# random +getrandom = { optional = true, workspace = true } +rand = { optional = true, workspace = true } +rand_distr = { optional = true, workspace = true } +# serialization +serde = { optional = true, workspace = true } +serde_derive = { optional = true, workspace = true } +serde_json = { optional = true, workspace = true } +# macros & utilities +paste = { workspace = true } +smart-default = { workspace = true } +strum = { workspace = true } +# logging +wasm-bindgen = { optional = true, workspace = true } + +[features] +default = ["macros", "std"] + +full = [ + "default", + "complex", + "hashbrown", + "json", + "rand", + "serde", +] + +# ********* [FF] Features ********* + +json = [ + "alloc", + "serde", + "serde_json", +] + +macros = [] + +nightly = [ + "rstm-traits/nightly", +] + +# ********* [FF] Environments ********* +std = [ + "alloc", + "anyhow/std", + "contained/std", + "getrandom?/std", + "rstm-traits/std", + "rand?/std", + "rand?/default", + "rand_distr?/std", + "serde?/std", + "serde_json?/std", + "strum/std", + "num-traits/std", + "thiserror/std", + "wasm-bindgen?/std", +] + +wasi = [ + "rstm-traits/wasi", +] + +wasm = [ + "wasm_bindgen", + "getrandom?/wasm_js", + "rayon?/web_spin_lock", + "rstm-traits/wasm", +] + +# ********* [FF] Dependencies ********* +alloc = [ + "contained/alloc", + "rand?/alloc", + "rand_distr?/alloc", + "rstm-traits/alloc", + "serde?/alloc", + "serde_json?/alloc", + "wasm-bindgen?/gg-alloc", +] + +bytes = ["dep:bytes"] + +complex = [ + "dep:num-complex", + "rstm-traits/complex", +] + +hashbrown = [ + "dep:hashbrown", + "rstm-traits/hashbrown", +] + +rand = [ + "dep:rand", + "dep:rand_distr", + "rng", + "num-complex?/rand", +] + +rayon = [ + "dep:rayon", + "hashbrown?/rayon", + "rstm-traits/rayon", +] + +rng = [ + "dep:getrandom", + "rand?/os_rng", +] + +serde = [ + "dep:serde", + "dep:serde_derive", + "serde?/derive", + "bytes?/serde", + "hashbrown?/serde", + "num-complex?/serde", + "rand?/serde", + "rand_distr?/serde", + "rstm-traits/serde", +] + +serde_json = ["dep:serde_json"] + +wasm_bindgen = [ + "dep:wasm-bindgen", + "rstm-traits/wasm_bindgen", +] diff --git a/state/build.rs b/crates/state/build.rs similarity index 100% rename from state/build.rs rename to crates/state/build.rs diff --git a/state/src/error.rs b/crates/state/src/error.rs similarity index 93% rename from state/src/error.rs rename to crates/state/src/error.rs index 04cbfd8e..e1d5bd5e 100644 --- a/state/src/error.rs +++ b/crates/state/src/error.rs @@ -1,22 +1,22 @@ -/* - Appellation: error - Contrib: FL03 -*/ -//! This module defines the custom error type for handling various state-related errors. -#[cfg(feature = "alloc")] -use alloc::string::String; - -/// A type alias for a [`Result`](core::result::Result) that uses the custom [`Error`] type -pub type Result = core::result::Result; - -/// the various errors that can occur in the state module -#[derive(Debug, thiserror::Error)] -pub enum StateError { - #[error("Failed to downcast state")] - DowncastFailure, - #[cfg(feature = "alloc")] - #[error("Invalid State: {0}")] - InvalidState(String), - #[error("State Not Found")] - StateNotFound, -} +/* + Appellation: error + Contrib: FL03 +*/ +//! This module defines the custom error type for handling various state-related errors. +#[cfg(feature = "alloc")] +use alloc::string::String; + +/// A type alias for a [`Result`](core::result::Result) that uses the custom [`StateError`] type +pub type Result = core::result::Result; + +/// the various errors that can occur in the state module +#[derive(Debug, thiserror::Error)] +pub enum StateError { + #[error("Failed to downcast state")] + DowncastFailure, + #[cfg(feature = "alloc")] + #[error("Invalid State: {0}")] + InvalidState(String), + #[error("State Not Found")] + StateNotFound, +} diff --git a/state/src/impls/impl_halt.rs b/crates/state/src/impls/impl_halt.rs similarity index 87% rename from state/src/impls/impl_halt.rs rename to crates/state/src/impls/impl_halt.rs index f4f6182c..f745f208 100644 --- a/state/src/impls/impl_halt.rs +++ b/crates/state/src/impls/impl_halt.rs @@ -4,16 +4,24 @@ */ use crate::{Halt, RawState, State}; -impl RawState for Halt { +impl RawState for Halt +where + Q: RawState, + H: RawState, +{ seal! {} } -impl Halt { - /// Creates a new instance of a [HaltState] with a halted state. +impl Halt +where + Q: RawState, + H: RawState, +{ + /// Creates a new instance of a [Halt] with a halted state. pub const fn from_halt(state: H) -> Self { Self::Halt(state) } - /// Creates a new instance of a [HaltState] with a continuing state. + /// Creates a new instance of a [Halt] with a continuing state. pub const fn from_state(state: Q) -> Self { Self::Step(state) } @@ -53,7 +61,10 @@ impl Halt { } } -impl Halt { +impl Halt +where + Q: RawState, +{ #[inline] /// consumes the current haltable state, returning the inner state. pub fn into_inner(self) -> Q { @@ -63,7 +74,7 @@ impl Halt { } } #[inline] - /// consumes the current instance to create another instance with a [`Halt`](Self::Halt) + /// consumes the current instance to ensure a halting state pub fn halt(self) -> Halt { match self { Self::Step(inner) => Halt::Halt(inner), @@ -124,7 +135,11 @@ impl Halt { } } -impl<'a, Q, H> Halt<&'a Q, &'a H> { +impl<'a, Q, H> Halt<&'a Q, &'a H> +where + Q: RawState, + H: RawState, +{ #[inline] /// consumes the current instance of the halt state to create another with cloned inner /// values. @@ -155,7 +170,11 @@ impl<'a, Q, H> Halt<&'a Q, &'a H> { } } -impl<'a, Q, H> Halt<&'a mut Q, &'a mut H> { +impl<'a, Q, H> Halt<&'a mut Q, &'a mut H> +where + Q: RawState, + H: RawState, +{ #[inline] /// consumes the current instance of the halt state to create another with cloned inner /// values. @@ -184,19 +203,28 @@ impl<'a, Q, H> Halt<&'a mut Q, &'a mut H> { } } -impl AsRef for Halt { +impl AsRef for Halt +where + Q: RawState, +{ fn as_ref(&self) -> &Q { self.get() } } -impl AsMut for Halt { +impl AsMut for Halt +where + Q: RawState, +{ fn as_mut(&mut self) -> &mut Q { self.get_mut() } } -impl core::ops::Deref for Halt { +impl core::ops::Deref for Halt +where + Q: RawState, +{ type Target = Q; fn deref(&self) -> &Self::Target { @@ -204,7 +232,10 @@ impl core::ops::Deref for Halt { } } -impl core::ops::DerefMut for Halt { +impl core::ops::DerefMut for Halt +where + Q: RawState, +{ fn deref_mut(&mut self) -> &mut Self::Target { self.get_mut() } @@ -212,14 +243,17 @@ impl core::ops::DerefMut for Halt { impl Default for Halt where - Q: Default, + Q: Default + RawState, { fn default() -> Self { Self::Step(Default::default()) } } -impl From> for Halt { +impl From> for Halt +where + Q: RawState, +{ fn from(State(state): State) -> Self { Self::Step(state) } diff --git a/state/src/impls/impl_state.rs b/crates/state/src/impls/impl_state.rs similarity index 92% rename from state/src/impls/impl_state.rs rename to crates/state/src/impls/impl_state.rs index ac55de01..a5b7d990 100644 --- a/state/src/impls/impl_state.rs +++ b/crates/state/src/impls/impl_state.rs @@ -1,255 +1,265 @@ -/* - Appellation: impl_state - Contrib: @FL03 -*/ -use crate::state::{Halt, State}; - -impl State { - /// a constructor method for the [`State`] type. - pub const fn new(state: Q) -> Self { - Self(state) - } - /// create a new state by invoking the given function and capturing its output. - #[inline] - pub fn create(f: F) -> Self - where - F: FnOnce() -> Q, - { - State(f()) - } - /// returns a new state with a value of one. - pub fn one() -> Self - where - Q: num_traits::One, - { - State::create(Q::one) - } - /// returns a new state with a value of zero. - pub fn zero() -> Self - where - Q: num_traits::Zero, - { - State::create(Q::zero) - } - /// returns a new instance of state with a raw pointer to the inner value. - pub const fn as_ptr(&self) -> *const Q { - core::ptr::addr_of!(self.0) - } - /// returns a new instance of state with a mutable raw pointer to the inner value. - pub const fn as_mut_ptr(&mut self) -> *mut Q { - core::ptr::addr_of_mut!(self.0) - } - /// returns an immutable reference to the inner value of the state. - pub const fn get(&self) -> &Q { - &self.0 - } - /// returns a mutable reference to the inner value of the state. - pub const fn get_mut(&mut self) -> &mut Q { - &mut self.0 - } - /// consumes and returns the inner value of the state. - #[inline] - pub fn value(self) -> Q { - self.0 - } - /// Casts the state to a new type, returning a new instance of [State]. - /// - /// # Safety - /// - /// The method is marked unsafe because there are no guarantees that the inner type `Q` - /// can be safely interpreted as type `R`. The caller must ensure that the cast is valid - /// to avoid undefined behavior. - #[inline] - pub unsafe fn cast(self) -> State { - unsafe { State(core::ptr::read(&self.0 as *const Q as *const R)) } - } - /// [State::map] applies the given function onto the inner value of the state, returning a - /// new state with the result. - pub fn map(self, f: F) -> State - where - F: FnOnce(Q) -> R, - { - State(f(self.value())) - } - /// reset the state back to its logical default, returning the previous value. - pub fn reset(&mut self) -> State - where - Q: Default, - { - let prev = self.take(); - State(prev) - } - /// update the current value of the object with the given state. - #[inline] - pub fn set(&mut self, state: Q) { - self.0 = state; - } - /// [`replace`](core::mem::replace) the inner value of the state with the given state, - pub const fn replace(&mut self, state: Q) -> Q { - core::mem::replace(self.get_mut(), state) - } - /// [`swap`](core::mem::swap) the inner value of the state with that of the given state. - pub const fn swap(&mut self, other: &mut State) { - core::mem::swap(self.get_mut(), other.get_mut()); - } - /// [`take`](core::mem::take) the inner value of the state, leaving the logical default in - /// its place - pub fn take(&mut self) -> Q - where - Q: Default, - { - core::mem::take(self.get_mut()) - } - /// converts the current reference into a haltable state initialized with the current state - pub fn as_halt(&self) -> State> { - State::new(Halt::Halt(self.get())) - } - /// consumes the wrapper to create another, haltable state that is initialized with the - /// current state - pub fn into_halt(self) -> State> { - State::new(Halt::Step(self.value())) - } - /// consumes the current state, returning a new one with a [`Halt`](Halt::Halt) - /// variant initialized with the current value. - pub fn halt(self) -> State> { - State::new(Halt::Halt(self.value())) - } - /// returns a state with an owned inner value. - pub const fn view(&self) -> State<&Q> { - State(self.get()) - } - /// returns a state with a mutable reference to the inner value. - pub const fn view_mut(&mut self) -> State<&mut Q> { - State(self.get_mut()) - } - /// returns the `name` of the generic inner type, `Q`. - pub fn get_inner_type_name(&self) -> &'static str { - core::any::type_name::() - } - /// returns the `type id` of the generic inner type, `Q`. - pub const fn get_inner_type_id(&self) -> core::any::TypeId - where - Q: 'static, - { - core::any::TypeId::of::() - } -} - -#[cfg(feature = "alloc")] -/// Additional implementations for the [`State`] type enabled whenever the `alloc` feature is -/// toggled. -impl State { - /// returns a new state with a boxed inner value. - pub fn boxed(self) -> State> { - self.map(alloc::boxed::Box::new) - } - /// Converts the inner type into a boxed "any" state, returning a new instance of state - pub fn as_any(&self) -> State> - where - Q: Clone + 'static, - { - State(alloc::boxed::Box::new(self.get().clone())) - } - /// Converts the inner type into a boxed "any" state, returning a new instance of state - pub fn into_any(self) -> State> - where - Q: 'static, - { - State(alloc::boxed::Box::new(self.value())) - } - /// Wraps the inner value of the state with an [`Arc`] and returns a new instance of [State] - pub fn shared(self) -> State> { - self.map(alloc::sync::Arc::new) - } - /// returns a shared reference to the state. - pub fn to_shared(&self) -> State> - where - Q: Clone, - { - self.clone().shared() - } -} - -impl AsRef for State { - fn as_ref(&self) -> &Q { - self.get() - } -} - -impl AsMut for State { - fn as_mut(&mut self) -> &mut Q { - self.get_mut() - } -} - -impl core::borrow::Borrow for State { - fn borrow(&self) -> &Q { - self.get() - } -} - -impl core::borrow::BorrowMut for State { - fn borrow_mut(&mut self) -> &mut Q { - self.get_mut() - } -} - -impl core::ops::Deref for State { - type Target = Q; - - fn deref(&self) -> &Self::Target { - self.get() - } -} - -impl core::ops::DerefMut for State { - fn deref_mut(&mut self) -> &mut Self::Target { - self.get_mut() - } -} - -impl From for State { - fn from(state: Q) -> Self { - State(state) - } -} - -impl PartialEq for State { - fn eq(&self, other: &Q) -> bool { - self.0.eq(other) - } -} - -impl<'a, Q: PartialEq> PartialEq<&'a Q> for State { - fn eq(&self, other: &&'a Q) -> bool { - self.0.eq(*other) - } -} - -impl<'a, Q: PartialEq> PartialEq<&'a mut Q> for State { - fn eq(&self, other: &&'a mut Q) -> bool { - self.0.eq(*other) - } -} - -impl PartialOrd for State { - fn partial_cmp(&self, other: &Q) -> Option { - self.0.partial_cmp(other) - } -} - -impl<'a, Q: PartialOrd> PartialOrd<&'a Q> for State { - fn partial_cmp(&self, other: &&'a Q) -> Option { - self.0.partial_cmp(*other) - } -} - -impl<'a, Q: PartialOrd> PartialOrd<&'a mut Q> for State { - fn partial_cmp(&self, other: &&'a mut Q) -> Option { - self.0.partial_cmp(*other) - } -} - -unsafe impl Send for State {} - -unsafe impl Sync for State {} +/* + Appellation: impl_state + Contrib: @FL03 +*/ +use crate::RawState; +use crate::state::{Halt, State}; + +impl State { + /// a constructor method for the [`State`] type. + pub const fn new(state: Q) -> Self { + Self(state) + } + /// create a new state by invoking the given function and capturing its output. + #[inline] + pub fn init(f: F) -> Self + where + F: FnOnce() -> Q, + { + State(f()) + } + /// returns a new state with a value of one. + pub fn one() -> Self + where + Q: num_traits::One, + { + State::init(Q::one) + } + /// returns a new state with a value of zero. + pub fn zero() -> Self + where + Q: num_traits::Zero, + { + State::init(Q::zero) + } + /// returns a new instance of state with a raw pointer to the inner value. + pub const fn as_ptr(&self) -> *const Q { + core::ptr::addr_of!(self.0) + } + /// returns a new instance of state with a mutable raw pointer to the inner value. + pub const fn as_mut_ptr(&mut self) -> *mut Q { + core::ptr::addr_of_mut!(self.0) + } + /// returns an immutable reference to the inner value of the state. + pub const fn get(&self) -> &Q { + &self.0 + } + /// returns a mutable reference to the inner value of the state. + pub const fn get_mut(&mut self) -> &mut Q { + &mut self.0 + } + /// consumes and returns the inner value of the state. + #[inline] + pub fn value(self) -> Q { + self.0 + } + /// Casts the state to a new type, returning a new instance of [State]. + /// + /// # Safety + /// + /// The method is marked unsafe because there are no guarantees that the inner type `Q` + /// can be safely interpreted as type `R`. The caller must ensure that the cast is valid + /// to avoid undefined behavior. + #[inline] + pub unsafe fn cast(self) -> State { + unsafe { State(core::ptr::read(&self.0 as *const Q as *const R)) } + } + /// [State::map] applies the given function onto the inner value of the state, returning a + /// new state with the result. + pub fn map(self, f: F) -> State + where + F: FnOnce(Q) -> R, + { + State(f(self.value())) + } + /// reset the state back to its logical default, returning the previous value. + pub fn reset(&mut self) -> State + where + Q: Default, + { + let prev = self.take(); + State(prev) + } + /// update the current value of the object with the given state. + #[inline] + pub fn set(&mut self, state: Q) { + self.0 = state; + } + /// [`replace`](core::mem::replace) the inner value of the state with the given state, + pub const fn replace(&mut self, state: Q) -> Q { + core::mem::replace(self.get_mut(), state) + } + /// [`swap`](core::mem::swap) the inner value of the state with that of the given state. + pub const fn swap(&mut self, other: &mut State) { + core::mem::swap(self.get_mut(), other.get_mut()); + } + /// [`take`](core::mem::take) the inner value of the state, leaving the logical default in + /// its place + pub fn take(&mut self) -> Q + where + Q: Default, + { + core::mem::take(self.get_mut()) + } + /// converts the current reference into a haltable state initialized with the current state + pub fn as_halt(&self) -> State> + where + Q: RawState, + { + State::new(Halt::Halt(self.get())) + } + /// consumes the wrapper to create another, haltable state that is initialized with the + /// current state + pub fn into_halt(self) -> State> + where + Q: RawState, + { + State::new(Halt::Step(self.value())) + } + /// consumes the current state, returning a new one with a [`Halt`](Halt::Halt) + /// variant initialized with the current value. + pub fn halt(self) -> State> + where + Q: RawState, + { + State::new(Halt::Halt(self.value())) + } + /// returns a state with an owned inner value. + pub const fn view(&self) -> State<&Q> { + State(self.get()) + } + /// returns a state with a mutable reference to the inner value. + pub const fn view_mut(&mut self) -> State<&mut Q> { + State(self.get_mut()) + } + /// returns the `name` of the generic inner type, `Q`. + pub fn get_inner_type_name(&self) -> &'static str { + core::any::type_name::() + } + /// returns the `type id` of the generic inner type, `Q`. + pub const fn get_inner_type_id(&self) -> core::any::TypeId + where + Q: 'static, + { + core::any::TypeId::of::() + } +} + +#[cfg(feature = "alloc")] +/// Additional implementations for the [`State`] type enabled whenever the `alloc` feature is +/// toggled. +impl State { + /// returns a new state with a boxed inner value. + pub fn boxed(self) -> State> { + self.map(alloc::boxed::Box::new) + } + /// Converts the inner type into a boxed "any" state, returning a new instance of state + pub fn as_any(&self) -> State> + where + Q: Clone + 'static, + { + State(alloc::boxed::Box::new(self.get().clone())) + } + /// Converts the inner type into a boxed "any" state, returning a new instance of state + pub fn into_any(self) -> State> + where + Q: 'static, + { + State(alloc::boxed::Box::new(self.value())) + } + /// convert the state into another instance by wrapping the inner value with an [`Arc`](alloc::sync::Arc). + pub fn shared(self) -> State> { + self.map(alloc::sync::Arc::new) + } + /// returns a shared reference to the state. + pub fn to_shared(&self) -> State> + where + Q: Clone, + { + self.clone().shared() + } +} + +impl AsRef for State { + fn as_ref(&self) -> &Q { + self.get() + } +} + +impl AsMut for State { + fn as_mut(&mut self) -> &mut Q { + self.get_mut() + } +} + +impl core::borrow::Borrow for State { + fn borrow(&self) -> &Q { + self.get() + } +} + +impl core::borrow::BorrowMut for State { + fn borrow_mut(&mut self) -> &mut Q { + self.get_mut() + } +} + +impl core::ops::Deref for State { + type Target = Q; + + fn deref(&self) -> &Self::Target { + self.get() + } +} + +impl core::ops::DerefMut for State { + fn deref_mut(&mut self) -> &mut Self::Target { + self.get_mut() + } +} + +impl From for State { + fn from(state: Q) -> Self { + State(state) + } +} + +impl PartialEq for State { + fn eq(&self, other: &Q) -> bool { + self.0.eq(other) + } +} + +impl<'a, Q: PartialEq> PartialEq<&'a Q> for State { + fn eq(&self, other: &&'a Q) -> bool { + self.0.eq(*other) + } +} + +impl<'a, Q: PartialEq> PartialEq<&'a mut Q> for State { + fn eq(&self, other: &&'a mut Q) -> bool { + self.0.eq(*other) + } +} + +impl PartialOrd for State { + fn partial_cmp(&self, other: &Q) -> Option { + self.0.partial_cmp(other) + } +} + +impl<'a, Q: PartialOrd> PartialOrd<&'a Q> for State { + fn partial_cmp(&self, other: &&'a Q) -> Option { + self.0.partial_cmp(*other) + } +} + +impl<'a, Q: PartialOrd> PartialOrd<&'a mut Q> for State { + fn partial_cmp(&self, other: &&'a mut Q) -> Option { + self.0.partial_cmp(*other) + } +} + +unsafe impl Send for State {} + +unsafe impl Sync for State {} diff --git a/state/src/impls/impl_state_ops.rs b/crates/state/src/impls/impl_state_ops.rs similarity index 100% rename from state/src/impls/impl_state_ops.rs rename to crates/state/src/impls/impl_state_ops.rs diff --git a/state/src/impls/impl_state_repr.rs b/crates/state/src/impls/impl_state_repr.rs similarity index 94% rename from state/src/impls/impl_state_repr.rs rename to crates/state/src/impls/impl_state_repr.rs index f546939d..2df8476a 100644 --- a/state/src/impls/impl_state_repr.rs +++ b/crates/state/src/impls/impl_state_repr.rs @@ -1,154 +1,154 @@ -/* - Appellation: impl_repr - Contrib: FL03 -*/ -use crate::error::StateError; -use crate::state::State; -#[cfg(feature = "alloc")] -use alloc::boxed::Box; -use core::mem::MaybeUninit; - -impl State<&Q> { - /// Clones the internal state and returning a new instance of [State] - pub fn cloned(&self) -> State - where - Q: Clone, - { - State(self.0.clone()) - } - /// Copies the internal state and returning a new instance of [State] - pub const fn copied(&self) -> State - where - Q: Copy, - { - State(*self.0) - } -} - -impl State<&mut Q> { - /// Clones the internal state and returning a new instance of [State] - pub fn cloned(&self) -> State - where - Q: Clone, - { - State(self.0.clone()) - } - /// Copies the internal state and returning a new instance of [State] - pub const fn copied(&self) -> State - where - Q: Copy, - { - State(*self.0) - } -} - -impl State<*const Q> { - /// Creates a new instance of state with a raw pointer to the inner value. - pub fn from_ptr(ptr: *const Q) -> Self { - Self(ptr) - } -} - -impl State<*mut Q> { - /// Creates a new instance of state with a mutable raw pointer to the inner value. - pub fn from_mut_ptr(ptr: *mut Q) -> Self { - Self(ptr) - } -} - -impl State> { - /// Creates a new instance of state with an initialized inner value. - pub fn init(value: Q) -> Self { - Self(MaybeUninit::new(value)) - } - /// Creates a new instance of state with an uninitialized inner value. - pub const fn uninit() -> Self { - Self(MaybeUninit::uninit()) - } - #[allow(clippy::missing_safety_doc)] - /// Converts the state into a new instance of [State] with an initialized state. - /// - /// # Safety - /// - /// This method is unsafe because it is up to the caller to ensure that the inner value - /// is indeed initialized. - pub unsafe fn assume_init(self) -> State { - State(unsafe { self.value().assume_init() }) - } - /// determines if the inner state is null; returns false if the inner state is not null. - pub fn is_null(&self) -> bool { - self.get().as_ptr().is_null() - } - /// Writes a value to the inner state. - pub fn write(&mut self, value: Q) -> &mut Q { - self.get_mut().write(value) - } -} - -impl State<()> { - /// Creates a new instance of [State] with an empty state. - pub const fn empty() -> Self { - Self(()) - } -} - -impl State { - /// Creates a new instance of [State] with an inner state of `true`. - pub const fn from_true() -> Self { - Self(true) - } - /// returns a new instance of [`State`] with an inner state of `false`. - pub const fn from_false() -> Self { - Self(false) - } - /// returns true if the inner state is true, false otherwise. - pub fn is_true(&self) -> bool { - self.value() - } - /// returns true if the inner state is false, false otherwise. - pub fn is_false(&self) -> bool { - !self.value() - } -} -#[cfg(feature = "alloc")] -impl State> { - /// Attempts to downcast the state to a concrete type `Q`; returns an error if the state - /// is not of type `Q`. - pub fn downcast(self) -> Result>, StateError> - where - Q: core::any::Any, - { - self.0 - .downcast() - .map(State) - .map_err(|_| StateError::DowncastFailure) - } - /// Returns an immutable reference to the state if it is of type `Q`; returns `None` - /// otherwise. - pub fn downcast_ref(&self) -> Option> - where - Q: core::any::Any, - { - self.0.downcast_ref().map(State) - } - - /// Returns a mutable reference to the state if it is of type `Q`; returns `None` - /// otherwise. - pub fn downcast_mut(&mut self) -> Option> - where - Q: core::any::Any, - { - self.0.downcast_mut().map(State) - } -} - -impl State> { - /// Creates a new instance of state whose inner state is [Option::None]. - pub const fn none() -> Self { - Self(None) - } - /// Creates a new instance of state whose inner state is [Option::Some]. - pub const fn some(value: Q) -> Self { - Self(Some(value)) - } -} +/* + Appellation: impl_repr + Contrib: FL03 +*/ +use crate::error::StateError; +use crate::state::State; +#[cfg(feature = "alloc")] +use alloc::boxed::Box; +use core::mem::MaybeUninit; + +impl State<&Q> { + /// Clones the internal state and returning a new instance of [State] + pub fn cloned(&self) -> State + where + Q: Clone, + { + State(self.0.clone()) + } + /// Copies the internal state and returning a new instance of [State] + pub const fn copied(&self) -> State + where + Q: Copy, + { + State(*self.0) + } +} + +impl State<&mut Q> { + /// Clones the internal state and returning a new instance of [State] + pub fn cloned(&self) -> State + where + Q: Clone, + { + State(self.0.clone()) + } + /// Copies the internal state and returning a new instance of [State] + pub const fn copied(&self) -> State + where + Q: Copy, + { + State(*self.0) + } +} + +impl State<*const Q> { + /// Creates a new instance of state with a raw pointer to the inner value. + pub fn from_ptr(ptr: *const Q) -> Self { + Self(ptr) + } +} + +impl State<*mut Q> { + /// Creates a new instance of state with a mutable raw pointer to the inner value. + pub fn from_mut_ptr(ptr: *mut Q) -> Self { + Self(ptr) + } +} + +impl State> { + /// Creates a new instance of state with an initialized inner value. + pub const fn initialized(value: Q) -> Self { + Self(MaybeUninit::new(value)) + } + /// Creates a new instance of state with an uninitialized inner value. + pub const fn uninit() -> Self { + Self(MaybeUninit::uninit()) + } + #[allow(clippy::missing_safety_doc)] + /// Converts the state into a new instance of [State] with an initialized state. + /// + /// # Safety + /// + /// This method is unsafe because it is up to the caller to ensure that the inner value + /// is indeed initialized. + pub unsafe fn assume_init(self) -> State { + State(unsafe { self.value().assume_init() }) + } + /// determines if the inner state is null; returns false if the inner state is not null. + pub fn is_null(&self) -> bool { + self.get().as_ptr().is_null() + } + /// Writes a value to the inner state. + pub fn write(&mut self, value: Q) -> &mut Q { + self.get_mut().write(value) + } +} + +impl State<()> { + /// Creates a new instance of [State] with an empty state. + pub const fn empty() -> Self { + Self(()) + } +} + +impl State { + /// Creates a new instance of [State] with an inner state of `true`. + pub const fn yes() -> Self { + Self(true) + } + /// returns a new instance of [`State`] with an inner state of `false`. + pub const fn no() -> Self { + Self(false) + } + /// returns true if the inner state is true, false otherwise. + pub fn is_true(&self) -> bool { + self.value() + } + /// returns true if the inner state is false, false otherwise. + pub fn is_false(&self) -> bool { + !self.value() + } +} +#[cfg(feature = "alloc")] +impl State> { + /// Attempts to downcast the state to a concrete type `Q`; returns an error if the state + /// is not of type `Q`. + pub fn downcast(self) -> Result>, StateError> + where + Q: core::any::Any, + { + self.0 + .downcast() + .map(State) + .map_err(|_| StateError::DowncastFailure) + } + /// Returns an immutable reference to the state if it is of type `Q`; returns `None` + /// otherwise. + pub fn downcast_ref(&self) -> Option> + where + Q: core::any::Any, + { + self.0.downcast_ref().map(State) + } + + /// Returns a mutable reference to the state if it is of type `Q`; returns `None` + /// otherwise. + pub fn downcast_mut(&mut self) -> Option> + where + Q: core::any::Any, + { + self.0.downcast_mut().map(State) + } +} + +impl State> { + /// Creates a new instance of state whose inner state is [Option::None]. + pub const fn none() -> Self { + Self(None) + } + /// Creates a new instance of state whose inner state is [Option::Some]. + pub const fn some(value: Q) -> Self { + Self(Some(value)) + } +} diff --git a/state/src/lib.rs b/crates/state/src/lib.rs similarity index 93% rename from state/src/lib.rs rename to crates/state/src/lib.rs index 66755618..e6a3d200 100644 --- a/state/src/lib.rs +++ b/crates/state/src/lib.rs @@ -1,73 +1,75 @@ -/* - Appellation: rstm-state - Created At: 2025.08.29:22:43:22 - Contrib: @FL03 -*/ -//! The [`state`](self) module provides abstractions and implementations for managing state -//! within the `rstm` framework. -//! -#![crate_type = "lib"] -#![allow( - clippy::missing_errors_doc, - clippy::missing_panics_doc, - clippy::missing_safety_doc, - clippy::module_inception, - clippy::needless_doctest_main, - clippy::non_canonical_partial_ord_impl, - clippy::should_implement_trait, - clippy::upper_case_acronyms -)] -#![cfg_attr(not(feature = "std"), no_std)] -#![cfg_attr(all(feature = "alloc", feature = "nightly"), feature(allocator_api))] -#![cfg_attr(feature = "nightly", feature(arbitrary_self_types))] -// external crates -#[cfg(feature = "alloc")] -extern crate alloc; -// macros -#[macro_use] -mod macros { - #[macro_use] - pub(crate) mod seal; - #[macro_use] - pub(crate) mod state; -} -// modules -pub mod error; -// modules (private) -mod state; - -mod impls { - mod impl_halt; - mod impl_state; - mod impl_state_ops; - mod impl_state_repr; -} - -mod traits { - #[doc(inline)] - pub use self::{convert::*, halting::*, raw_state::*, stateful::*}; - - mod convert; - mod halting; - mod raw_state; - mod stateful; -} - -mod types { - #[doc(inline)] - pub use self::aliases::*; - - mod aliases; -} -// re-exports -#[doc(inline)] -pub use self::{error::*, state::*, traits::*, types::*}; -// prelude -#[doc(hidden)] -pub mod prelude { - #[cfg(feature = "macros")] - pub use crate::s; - pub use crate::state::*; - pub use crate::traits::*; - pub use crate::types::*; -} +/* + Appellation: rstm-state + Created At: 2025.08.29:22:43:22 + Contrib: @FL03 +*/ +//! The [`state`](self) module provides abstractions and implementations for managing state +//! within the `rstm` framework. +//! +#![crate_type = "lib"] +#![allow( + clippy::len_without_is_empty, + clippy::missing_docs_in_private_items, + clippy::missing_errors_doc, + clippy::missing_panics_doc, + clippy::missing_safety_doc, + clippy::module_inception, + clippy::needless_doctest_main, + clippy::new_ret_no_self, + clippy::should_implement_trait, + clippy::upper_case_acronyms +)] +#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(all(feature = "alloc", feature = "nightly"), feature(allocator_api))] +#![cfg_attr(feature = "nightly", feature(arbitrary_self_types))] +// external crates +#[cfg(feature = "alloc")] +extern crate alloc; +// macros +#[macro_use] +mod macros { + #[macro_use] + pub(crate) mod seal; + #[macro_use] + pub(crate) mod state; +} +// modules +pub mod error; +// modules (private) +mod state; + +mod impls { + mod impl_halt; + mod impl_state; + mod impl_state_ops; + mod impl_state_repr; +} + +mod traits { + #[doc(inline)] + pub use self::{convert::*, halting::*, raw_state::*, stateful::*}; + + mod convert; + mod halting; + mod raw_state; + mod stateful; +} + +mod types { + #[doc(inline)] + pub use self::aliases::*; + + mod aliases; +} +// re-exports +#[doc(inline)] +pub use self::{error::*, state::*, traits::*, types::*}; +// prelude +#[doc(hidden)] +pub mod prelude { + #[cfg(feature = "macros")] + pub use crate::s; + pub use crate::state::*; + pub use crate::traits::*; + pub use crate::types::*; +} diff --git a/state/src/macros/seal.rs b/crates/state/src/macros/seal.rs similarity index 100% rename from state/src/macros/seal.rs rename to crates/state/src/macros/seal.rs diff --git a/state/src/macros/state.rs b/crates/state/src/macros/state.rs similarity index 72% rename from state/src/macros/state.rs rename to crates/state/src/macros/state.rs index c9a08ef9..1e2f236e 100644 --- a/state/src/macros/state.rs +++ b/crates/state/src/macros/state.rs @@ -1,17 +1,17 @@ -/* - Appellation: state - Created At: 2025.08.30:00:11:24 - Contrib: @FL03 -*/ -#![cfg(feature = "macros")] - -/// the [`s!`] macro is a simple helper macro to create a [`State`](crate::state::State) -/// instance. -#[macro_export] -macro_rules! s { - ($($state:expr),* $(,)?) => { - $( - $crate::state::State($state), - )* - }; -} +/* + Appellation: state + Created At: 2025.08.30:00:11:24 + Contrib: @FL03 +*/ +#![cfg(feature = "macros")] + +/// the `s!` macro is a simple helper macro to create a [`State`](crate::state::State) +/// instance. +#[macro_export] +macro_rules! s { + ($($state:expr),* $(,)?) => { + $( + $crate::state::State($state), + )* + }; +} diff --git a/crates/state/src/state.rs b/crates/state/src/state.rs new file mode 100644 index 00000000..822bf2d1 --- /dev/null +++ b/crates/state/src/state.rs @@ -0,0 +1,36 @@ +/* + Appellation: state + Contrib: FL03 +*/ + +use crate::RawState; + +/// The [`State`] wrapper is a generic container used to denote objects being used as a +/// _state_ in a Turing machine, finite-state machine, or similar computational model. +#[derive(Clone, Copy, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +#[cfg_attr( + feature = "serde", + derive(serde::Deserialize, serde::Serialize), + serde(transparent) +)] +#[repr(transparent)] +pub struct State(pub Q); + +/// The [`Halt`] implementation is a binary enum designed to represent either a halting state +/// or a stepping state within a Turing machine or similar computational model. +#[derive( + Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, strum::EnumCount, strum::EnumIs, +)] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[repr(C)] +pub enum Halt +where + Q: RawState, + H: RawState, +{ + Halt(H), + Step(Q), +} + +#[cfg(test)] +mod tests {} diff --git a/state/src/traits/convert.rs b/crates/state/src/traits/convert.rs similarity index 100% rename from state/src/traits/convert.rs rename to crates/state/src/traits/convert.rs diff --git a/state/src/traits/halting.rs b/crates/state/src/traits/halting.rs similarity index 94% rename from state/src/traits/halting.rs rename to crates/state/src/traits/halting.rs index 026d0dd4..4c72adfb 100644 --- a/state/src/traits/halting.rs +++ b/crates/state/src/traits/halting.rs @@ -2,6 +2,7 @@ appellation: halted authors: @FL03 */ +use crate::RawState; use crate::state::State; /// The [`Halting`] trait establishes an interface for determining whether a given state @@ -26,7 +27,11 @@ where } } -impl Halting for Halt { +impl Halting for Halt +where + Q: RawState, + H: RawState, +{ fn is_halted(&self) -> bool { matches!(self, &Halt::Halt(_)) } diff --git a/state/src/traits/raw_state.rs b/crates/state/src/traits/raw_state.rs similarity index 100% rename from state/src/traits/raw_state.rs rename to crates/state/src/traits/raw_state.rs diff --git a/state/src/traits/stateful.rs b/crates/state/src/traits/stateful.rs similarity index 100% rename from state/src/traits/stateful.rs rename to crates/state/src/traits/stateful.rs diff --git a/state/src/types/aliases.rs b/crates/state/src/types/aliases.rs similarity index 100% rename from state/src/types/aliases.rs rename to crates/state/src/types/aliases.rs diff --git a/state/tests/default.rs b/crates/state/tests/default.rs similarity index 100% rename from state/tests/default.rs rename to crates/state/tests/default.rs diff --git a/state/tests/state.rs b/crates/state/tests/state.rs similarity index 96% rename from state/tests/state.rs rename to crates/state/tests/state.rs index 5ea8777a..93f35ac0 100644 --- a/state/tests/state.rs +++ b/crates/state/tests/state.rs @@ -1,71 +1,71 @@ -/* - Appellation: state - Contrib: FL03 -*/ -extern crate rstm_state as rstm; - -use rstm::{Halt, State}; - -#[test] -fn state() { - // create a new instance of state - let mut state = State(0); - // validate the functional accessors; get and into_inner - assert_eq!(state.get(), &0); - assert_eq!(state.value(), 0); - // replace the inner value with 1 - assert_eq!(state.replace(1), 0); - // verify the replacement - assert_eq!(*state.get(), 1); - // set the inner value to 2 - state.set(2); - // verify the update - assert_eq!(*state.get(), 2); - // reset the state to its default value - state.reset(); - // verify the reset - assert_eq!(*state.get(), 0); - // swap - state.swap(&mut State(10)); - // verify the swap - assert_eq!(*state.get(), 10); -} - -#[test] -fn halt_state() { - let state = State(0_usize); - assert_eq! { state.halt(), Halt::Halt(0) } - assert_eq! { state.into_halt(), Halt::Step(0) } -} - -#[test] -fn cast_state() { - // create a new instance of state with a value of 0_isize - let q = State(0_isize); - // cast the state to a usize - let r = unsafe { q.cast::() }; - // verify the casted state has an inner value of 0 - assert_eq!(r, 0_usize); -} - -#[test] -fn convert_state() { - // create a new instance of state with a value of 0 - let q = State(0_isize); - // convert the state into an Any - let r = q.into_any(); - // verify the converted state has an inner value of 0 - assert_eq!(*r.0.downcast_ref::().unwrap(), 0_isize); -} - -#[test] -fn numstate() { - // create a new instance of state with a value of 1 - let one = State::::one(); - // create a new instance of state with a value of 0_f64 - let zero = State::::zero(); - // verify the state has an inner value of 1 - assert_eq!(one, 1); - // verify the state has an inner value of 0 - assert_eq!(zero, 0.0); -} +/* + Appellation: state + Contrib: FL03 +*/ +extern crate rstm_state as rstm; + +use rstm::{Halt, State}; + +#[test] +fn state() { + // create a new instance of state + let mut state = State(0); + // validate the functional accessors; get and into_inner + assert_eq!(state.get(), &0); + assert_eq!(state.value(), 0); + // replace the inner value with 1 + assert_eq!(state.replace(1), 0); + // verify the replacement + assert_eq!(*state.get(), 1); + // set the inner value to 2 + state.set(2); + // verify the update + assert_eq!(*state.get(), 2); + // reset the state to its default value + state.reset(); + // verify the reset + assert_eq!(*state.get(), 0); + // swap + state.swap(&mut State(10)); + // verify the swap + assert_eq!(*state.get(), 10); +} + +#[test] +fn halt_state() { + let state = State(0_usize); + assert_eq! { state.halt(), Halt::Halt(0) } + assert_eq! { state.into_halt(), Halt::Step(0) } +} + +#[test] +fn cast_state() { + // create a new instance of state with a value of 0_isize + let q = State(0_isize); + // cast the state to a usize + let r = unsafe { q.cast::() }; + // verify the casted state has an inner value of 0 + assert_eq!(r, 0_usize); +} + +#[test] +fn convert_state() { + // create a new instance of state with a value of 0 + let q = State(0_isize); + // convert the state into an Any + let r = q.into_any(); + // verify the converted state has an inner value of 0 + assert_eq!(*r.0.downcast_ref::().unwrap(), 0_isize); +} + +#[test] +fn numstate() { + // create a new instance of state with a value of 1 + let one = State::::one(); + // create a new instance of state with a value of 0_f64 + let zero = State::::zero(); + // verify the state has an inner value of 1 + assert_eq!(one, 1); + // verify the state has an inner value of 0 + assert_eq!(zero, 0.0); +} diff --git a/tape/Cargo.toml b/crates/tape/Cargo.toml similarity index 94% rename from tape/Cargo.toml rename to crates/tape/Cargo.toml index 0773b23b..5a2da2af 100644 --- a/tape/Cargo.toml +++ b/crates/tape/Cargo.toml @@ -56,6 +56,8 @@ paste = { workspace = true } smart-default = { workspace = true } strum = { workspace = true } # logging +tracing = { optional = true, workspace = true } +# wasm wasm-bindgen = { optional = true, workspace = true } [features] @@ -81,6 +83,7 @@ json = [ macros = [] nightly = [ + "rand?/nightly", "rspace-traits/nightly", "rstm-traits/nightly", ] @@ -89,7 +92,9 @@ nightly = [ std = [ "alloc", "anyhow/std", + "bytes?/std", "contained/std", + "getrandom?/std", "rspace-traits/std", "rstm-traits/std", "rand?/std", @@ -100,6 +105,8 @@ std = [ "strum/std", "num-traits/std", "thiserror/std", + "tracing?/std", + "wasm-bindgen?/std", ] wasi = [ @@ -124,6 +131,7 @@ alloc = [ "rstm-traits/alloc", "serde?/alloc", "serde_json?/alloc", + "wasm-bindgen?/gg-alloc", ] complex = [ @@ -174,6 +182,8 @@ serde = [ serde_json = ["dep:serde_json"] +tracing = ["dep:tracing"] + wasm_bindgen = [ "dep:wasm-bindgen", "rspace-traits/wasm_bindgen", diff --git a/tape/build.rs b/crates/tape/build.rs similarity index 100% rename from tape/build.rs rename to crates/tape/build.rs diff --git a/tape/src/cell.rs b/crates/tape/src/cell.rs similarity index 100% rename from tape/src/cell.rs rename to crates/tape/src/cell.rs diff --git a/tape/src/error.rs b/crates/tape/src/error.rs similarity index 100% rename from tape/src/error.rs rename to crates/tape/src/error.rs diff --git a/tape/src/impls/impl_cell.rs b/crates/tape/src/impls/impl_cell.rs similarity index 100% rename from tape/src/impls/impl_cell.rs rename to crates/tape/src/impls/impl_cell.rs diff --git a/tape/src/impls/impl_tape_base.rs b/crates/tape/src/impls/impl_tape_base.rs similarity index 100% rename from tape/src/impls/impl_tape_base.rs rename to crates/tape/src/impls/impl_tape_base.rs diff --git a/tape/src/lib.rs b/crates/tape/src/lib.rs similarity index 91% rename from tape/src/lib.rs rename to crates/tape/src/lib.rs index fd454937..82319658 100644 --- a/tape/src/lib.rs +++ b/crates/tape/src/lib.rs @@ -2,12 +2,14 @@ //! generalizing cell-based memory systems in Rust. #![crate_type = "lib"] #![allow( + clippy::len_without_is_empty, + clippy::missing_docs_in_private_items, clippy::missing_errors_doc, clippy::missing_panics_doc, clippy::missing_safety_doc, clippy::module_inception, clippy::needless_doctest_main, - clippy::non_canonical_partial_ord_impl, + clippy::new_ret_no_self, clippy::should_implement_trait, clippy::upper_case_acronyms )] diff --git a/tape/src/macros/seal.rs b/crates/tape/src/macros/seal.rs similarity index 100% rename from tape/src/macros/seal.rs rename to crates/tape/src/macros/seal.rs diff --git a/tape/src/tape_base.rs b/crates/tape/src/tape_base.rs similarity index 100% rename from tape/src/tape_base.rs rename to crates/tape/src/tape_base.rs diff --git a/tape/src/traits/cellular.rs b/crates/tape/src/traits/cellular.rs similarity index 100% rename from tape/src/traits/cellular.rs rename to crates/tape/src/traits/cellular.rs diff --git a/tape/src/traits/raw_data.rs b/crates/tape/src/traits/raw_data.rs similarity index 100% rename from tape/src/traits/raw_data.rs rename to crates/tape/src/traits/raw_data.rs diff --git a/tape/src/traits/raw_tape.rs b/crates/tape/src/traits/raw_tape.rs similarity index 100% rename from tape/src/traits/raw_tape.rs rename to crates/tape/src/traits/raw_tape.rs diff --git a/tape/tests/default.rs b/crates/tape/tests/default.rs similarity index 100% rename from tape/tests/default.rs rename to crates/tape/tests/default.rs diff --git a/traits/Cargo.toml b/crates/traits/Cargo.toml similarity index 97% rename from traits/Cargo.toml rename to crates/traits/Cargo.toml index a9d9b475..fa3beb14 100644 --- a/traits/Cargo.toml +++ b/crates/traits/Cargo.toml @@ -80,6 +80,7 @@ std = [ "rspace-traits/std", "serde?/std", "thiserror/std", + "wasm-bindgen?/std", ] wasi = [ @@ -99,6 +100,7 @@ alloc = [ "rspace-traits/alloc", "serde?/alloc", "serde_json?/alloc", + "wasm-bindgen?/gg-alloc", ] bytes = ["dep:bytes"] diff --git a/traits/build.rs b/crates/traits/build.rs similarity index 100% rename from traits/build.rs rename to crates/traits/build.rs diff --git a/traits/src/io.rs b/crates/traits/src/io.rs similarity index 87% rename from traits/src/io.rs rename to crates/traits/src/io.rs index 690b55b8..2c052342 100644 --- a/traits/src/io.rs +++ b/crates/traits/src/io.rs @@ -3,8 +3,8 @@ Created At: 2026.01.11:13:54:16 Contrib: @FL03 */ -/// [`Reader`] establishes an interface for objects capable of reading data from internal -/// sources. +/// The [`Reader`] trait defines implementations used to actually produce output by relying on +/// configured sources. pub trait Reader { type Error: core::error::Error; diff --git a/traits/src/lib.rs b/crates/traits/src/lib.rs similarity index 85% rename from traits/src/lib.rs rename to crates/traits/src/lib.rs index 98be488c..f2dda3b8 100644 --- a/traits/src/lib.rs +++ b/crates/traits/src/lib.rs @@ -7,9 +7,14 @@ //! their components. #![crate_type = "lib"] #![allow( - clippy::missing_saftey_doc, + clippy::len_without_is_empty, + clippy::missing_docs_in_private_items, + clippy::missing_errors_doc, + clippy::missing_panics_doc, + clippy::missing_safety_doc, clippy::module_inception, clippy::needless_doctest_main, + clippy::new_ret_no_self, clippy::should_implement_trait, clippy::upper_case_acronyms )] diff --git a/traits/src/macros/seal.rs b/crates/traits/src/macros/seal.rs similarity index 100% rename from traits/src/macros/seal.rs rename to crates/traits/src/macros/seal.rs diff --git a/crates/traits/src/ops/execute.rs b/crates/traits/src/ops/execute.rs new file mode 100644 index 00000000..b5e221e4 --- /dev/null +++ b/crates/traits/src/ops/execute.rs @@ -0,0 +1,12 @@ +/* + Appellation: execute + Contrib: @FL03 +*/ + +/// The [`TryExecute`] trait is used to define a fallible execution operation over some `Rhs`. +pub trait TryExecute { + type Error; + type Output; + + fn try_execute(&mut self, rhs: Rhs) -> Result; +} diff --git a/traits/src/ops/handle.rs b/crates/traits/src/ops/handle.rs similarity index 73% rename from traits/src/ops/handle.rs rename to crates/traits/src/ops/handle.rs index 8e646d7e..bfba1994 100644 --- a/traits/src/ops/handle.rs +++ b/crates/traits/src/ops/handle.rs @@ -4,6 +4,7 @@ Contrib: @FL03 */ +#[deprecated(since = "0.1.4", note = "Use the `TryExecute` trait instead")] /// The [`Handle`] trait pub trait Handle { type Output; diff --git a/crates/traits/src/ops/increment.rs b/crates/traits/src/ops/increment.rs new file mode 100644 index 00000000..9fe5ba2c --- /dev/null +++ b/crates/traits/src/ops/increment.rs @@ -0,0 +1,64 @@ +/* + Appellation: increment + Contrib: @FL03 +*/ +/// [`Increment`] defines an unary operator for incrementing, or stepping up, a value by a +/// single unit. +pub trait Increment { + fn inc(self) -> Self; +} +/// A mutable unary operator defining a self-incrementing operation +pub trait IncrementAssign { + fn inc_assign(&mut self); +} +/// [`Decrement`] defines an unary operator for decrementing, or stepping down, a value by a +/// single unit. +pub trait Decrement { + fn dec(self) -> Self; +} +/// A mutable unary operator defining a self-decrementing operation +pub trait DecAssign { + fn dec_assign(&mut self); +} + +/* + ************* Implementations ************* +*/ +macro_rules! impl_inc_dec_for { + (@impl $T:ty: $one:literal) => { + impl Increment for $T { + fn inc(self) -> Self { + self + $one + } + } + + impl IncrementAssign for $T { + fn inc_assign(&mut self) { + *self += $one + } + } + + impl Decrement for $T { + fn dec(self) -> Self { + self - $one + } + } + + impl DecAssign for $T { + fn dec_assign(&mut self) { + *self -= $one + } + } + }; + ($($one:literal {$($T:ty),* $(,)?});* $(;)?) => { + $($(impl_inc_dec_for! { @impl $T: $one })*)* + }; +} + +impl_inc_dec_for! { + 1 { + u8, u16, u32, u64, u128, usize, + i8, i16, i32, i64, i128, isize, + }; + 1.0 { f32, f64 }; +} diff --git a/traits/src/ops/percentage.rs b/crates/traits/src/ops/percentage.rs similarity index 100% rename from traits/src/ops/percentage.rs rename to crates/traits/src/ops/percentage.rs diff --git a/traits/src/ops/step.rs b/crates/traits/src/ops/step.rs similarity index 56% rename from traits/src/ops/step.rs rename to crates/traits/src/ops/step.rs index 659319ec..90736ac3 100644 --- a/traits/src/ops/step.rs +++ b/crates/traits/src/ops/step.rs @@ -4,12 +4,11 @@ Contrib: @FL03 */ -/// A trait defining an unary step operation primarily intended to enable iterable execution -/// patterns from implemented machines. +/// The [`TryStep`] trait establishes an interface for a fallible step operation pub trait TryStep { type Error; type Output; - /// Performs a step operation + /// try to perform a step operation fn try_step(&mut self) -> Result; } diff --git a/traits/src/symbols.rs b/crates/traits/src/symbols.rs similarity index 100% rename from traits/src/symbols.rs rename to crates/traits/src/symbols.rs diff --git a/traits/tests/default.rs b/crates/traits/tests/default.rs similarity index 100% rename from traits/tests/default.rs rename to crates/traits/tests/default.rs diff --git a/default.nix b/default.nix index dcc92b3b..21e31777 100644 --- a/default.nix +++ b/default.nix @@ -5,14 +5,15 @@ let overlays = [ (import rust-overlay) ]; }; - rustVersion = "1.85.0"; - wasmUnknownUknown = "wasm32-unknown-unknown"; - wasm32Wasi = "wasm32-wasi"; + rustVersion = "1.91.0"; + + wasm = "wasm32-unknown-unknown"; + wasi = "wasm32-wasip2"; rustDefaultTarget = rustPkgs.rust-bin.stable.${rustVersion}.default; rustWithWasmTarget = rustPkgs.rust-bin.nightly.${rustVersion}.default.override { - targets = [ wasmUnknownUknown ]; + targets = [ wasm ]; }; rustPlatform = makeRustPlatform { @@ -26,7 +27,7 @@ let }; common = { - version = "0.1.3"; + version = "0.1.4"; src = self; cargoLock = { diff --git a/flake.nix b/flake.nix index 244c8b5b..83585788 100644 --- a/flake.nix +++ b/flake.nix @@ -1,5 +1,6 @@ { - description = "A developmental environment for a Rust project using Nix flakes with direnv"; + description = + "A developmental environment for a Rust project using Nix flakes with direnv"; inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; @@ -19,25 +20,24 @@ in rec { packages.default = pkgs.rustPlatform.buildRustPackage { pname = "rstm"; - version = "0.1.3"; + version = "0.1.4"; src = self; # ./.; - cargoLock = { - lockFile = ./Cargo.lock; - }; + cargoLock = { lockFile = ./Cargo.lock; }; }; devShells.default = pkgs.mkShell { buildInputs = [ rustToolchain - pkgs.cargo - pkgs.rust-analyzer pkgs.pkg-config pkgs.openssl + pkgs.cargo + pkgs.rust-analyzer + pkgs.cargo-binstall + pkgs.cargo-criterion ]; shellHook = '' export CARGO_HOME=$PWD/.cargo ''; }; - } - ); -} \ No newline at end of file + }); +} diff --git a/state/src/state.rs b/state/src/state.rs deleted file mode 100644 index 29632558..00000000 --- a/state/src/state.rs +++ /dev/null @@ -1,44 +0,0 @@ -/* - Appellation: state - Contrib: FL03 -*/ - -/// The [`State`] wrapper is a generic container used to denote objects being used as a -/// _state_ in a Turing machine, finite-state machine, or similar computational model. -#[derive(Clone, Copy, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] -#[cfg_attr( - feature = "serde", - derive(serde::Deserialize, serde::Serialize), - serde(transparent) -)] -#[repr(transparent)] -pub struct State(pub Q); - -/// Inline with the formal definition of a halt state, the [`Halt`] implementation -/// extends a stateful object, enabling _**any**_ given state to be halted. -#[derive( - Clone, - Copy, - Debug, - Eq, - Hash, - Ord, - PartialEq, - PartialOrd, - strum::EnumDiscriminants, - strum::EnumIs, -)] -#[cfg_attr( - feature = "serde", - derive(serde::Deserialize, serde::Serialize), - strum_discriminants(derive(serde::Deserialize, serde::Serialize)) -)] -#[strum_discriminants(name(HaltTag), derive(Hash, Ord, PartialOrd))] -#[repr(C)] -pub enum Halt { - Halt(H), - Step(Q), -} - -#[cfg(test)] -mod tests {} diff --git a/traits/src/ops/execute.rs b/traits/src/ops/execute.rs deleted file mode 100644 index 33f8a17c..00000000 --- a/traits/src/ops/execute.rs +++ /dev/null @@ -1,86 +0,0 @@ -/* - Appellation: execute - Contrib: @FL03 -*/ - -/// The [`ExecuteOnce`] defines the ability for an object to perform **exactly** one execution -/// or computation. -pub trait ExecuteOnce { - type Output; - - fn execute(self, rhs: Rhs) -> Self::Output; -} -/// A trait denoting the ability to execute a given operation, transaction, etc. -pub trait Execute { - type Output; - - fn execute(&self, rhs: Rhs) -> Self::Output; -} -/// The [`ExecuteMut`] trait is similar to [`Execute`], but it allows for -/// mutable execution of the operation, transaction, etc. This is useful when -/// the operation needs mutable access to the data being operated on. -pub trait ExecuteMut { - type Output; - - fn execute(&mut self, rhs: Rhs) -> Self::Output; -} - -/// The [`TryExecuteOnce`] trait defines the ability for an object to perform -/// one execution or computation that may fail, returning a `Result` configured to use the -/// defined error type. -pub trait TryExecuteOnce { - type Error; - type Output; - - fn try_execute(self, rhs: Rhs) -> Result; -} - -pub trait TryExecuteMut { - type Error; - type Output; - - fn try_execute(&mut self, rhs: Rhs) -> Result; -} - -pub trait TryExecute { - type Error; - type Output; - - fn try_execute(&self, rhs: Rhs) -> Result; -} - -/* - ************* Implementations ************* -*/ -impl ExecuteOnce for F -where - F: FnOnce(U) -> V, -{ - type Output = V; - - fn execute(self, rhs: U) -> Self::Output { - self(rhs) - } -} - -impl ExecuteMut for F -where - F: FnMut(U) -> V, -{ - type Output = V; - - fn execute(&mut self, rhs: U) -> Self::Output { - self(rhs) - } -} - -impl Execute for F -where - F: Fn(U) -> V, -{ - type Output = V; - - fn execute(&self, rhs: U) -> Self::Output { - self(rhs) - } -} diff --git a/traits/src/ops/increment.rs b/traits/src/ops/increment.rs deleted file mode 100644 index 67fd53ee..00000000 --- a/traits/src/ops/increment.rs +++ /dev/null @@ -1,61 +0,0 @@ -/* - Appellation: increment - Contrib: @FL03 -*/ -/// An unary operator defining an incremental operation -pub trait Increment { - fn increment(self) -> Self; -} -/// A mutable unary operator defining a self-incrementing operation -pub trait IncrementMut { - fn increment_mut(&mut self); -} -/// An unary operator defining a decremental operation -pub trait Decrement { - fn decrement(self) -> Self; -} -/// A mutable unary operator defining a self-decrementing operation -pub trait DecrementMut { - fn decrement_mut(&mut self); -} - -/* - ************* Implementations ************* -*/ -use num_traits::One; - -impl Decrement for T -where - T: One + core::ops::Sub, -{ - fn decrement(self) -> Self { - self - T::one() - } -} - -impl DecrementMut for T -where - T: One + core::ops::SubAssign, -{ - fn decrement_mut(&mut self) { - *self -= T::one() - } -} - -impl Increment for T -where - T: One + core::ops::Add, -{ - fn increment(self) -> Self { - self + T::one() - } -} - -impl IncrementMut for T -where - T: One + core::ops::AddAssign, -{ - fn increment_mut(&mut self) { - *self += T::one() - } -}