├── src ├── lib.rs ├── ui │ ├── mod.rs │ ├── handler.rs │ ├── simulation.rs │ └── menu.rs ├── ram │ ├── types.rs │ ├── mod.rs │ ├── op.rs │ ├── rel.rs │ ├── instruction.rs │ ├── instruction_op.rs │ └── machine.rs ├── main.rs └── parser.rs ├── gif ├── menu.gif └── simulation.gif ├── data ├── testing │ ├── load_store.ram │ ├── test.ram │ ├── basic_arithmetic.ram │ ├── cond_reg_const.ram │ ├── jump_skip_code.ram │ ├── add_five_times.ram │ └── read_first_half.ram └── programs │ ├── fibonacci.ram │ ├── reverse.ram │ └── do_everything.ram ├── Cargo.toml ├── .github └── workflows │ ├── tests.yml │ └── publish.yml ├── .gitignore ├── LICENSE ├── tests ├── combined.rs ├── parser.rs └── machine.rs └── README.md /src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod parser; 2 | pub mod ui; 3 | pub mod ram; -------------------------------------------------------------------------------- /src/ui/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod handler; 2 | mod simulation; 3 | mod menu; -------------------------------------------------------------------------------- /gif/menu.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kkobarii/Rusty-Tape/HEAD/gif/menu.gif -------------------------------------------------------------------------------- /gif/simulation.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kkobarii/Rusty-Tape/HEAD/gif/simulation.gif -------------------------------------------------------------------------------- /src/ram/types.rs: -------------------------------------------------------------------------------- 1 | pub type Number = i32; 2 | pub type Index = usize; 3 | pub type Label = String; 4 | -------------------------------------------------------------------------------- /data/testing/load_store.ram: -------------------------------------------------------------------------------- 1 | R0 := 2 2 | R1 := 42 3 | [R0] := R1 4 | R3 := [R0] 5 | R4 := [R1] # nothing here -------------------------------------------------------------------------------- /data/testing/test.ram: -------------------------------------------------------------------------------- 1 | R0 := 2 2 | R1 := 21 3 | [R0] := R1 4 | R0 := R0 + 1 5 | R1 := R1 * 2 6 | [R0] := R1 7 | halt -------------------------------------------------------------------------------- /src/ram/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod machine; 2 | pub mod op; 3 | pub mod rel; 4 | pub mod instruction_op; 5 | pub mod types; 6 | pub mod instruction; -------------------------------------------------------------------------------- /data/testing/basic_arithmetic.ram: -------------------------------------------------------------------------------- 1 | start: R0 := 10 2 | R3 := R0 + 5 3 | R4 := R0 - 5 4 | R5 := R0 * 5 5 | R6 := R0 / 5 -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rusty_tape" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | ratatui = "0.29.0" 8 | walkdir = "2.5.0" 9 | -------------------------------------------------------------------------------- /data/testing/cond_reg_const.ram: -------------------------------------------------------------------------------- 1 | R0 := 4 2 | R2 := 5 3 | if (R0 < R2) goto true 4 | R1 := -1 5 | goto end 6 | true: R1 := 1 7 | end: halt -------------------------------------------------------------------------------- /data/testing/jump_skip_code.ram: -------------------------------------------------------------------------------- 1 | R0 := 1 2 | R1 := 3 3 | R2 := 1000 4 | R0 := R0 + R1 5 | goto skip 6 | R0 := R0 + R2 7 | skip: R0 := R0 + R1 -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | pub mod parser; 2 | pub mod ui; 3 | pub mod ram; 4 | 5 | use crate::ui::handler::UiHandler; 6 | 7 | fn main() { 8 | let mut ui = UiHandler::default(); 9 | ui.run().expect("Error running UI"); 10 | } 11 | -------------------------------------------------------------------------------- /data/testing/add_five_times.ram: -------------------------------------------------------------------------------- 1 | R0 := 0 # sum 2 | R1 := 2 # increment 3 | R2 := 5 # counter 4 | start: if (R2 <= 0) goto end 5 | R0 := R0 + R1 6 | R2 := R2 - 1 7 | goto start 8 | end: halt -------------------------------------------------------------------------------- /data/testing/read_first_half.ram: -------------------------------------------------------------------------------- 1 | R0 := 0 # counter 2 | 3 | loop: if (R0 >= 4) goto end 4 | R1 := R0 / 2 5 | if (R1 != 0) goto skip 6 | R2 := read() 7 | R2 := R2 * 10 8 | write(R2) 9 | 10 | skip: R0 := R0 + 1 11 | goto loop 12 | 13 | end: halt -------------------------------------------------------------------------------- /data/programs/fibonacci.ram: -------------------------------------------------------------------------------- 1 | # source: adaxiik, rest his soul 2 | 3 | R0 := read() # R0 = n 4 | R1 := 0 5 | R2 := 1 6 | L: if (R0 <= 0) goto END 7 | R3 := R2 8 | R2 := R3 + R1 9 | R1 := R3 10 | R0 := R0 - 1 11 | goto L 12 | END: write(R1) # write fib(n) 13 | halt -------------------------------------------------------------------------------- /data/programs/reverse.ram: -------------------------------------------------------------------------------- 1 | # Input a list of numbers 2 | # End the list with a 0 3 | # Output is the list in reverse order 4 | 5 | R0 := 3 6 | R1 := R0 7 | L1: R2 := read() 8 | if (R2 == 0) goto L3 9 | [R1] := R2 10 | R1 := R1 + 1 11 | goto L1 12 | L2: R1 := R1 - 1 13 | R2 := [R1] 14 | write(R2) 15 | L3: if (R1 > R0) goto L2 16 | halt -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | 3 | on: 4 | push: 5 | branches: [ "master", "actions" ] 6 | pull_request: 7 | branches: [ "master", "actions" ] 8 | 9 | env: 10 | CARGO_TERM_COLOR: always 11 | 12 | jobs: 13 | run-tests: 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - uses: actions/checkout@v4 18 | - name: Build 19 | run: cargo build --verbose 20 | - name: Run tests 21 | run: cargo test --verbose 22 | -------------------------------------------------------------------------------- /src/ram/op.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::Display; 2 | 3 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] 4 | pub enum Op { 5 | Add, 6 | Sub, 7 | Mul, 8 | Div, 9 | } 10 | 11 | impl Display for Op { 12 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 13 | match self { 14 | Op::Add => write!(f, "+"), 15 | Op::Sub => write!(f, "-"), 16 | Op::Mul => write!(f, "*"), 17 | Op::Div => write!(f, "/"), 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /src/ram/rel.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::Display; 2 | 3 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] 4 | pub enum Rel { 5 | Lt, 6 | Gt, 7 | Le, 8 | Ge, 9 | Eq, 10 | Ne, 11 | } 12 | 13 | impl Display for Rel { 14 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 15 | match self { 16 | Rel::Lt => write!(f, "<"), 17 | Rel::Gt => write!(f, ">"), 18 | Rel::Le => write!(f, "<="), 19 | Rel::Ge => write!(f, ">="), 20 | Rel::Eq => write!(f, "=="), 21 | Rel::Ne => write!(f, "!="), 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | release: 5 | types: [created] 6 | 7 | jobs: 8 | release: 9 | name: release ${{ matrix.target }} 10 | runs-on: ubuntu-latest 11 | strategy: 12 | fail-fast: false 13 | matrix: 14 | target: [x86_64-pc-windows-gnu, x86_64-unknown-linux-musl] 15 | steps: 16 | - uses: actions/checkout@master 17 | - name: Compile and release 18 | uses: rust-build/rust-build.action@v1.4.5 19 | env: 20 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 21 | with: 22 | RUSTTARGET: ${{ matrix.target }} 23 | EXTRA_FILES: "README.md LICENSE data/*/*.ram gif/*" 24 | -------------------------------------------------------------------------------- /data/programs/do_everything.ram: -------------------------------------------------------------------------------- 1 | # testing ram to try everything it can do 2 | # it reads in a number of items, 3 | # saves them to memory, 4 | # then prints them out times 10 5 | 6 | # save number of items on input to r0 7 | R0 := read() 8 | 9 | # save that many items to memory 10 | R1 := 0 11 | memory_loop: if (R1 == R0) goto end_memory_loop 12 | R2 := read() 13 | R3 := R1 + 10 14 | [R3] := R2 15 | R1 := R1 + 1 16 | goto memory_loop 17 | 18 | # print out the memory times 10 19 | end_memory_loop: R1 := 0 20 | print_loop: if (R1 == R0) goto end_print_loop 21 | R3 := R1 + 10 22 | R2 := [R3] 23 | R2 := R2 * 10 24 | write(R2) 25 | R1 := R1 + 1 26 | goto print_loop 27 | 28 | end_print_loop: halt -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | debug/ 4 | target/ 5 | 6 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 7 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 8 | Cargo.lock 9 | 10 | # These are backup files generated by rustfmt 11 | **/*.rs.bk 12 | 13 | # MSVC Windows builds of rustc generate these, which store debugging information 14 | *.pdb 15 | 16 | # RustRover 17 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 18 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 19 | # and can be added to the global gitignore or merged into this file. For a more nuclear 20 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 21 | .idea/ -------------------------------------------------------------------------------- /src/ram/instruction.rs: -------------------------------------------------------------------------------- 1 | use crate::ram::instruction_op::InstructionOp; 2 | use crate::ram::types::Label; 3 | 4 | #[derive(Debug, Clone, PartialEq)] 5 | pub struct Instruction { 6 | pub label: Option