├── .envrc ├── ex3.ram ├── .gitignore ├── .replit ├── src ├── tests │ ├── std │ │ ├── mod.rs │ │ ├── parse.rs │ │ └── string.rs │ ├── mod.rs │ ├── operations │ │ ├── mod.rs │ │ ├── div.rs │ │ ├── mul.rs │ │ ├── sub.rs │ │ └── add.rs │ └── stack │ │ ├── mod.rs │ │ ├── drop.rs │ │ ├── butterfly.rs │ │ ├── stack_test.rs │ │ ├── copy.rs │ │ └── vec.rs ├── funcs │ ├── operations │ │ ├── mod.rs │ │ ├── mul.rs │ │ ├── sub.rs │ │ ├── add.rs │ │ ├── div.rs │ │ └── cmp.rs │ ├── stdf │ │ ├── mod.rs │ │ ├── rand.rs │ │ ├── parse.rs │ │ ├── stdin.rs │ │ ├── stdfs.rs │ │ └── string.rs │ ├── mod.rs │ ├── errors.rs │ ├── print.rs │ ├── butterfly.rs │ ├── jump.rs │ ├── stack.rs │ └── vec.rs ├── main.rs ├── parser.rs ├── lib.rs └── memory.rs ├── ex.ram ├── examples ├── interpreter │ ├── test.txt │ ├── var.ram │ ├── parser.ram │ ├── jump.ram │ └── interpreter.ram ├── loop.txt ├── head_tails.ram ├── map_bench.ram ├── largest_number.ram └── deep_map.ram ├── ex2.ram ├── Cargo.toml ├── .github └── workflows │ └── rust.yml ├── flake.nix ├── README.md ├── .vscode └── launch.json ├── flake.lock └── Cargo.lock /.envrc: -------------------------------------------------------------------------------- 1 | use flake -------------------------------------------------------------------------------- /ex3.ram: -------------------------------------------------------------------------------- 1 | one: 2 | print hello from one -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | plan.txt 3 | /.direnv -------------------------------------------------------------------------------- /.replit: -------------------------------------------------------------------------------- 1 | language = "rust" 2 | run = "cargo run" -------------------------------------------------------------------------------- /src/tests/std/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod parse; 2 | pub mod string; 3 | -------------------------------------------------------------------------------- /src/tests/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod operations; 2 | pub mod stack; 3 | pub mod std; 4 | -------------------------------------------------------------------------------- /ex.ram: -------------------------------------------------------------------------------- 1 | main: 2 | ram a :int = 10 3 | ram b :float = 20.13 4 | print var b -------------------------------------------------------------------------------- /examples/interpreter/test.txt: -------------------------------------------------------------------------------- 1 | main: 2 | var x int = 10 3 | push var x 4 | print -------------------------------------------------------------------------------- /src/tests/operations/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod add; 2 | pub mod div; 3 | pub mod mul; 4 | pub mod sub; 5 | -------------------------------------------------------------------------------- /src/funcs/operations/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod add; 2 | pub mod cmp; 3 | pub mod div; 4 | pub mod mul; 5 | pub mod sub; 6 | -------------------------------------------------------------------------------- /src/funcs/stdf/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod parse; 2 | pub mod rand; 3 | pub mod stdfs; 4 | pub mod stdin; 5 | pub mod string; 6 | -------------------------------------------------------------------------------- /src/tests/stack/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod butterfly; 2 | pub mod copy; 3 | pub mod stack_test; 4 | pub mod vec; 5 | pub mod drop; 6 | -------------------------------------------------------------------------------- /src/funcs/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod butterfly; 2 | pub mod errors; 3 | pub mod jump; 4 | pub mod operations; 5 | pub mod print; 6 | pub mod stack; 7 | pub mod stdf; 8 | pub mod vec; 9 | -------------------------------------------------------------------------------- /ex2.ram: -------------------------------------------------------------------------------- 1 | main: 2 | ram lx 3 | ram 1 4 | add 5 | ram lx prev 6 | print var lx 7 | ram lx 8 | ram 1000 9 | cmp 10 | je halt: 11 | jmp main: 12 | 13 | halt: 14 | halt -------------------------------------------------------------------------------- /examples/loop.txt: -------------------------------------------------------------------------------- 1 | main: 2 | ram lx 3 | ram 1 4 | add 5 | ram lx prev 6 | print var lx 7 | ram lx 8 | ram 500 9 | cmp 10 | je halt: 11 | jmp main: 12 | 13 | halt: 14 | halt -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ram" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | rand = "0.8.4" 10 | regex = "1.5" -------------------------------------------------------------------------------- /examples/head_tails.ram: -------------------------------------------------------------------------------- 1 | main: 2 | print Coin Flip 3 | rand [0,2] 4 | ram lx prev 5 | ram lx 6 | ram 1 7 | cmp 8 | je heads: 9 | pop 10 | ram lx 11 | ram 0 12 | cmp 13 | je tails: 14 | 15 | heads: 16 | print Heads 17 | halt 18 | 19 | tails: 20 | print Tails 21 | halt -------------------------------------------------------------------------------- /examples/map_bench.ram: -------------------------------------------------------------------------------- 1 | main: 2 | ram i :int = 0 3 | jmp ok: 4 | 5 | ok: 6 | ram lx 1 7 | add i lx 8 | ram lx prev 9 | copy i = lx 10 | ram v8 :map 11 | insert v8 { "hp": 3000 } 12 | insert v8 { "meow": 3000 } 13 | insert v8 { "omk": "3000" } 14 | 15 | ram car :map 16 | insert car { "name": "d" } 17 | insert car { "engine": v8 } 18 | 19 | ram lx 20 | ram 500000000 21 | cmp 22 | je halt: 23 | drop car 24 | jmp ok: 25 | 26 | halt: 27 | dbg 28 | halt 29 | -------------------------------------------------------------------------------- /.github/workflows/rust.yml: -------------------------------------------------------------------------------- 1 | name: Rust 2 | 3 | on: 4 | push: 5 | branches: [ master, dev ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | env: 10 | CARGO_TERM_COLOR: always 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | - name: Build 20 | run: cargo build --verbose 21 | - name: Run unit test 22 | run: cargo test --verbose 23 | # - name: E2E 24 | # run: cargo run ./examples/default.ram --verbose 25 | -------------------------------------------------------------------------------- /examples/largest_number.ram: -------------------------------------------------------------------------------- 1 | main: 2 | ram nums :vec :int = [12, 22, 14, 10000] 3 | ram largest :int = 0 4 | vec largest = nums[0] 5 | ram i :int = 0 6 | ram curr :int = 0 7 | jmp a: 8 | 9 | a: 10 | vec curr = nums[i] 11 | ram 1 12 | add i 13 | ram lx prev 14 | copy i = lx 15 | copy lx = curr 16 | ram lx 17 | copy lx = largest 18 | ram lx 19 | cmp 20 | jgr swap: 21 | copy lx = i 22 | ram lx 23 | vec nums len 24 | cmp 25 | jne a: 26 | print var largest 27 | halt 28 | 29 | swap: 30 | copy largest = curr 31 | ret -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | inputs = { 3 | naersk.url = "github:nix-community/naersk/master"; 4 | nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; 5 | utils.url = "github:numtide/flake-utils"; 6 | }; 7 | 8 | outputs = { self, nixpkgs, utils, naersk }: 9 | utils.lib.eachDefaultSystem (system: 10 | let 11 | pkgs = import nixpkgs { inherit system; }; 12 | naersk-lib = pkgs.callPackage naersk { }; 13 | in 14 | { 15 | defaultPackage = naersk-lib.buildPackage ./.; 16 | devShell = with pkgs; mkShell { 17 | buildInputs = [ 18 | cargo 19 | rustc 20 | rustfmt 21 | rustPackages.clippy 22 | bashInteractive 23 | rust-analyzer 24 | ]; 25 | RUST_SRC_PATH = rustPlatform.rustLibSrc; 26 | }; 27 | } 28 | ); 29 | } -------------------------------------------------------------------------------- /examples/deep_map.ram: -------------------------------------------------------------------------------- 1 | main: 2 | ram x :map 3 | 4 | ram y :map 5 | insert x { "randstring": y } 6 | 7 | ram z :map 8 | insert z { "randstring1": x } 9 | 10 | ram a :map 11 | insert a { "randstring2": z } 12 | 13 | ram b :map 14 | insert b { "randstring3": a } 15 | 16 | ram c :map 17 | insert c { "randstring4": b } 18 | 19 | ram d :map 20 | insert d { "randstring5": c } 21 | 22 | ram e :map 23 | insert e { "randstring6": d } 24 | 25 | ram f :map 26 | insert f { "randstring7": e } 27 | 28 | ram g :map 29 | insert g { "randstring8": f } 30 | 31 | ram h :map 32 | insert h { "randstring9": g } 33 | 34 | ram i :map 35 | insert i { "randstring10": h } 36 | 37 | ram j :map 38 | insert j { "randstring11": i } 39 | 40 | ram k :map 41 | insert k { "randstring12": j } 42 | 43 | ram l :map 44 | insert l { "randstring13": k } 45 | 46 | ram m :map 47 | insert m { "randstring14": l } 48 | 49 | ram n :map 50 | insert n { "randstring15": m } 51 | dbg -------------------------------------------------------------------------------- /examples/interpreter/var.ram: -------------------------------------------------------------------------------- 1 | var: 2 | vec cmd len 3 | ram 5 4 | cmp 5 | jsm var_len_err: 6 | ram var_name :str = "" 7 | ram type :str = "" 8 | vec type = cmd[2] 9 | vec var_name = cmd[1] 10 | ram match_type :str = "str" 11 | cmp type match_type 12 | je var_add_str: 13 | 14 | ram match_type :str = "int" 15 | cmp type match_type 16 | je var_add_int: 17 | 18 | drop match_type 19 | drop type 20 | drop var_name 21 | ret 22 | 23 | var_add_int: 24 | ram int_str :str = "" 25 | vec int_str = cmd[4] 26 | parse int_str :int 27 | ram temp_lx :int = 0 28 | copy temp_lx = lx 29 | insert vars_int { var_name: temp_lx } 30 | 31 | drop temp_lx 32 | drop int_str 33 | ret 34 | 35 | var_add_str: 36 | ram eq :vec :str = [] 37 | split statement > "=" = eq 38 | ram value :str = "" 39 | vec value = eq[1] 40 | trim value 41 | insert vars_str { var_name: value } 42 | 43 | drop value 44 | drop eq 45 | ret 46 | 47 | var_len_err: 48 | syntax error: bad args for var command 49 | halt 50 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | use std::fs::File; 2 | use std::io::prelude::*; 3 | use std::{env, io}; 4 | 5 | use ram::memory::Memory; 6 | use ram::parser::{self, LabelMap}; 7 | use ram::types::Vars; 8 | use ram::CPU; 9 | 10 | fn main() { 11 | let mut filename: String = String::new(); 12 | if env::args().nth(1).is_none() { 13 | println!("Welcome to the Ram stack-based programming language."); 14 | println!("Please enter a filename: "); 15 | io::stdin() 16 | .read_line(&mut filename) 17 | .expect("Error reading filename"); 18 | filename = filename.trim().to_string(); 19 | } else { 20 | filename = env::args().nth(1).unwrap() 21 | } 22 | let mut file: File = File::open(filename.trim()).expect("Error opening file"); 23 | let mut contents: String = String::new(); 24 | file.read_to_string(&mut contents) 25 | .expect("Error reading file"); 26 | 27 | let p_lines: Vec<&str> = contents.split('\n').collect(); 28 | let program: LabelMap = parser::parse_lines(p_lines); 29 | let instructions = program.instructions; 30 | let label_map = program.map; 31 | 32 | let mut cpu = CPU::new(); 33 | let mut memory = Memory::new(); 34 | let mut vars = Vars::new(); 35 | 36 | cpu.execute(instructions, label_map, &mut memory, &mut vars); 37 | } 38 | -------------------------------------------------------------------------------- /examples/interpreter/parser.ram: -------------------------------------------------------------------------------- 1 | parser_loop: 2 | ram statement :str = "" 3 | vec statement = program[i] 4 | trim statement 5 | 6 | jmp parser_start: 7 | 8 | ram lx 1 9 | add i lx 10 | ram lx prev 11 | copy i = lx 12 | 13 | cmp plen i 14 | jne parser_loop: 15 | ret 16 | 17 | parser_start: 18 | ram isLabel :int = 0 19 | ram chars :vec :str = [] 20 | split statement > "" = chars 21 | vec chars len 22 | ram 0 23 | cmp 24 | jne parser_label: 25 | ret 26 | 27 | parser_label: 28 | vec chars len 29 | ram 1 30 | sub 31 | ram lx prev 32 | ram col :str = "" 33 | vec col = chars[lx] 34 | ram string = ":" 35 | cmp col string 36 | je add_label_check: 37 | ram lx 1 38 | cmp isLabel lx 39 | jne push_instruction: 40 | drop chars 41 | ret 42 | 43 | push_instruction: 44 | ram lx 1 45 | add parser_ip lx 46 | ram lx prev 47 | copy parser_ip = lx 48 | vec instructions push statement 49 | ret 50 | 51 | add_label_check: 52 | ram cmd :vec :str = [] 53 | split statement > " " = cmd 54 | vec cmd len 55 | ram 1 56 | cmp 57 | drop cmd 58 | je add_label: 59 | ret 60 | 61 | add_label: 62 | ram isLabel :int = 1 63 | insert labelMap { statement: parser_ip } 64 | ret 65 | 66 | -------------------------------------------------------------------------------- /src/tests/stack/drop.rs: -------------------------------------------------------------------------------- 1 | use crate::funcs::stack::drop; 2 | use crate::{memory::Memory, types::Vars}; 3 | 4 | #[test] 5 | #[should_panic] 6 | fn drop_str() { 7 | let mut memory: Memory = Memory::new(); 8 | let mut vars: Vars = Vars::new(); 9 | vars.set_string("x".to_string(), "ok", &mut memory); 10 | let statement: &str = "drop x"; 11 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 12 | drop(&mut memory, &mut vars, cmd).unwrap(); 13 | vars.get_type("x".to_string()).unwrap(); 14 | } 15 | 16 | #[test] 17 | #[should_panic] 18 | fn drop_int_vec() { 19 | let mut memory: Memory = Memory::new(); 20 | let mut vars: Vars = Vars::new(); 21 | vars.set_int_vec("x".to_string(), "[1, 2, 3]", &mut memory).unwrap(); 22 | let statement: &str = "drop x"; 23 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 24 | drop(&mut memory, &mut vars, cmd).unwrap(); 25 | vars.get_type("x".to_string()).unwrap(); 26 | } 27 | 28 | #[test] 29 | #[should_panic] 30 | fn drop_str_vec() { 31 | let mut memory: Memory = Memory::new(); 32 | let mut vars: Vars = Vars::new(); 33 | vars.set_str_vec("x".to_string(), "['a', 'b', 'c']", &mut memory); 34 | let statement: &str = "drop x"; 35 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 36 | drop(&mut memory, &mut vars, cmd).unwrap(); 37 | vars.get_type("x".to_string()).unwrap(); 38 | } 39 | 40 | -------------------------------------------------------------------------------- /src/funcs/stdf/rand.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | funcs::errors::{self, ErrorKind}, 3 | memory::Memory, 4 | CPU, 5 | }; 6 | use rand::Rng; 7 | 8 | // rand [1,10] 9 | // rand lx [10,10] 10 | // rand rv [10,20] 11 | // rand lx [rv,lx] 12 | 13 | pub fn rand( 14 | memory: &mut Memory, 15 | registers: &mut CPU, 16 | cmd: Vec<&str>, 17 | statement: &str, 18 | ) -> Result<(), ErrorKind> { 19 | let num1: i32; 20 | let num2: i32; 21 | let coma_split: Vec<&str> = statement.split(',').collect(); 22 | let num1_str = coma_split[0].split('[').collect::>()[1].trim(); 23 | let num2_str = coma_split[1].split(']').collect::>()[0].trim(); 24 | 25 | match num1_str { 26 | "lx" => num1 = registers.lx, 27 | "rv" => num1 = registers.rv, 28 | _ => num1 = errors::parse_int(num1_str)?, 29 | } 30 | 31 | match num2_str { 32 | "lx" => num2 = registers.lx, 33 | "rv" => num2 = registers.rv, 34 | _ => num2 = errors::parse_int(num2_str)?, 35 | } 36 | 37 | if num1 >= num2 { 38 | return Err(ErrorKind::RangeNegative); 39 | } 40 | 41 | let mut rng = rand::thread_rng(); 42 | let random_num = rng.gen_range(num1..num2); 43 | 44 | match cmd[1] { 45 | "lx" => registers.lx = random_num, 46 | "rv" => registers.rv = random_num, 47 | _ => memory.set_int_to_stack(random_num), 48 | } 49 | Ok(()) 50 | } 51 | -------------------------------------------------------------------------------- /src/funcs/stdf/parse.rs: -------------------------------------------------------------------------------- 1 | use crate::funcs::errors::{self, ErrorKind}; 2 | use crate::types::{TypeName, Vars}; 3 | use crate::{memory::Memory, CPU}; 4 | 5 | pub fn parse( 6 | memory: &mut Memory, 7 | vars: &mut Vars, 8 | registers: &mut CPU, 9 | cmd: Vec<&str>, 10 | ) -> Result<(), ErrorKind> { 11 | if cmd.len() < 3 { 12 | return Err(ErrorKind::ArgErr); 13 | } 14 | 15 | match cmd[2] { 16 | ":int" => match cmd[1] { 17 | "string" => registers.lx = errors::parse_int(®isters.string)?, 18 | "lxstring" => registers.lx = errors::parse_int(®isters.lxstring)?, 19 | _ => { 20 | let t = vars.get_type(cmd[1].to_string())?; 21 | registers.lx = errors::parse_int(&memory.yeild_string(t.location))? 22 | } 23 | }, 24 | ":str" => match cmd[1] { 25 | "lx" => registers.string = registers.lx.to_string(), 26 | "rv" => registers.string = registers.rv.to_string(), 27 | _ => { 28 | let t = vars.get_type(cmd[1].to_string())?; 29 | if t.name == TypeName::I32 { 30 | registers.string = memory.yeild_i32(t.location).to_string(); 31 | } else { 32 | return Err(ErrorKind::ExpectedInt(cmd[1].to_string())); 33 | } 34 | } 35 | }, 36 | _ => return Err(ErrorKind::ArgErr), 37 | } 38 | Ok(()) 39 | } 40 | -------------------------------------------------------------------------------- /examples/interpreter/jump.ram: -------------------------------------------------------------------------------- 1 | jmp: 2 | ram labelName :str = "" 3 | vec labelName = cmd[1] 4 | jmp get_label_id: 5 | jmp push_pc_callstack: 6 | ram pc :int = 0 7 | copy pc = label_id 8 | ret 9 | 10 | jc_prepare: 11 | vec stack len 12 | ram 1 13 | sub 14 | ram lx prev 15 | ram stack_int :int = 0 16 | vec stack_int = stack[lx] 17 | copy lx = stack_int 18 | drop stack_int 19 | vec stack pop 20 | ret 21 | 22 | je: 23 | jmp jc_prepare: 24 | ram 0 25 | ram lx 26 | cmp 27 | je jmp: 28 | ret 29 | 30 | jne: 31 | jmp jc_prepare: 32 | ram 0 33 | ram lx 34 | cmp 35 | jne jmp: 36 | ret 37 | 38 | jsm: 39 | jmp jc_prepare: 40 | ram -1 41 | ram lx 42 | cmp 43 | je jmp: 44 | ret 45 | 46 | jgr: 47 | jmp jc_prepare: 48 | ram 1 49 | ram lx 50 | cmp 51 | je jmp: 52 | ret 53 | 54 | get_label_id: 55 | ram label_id :int = 0 56 | get labelMap labelName = label_id 57 | ram lx 1 58 | sub label_id lx 59 | ram lx prev 60 | copy label_id = lx 61 | ret 62 | 63 | push_pc_callstack: 64 | ram lx 1 65 | add pc lx 66 | ram lx prev 67 | copy pc = lx 68 | vec callstask push pc 69 | drop pc 70 | ret 71 | 72 | ret: 73 | ram pc :int = 0 74 | vec callstask len 75 | ram 1 76 | sub 77 | ram lx prev 78 | vec pc = callstask[lx] 79 | vec callstask pop 80 | copy lx = pc 81 | ram lx 82 | ram 1 83 | sub 84 | ram lx prev 85 | copy pc = lx 86 | ret -------------------------------------------------------------------------------- /src/funcs/stdf/stdin.rs: -------------------------------------------------------------------------------- 1 | use crate::funcs::errors::ErrorKind; 2 | use crate::types::{TypeName, Vars}; 3 | use crate::{memory::Memory, CPU}; 4 | use std::io::{self, Write}; 5 | 6 | pub fn stdin( 7 | memory: &mut Memory, 8 | vars: &mut Vars, 9 | registers: &mut CPU, 10 | cmd: Vec<&str>, 11 | statement: &str, 12 | ) -> Result<(), ErrorKind> { 13 | // stdin string = "input something: " 14 | // stdin lxstring = "kekw " 15 | // stdin var 16 | 17 | if cmd.len() < 2 { 18 | return Err(ErrorKind::ArgErr); 19 | } 20 | let mut message: &str = ""; 21 | if statement.contains('=') { 22 | let exp = statement.split('=').collect::>()[1].trim(); 23 | message = &exp[1..exp.len() - 1]; 24 | } 25 | print!("{}", message); 26 | io::stdout().flush().unwrap(); 27 | let mut buffer = String::new(); 28 | io::stdin() 29 | .read_line(&mut buffer) 30 | .expect("Error reading input"); 31 | match cmd[1] { 32 | "string" => registers.string = buffer, 33 | "lxstring" => registers.lxstring = buffer, 34 | _ => { 35 | let t = vars.get_type(cmd[1].to_string())?; 36 | if t.name == TypeName::String { 37 | let heap_addr = u32::from_be_bytes(memory.load(t.location).try_into().unwrap()); 38 | memory.heap_mod(heap_addr, buffer.as_bytes()); 39 | } else { 40 | return Err(ErrorKind::ExpectedStr(cmd[2].to_string())); 41 | } 42 | } 43 | } 44 | 45 | Ok(()) 46 | } 47 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # The Ram programming language 2 | A stack-based programming language developed to experiment with my language development skills. Runs on an emulated virtual machine, using custom memory, allocation, and garbage collection methods. 3 | 4 | ## How to run 5 | 1. Download the [release binary](https://github.com/ujjwal-kr/ram/releases/latest) [Only for windows and linux]. 6 | 2. Make it executable using `chmod +x ./ram` 7 | 3. Make a .ram file with the following contents in the same directory as the binary: 8 | 9 | ```as 10 | main: 11 | ram lx 12 | ram 1 13 | add 14 | ram lx prev 15 | print var lx 16 | ram lx 17 | ram 500 18 | cmp 19 | je halt: 20 | jmp main: 21 | 22 | halt: 23 | halt 24 | ``` 25 | 26 | 4. run `./ram ./example.ram` and press enter. 27 | 28 | # Documentation 29 | 30 | The language documentation is available in the [wiki](https://github.com/ujjwal-kr/ram/wiki/Dcoumentation-v3.1). You can read about the detailed work of the project in [my blog](https://crackhead-systems.vercel.app/tags/ram). 31 | 32 | ## How to test 33 | Run `cargo test` to run all the tests. This is the output of the test runner: 34 | 35 | ![tests](https://cdn.discordapp.com/attachments/875733830542196768/1032414620377428059/unknown.png) 36 | 37 | # Contribution 38 | 39 | Im not accepting any breaking changes to the specs, as the language syntax is still in development. But suggestions can be made using the issue tracker. All other types of contributions are welcome. Check the `dev` branch, PRs to the master branch won't be accepted. 40 | -------------------------------------------------------------------------------- /src/tests/stack/butterfly.rs: -------------------------------------------------------------------------------- 1 | use crate::funcs::butterfly; 2 | use crate::memory::Location; 3 | use crate::types::{ButterFly, Type}; 4 | use crate::{memory::Memory, types::Vars}; 5 | 6 | #[test] 7 | fn ram_map() { 8 | let mut memory: Memory = Memory::new(); 9 | let mut vars: Vars = Vars::new(); 10 | 11 | let statement: &str = "ram x :map"; 12 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 13 | butterfly::map(&mut memory, &mut vars, cmd, statement).unwrap(); 14 | let t: Type = Type { 15 | name: crate::types::TypeName::ButterFly(ButterFly::new()), 16 | location: Location { start: 0, size: 0 }, 17 | }; 18 | assert_eq!(vars.get_type("x".to_string()).unwrap(), t) 19 | } 20 | 21 | #[test] 22 | fn insert_and_get_map() { 23 | let mut memory: Memory = Memory::new(); 24 | let mut vars: Vars = Vars::new(); 25 | 26 | let statement: &str = "ram x :map"; 27 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 28 | butterfly::map(&mut memory, &mut vars, cmd, statement).unwrap(); 29 | let statement: &str = "insert x { \"hello\": \"world\" } "; 30 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 31 | butterfly::map(&mut memory, &mut vars, cmd, statement).unwrap(); 32 | 33 | vars.set_string("y".to_string(), "", &mut memory); 34 | let statement: &str = "get x \"hello\" = y"; 35 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 36 | butterfly::map(&mut memory, &mut vars, cmd, statement).unwrap(); 37 | let t = vars.get_type("y".to_string()).unwrap(); 38 | assert_eq!(memory.yeild_string(t.location), "world".to_string()); 39 | } -------------------------------------------------------------------------------- /src/funcs/errors.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | #[derive(Debug)] 4 | pub enum ErrorKind { 5 | ParseInt, 6 | ArgErr, 7 | StackLen, 8 | VarNotFound(String), 9 | Casting { src: String, dest: String }, 10 | ExpectedInt(String), 11 | ExpectedStr(String), 12 | ExpectedVec(String), 13 | RangeNegative, 14 | EmptyCallstack, 15 | LabelNotFound(String), 16 | VecLen(String), 17 | MapValueNotFound, 18 | ExpectedMap(String), 19 | ExpectedFloat 20 | } 21 | 22 | pub fn parse_int(value: &str) -> Result { 23 | let num: i32; 24 | match value.parse::() { 25 | Ok(n) => num = n, 26 | _parse_int_errorr => return Err(ErrorKind::ParseInt), 27 | } 28 | Ok(num) 29 | } 30 | 31 | pub fn get_label(pc: i32, map: HashMap) -> String { 32 | let mut value_point_vec: Vec = vec![]; 33 | let mut key_vec: Vec = vec![]; 34 | for (k, v) in map.clone().into_iter() { 35 | value_point_vec.push(v); 36 | key_vec.push(k); 37 | } 38 | value_point_vec.sort(); 39 | 40 | let mut final_label = String::from(""); 41 | let mut point_stack: Vec = vec![]; 42 | for point in value_point_vec { 43 | if pc >= point as i32 { 44 | point_stack.push(point) 45 | } 46 | } 47 | let final_point: isize = point_stack[point_stack.len() - 1]; 48 | for k in key_vec { 49 | match map.get(&k) { 50 | Some(&n) => { 51 | if n == final_point { 52 | final_label = k; 53 | break; 54 | } 55 | } 56 | None => panic!("nani?"), 57 | } 58 | } 59 | final_label 60 | } 61 | -------------------------------------------------------------------------------- /src/funcs/stdf/stdfs.rs: -------------------------------------------------------------------------------- 1 | use std::fs::File; 2 | use std::io::prelude::*; 3 | 4 | use crate::funcs::errors::ErrorKind; 5 | use crate::types::{TypeName, Vars}; 6 | use crate::{memory::Memory, CPU}; 7 | 8 | pub fn stdfs( 9 | memory: &mut Memory, 10 | vars: &mut Vars, 11 | registers: &mut CPU, 12 | cmd: Vec<&str>, 13 | ) -> Result<(), ErrorKind> { 14 | // PARSER CHANGE WHEN FS WRITE IS ADDED 15 | 16 | // stdfs open lxstring = string 17 | // stdfs open string = lxstring 18 | // stdfs open var_str = string/lxstring/var_str 19 | 20 | if cmd.len() < 5 { 21 | return Err(ErrorKind::ArgErr); 22 | } 23 | let filename: String; 24 | match cmd[2] { 25 | "string" => filename = registers.string.clone(), 26 | "lxstring" => filename = registers.lxstring.clone(), 27 | _ => { 28 | let t = vars.get_type(cmd[2].to_string())?; 29 | if t.name == TypeName::String { 30 | filename = memory.yeild_string(t.location); 31 | } else { 32 | return Err(ErrorKind::ExpectedStr(cmd[2].to_string())); 33 | } 34 | } 35 | } 36 | 37 | let mut file = File::open(filename.trim()).expect("Cannot open file"); 38 | let mut contents = String::new(); 39 | file.read_to_string(&mut contents) 40 | .expect("Error reading file to string"); 41 | 42 | match cmd[cmd.len() - 1] { 43 | "string" => registers.string = contents, 44 | "lxstring" => registers.lxstring = contents, 45 | _ => { 46 | let t = vars.get_type(cmd[cmd.len() - 1].to_string())?; 47 | if t.name == TypeName::String { 48 | let heap_addr = u32::from_be_bytes(memory.load(t.location).try_into().unwrap()); 49 | memory.heap_mod(heap_addr, contents.as_bytes()) 50 | } else { 51 | return Err(ErrorKind::ExpectedStr(cmd[cmd.len() - 1].to_string())); 52 | } 53 | } 54 | } 55 | 56 | Ok(()) 57 | } 58 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "lldb", 9 | "request": "launch", 10 | "name": "Debug unit tests in library 'ram'", 11 | "cargo": { 12 | "args": [ 13 | "test", 14 | "--no-run", 15 | "--lib", 16 | "--package=ram" 17 | ], 18 | "filter": { 19 | "name": "ram", 20 | "kind": "lib" 21 | } 22 | }, 23 | "args": [], 24 | "cwd": "${workspaceFolder}" 25 | }, 26 | { 27 | "type": "lldb", 28 | "request": "launch", 29 | "name": "Debug executable 'ram'", 30 | "cargo": { 31 | "args": [ 32 | "build", 33 | "--bin=ram", 34 | "--package=ram" 35 | ], 36 | "filter": { 37 | "name": "ram", 38 | "kind": "bin" 39 | } 40 | }, 41 | "args": [], 42 | "cwd": "${workspaceFolder}" 43 | }, 44 | { 45 | "type": "lldb", 46 | "request": "launch", 47 | "name": "Debug unit tests in executable 'ram'", 48 | "cargo": { 49 | "args": [ 50 | "test", 51 | "--no-run", 52 | "--bin=ram", 53 | "--package=ram" 54 | ], 55 | "filter": { 56 | "name": "ram", 57 | "kind": "bin" 58 | } 59 | }, 60 | "args": [], 61 | "cwd": "${workspaceFolder}" 62 | } 63 | ] 64 | } -------------------------------------------------------------------------------- /src/funcs/print.rs: -------------------------------------------------------------------------------- 1 | use crate::memory::Memory; 2 | use crate::types::{Type, TypeName, Vars, Vector}; 3 | use crate::CPU; 4 | 5 | use super::errors::ErrorKind; 6 | 7 | pub fn print( 8 | memory: &mut Memory, 9 | vars: &mut Vars, 10 | registers: &mut CPU, 11 | cmd: Vec<&str>, 12 | ) -> Result<(), ErrorKind> { 13 | // print var { lx/rv/string/lxstring/var-name } 14 | // print hello world 15 | if cmd.len() == 1 { 16 | println!("{}", memory.get_int_from_stack()?); 17 | Ok(()) 18 | } else if cmd[1] == "var" { 19 | match cmd[2] { 20 | "lx" => println!("{}", registers.lx), 21 | "rv" => println!("{}", registers.rv), 22 | "string" => println!("{}", registers.string), 23 | "lxstring" => println!("{}", registers.lxstring), 24 | _ => { 25 | if cmd.len() == 3 { 26 | let _type: Type = vars.get_type(cmd[2].to_string())?; 27 | match _type.name { 28 | TypeName::I32 => println!("{}", memory.yeild_i32(_type.location)), 29 | TypeName::String => println!("{}", memory.yeild_string(_type.location)), 30 | TypeName::Vector(Vector::String) => { 31 | println!("{:?}", memory.yeild_str_vec(_type.location)) 32 | } 33 | TypeName::Vector(Vector::Int) => { 34 | println!("{:?}", memory.yeild_int_vec(_type.location)) 35 | } 36 | TypeName::Float => println!("{:?}", memory.yeild_float(_type.location)), 37 | _ => unimplemented!(), 38 | } 39 | } else { 40 | let print_st = &cmd[1..cmd.len()].to_vec().join(" "); 41 | println!("{print_st}"); 42 | } 43 | } 44 | } 45 | Ok(()) 46 | } else { 47 | let print_st = &cmd[1..cmd.len()].to_vec().join(" "); 48 | println!("{print_st}"); 49 | Ok(()) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "naersk": { 4 | "inputs": { 5 | "nixpkgs": "nixpkgs" 6 | }, 7 | "locked": { 8 | "lastModified": 1743800763, 9 | "narHash": "sha256-YFKV+fxEpMgP5VsUcM6Il28lI0NlpM7+oB1XxbBAYCw=", 10 | "owner": "nix-community", 11 | "repo": "naersk", 12 | "rev": "ed0232117731a4c19d3ee93aa0c382a8fe754b01", 13 | "type": "github" 14 | }, 15 | "original": { 16 | "owner": "nix-community", 17 | "ref": "master", 18 | "repo": "naersk", 19 | "type": "github" 20 | } 21 | }, 22 | "nixpkgs": { 23 | "locked": { 24 | "lastModified": 1745377448, 25 | "narHash": "sha256-jhZDfXVKdD7TSEGgzFJQvEEZ2K65UMiqW5YJ2aIqxMA=", 26 | "owner": "NixOS", 27 | "repo": "nixpkgs", 28 | "rev": "507b63021ada5fee621b6ca371c4fca9ca46f52c", 29 | "type": "github" 30 | }, 31 | "original": { 32 | "owner": "NixOS", 33 | "ref": "nixpkgs-unstable", 34 | "repo": "nixpkgs", 35 | "type": "github" 36 | } 37 | }, 38 | "nixpkgs_2": { 39 | "locked": { 40 | "lastModified": 1745377448, 41 | "narHash": "sha256-jhZDfXVKdD7TSEGgzFJQvEEZ2K65UMiqW5YJ2aIqxMA=", 42 | "owner": "NixOS", 43 | "repo": "nixpkgs", 44 | "rev": "507b63021ada5fee621b6ca371c4fca9ca46f52c", 45 | "type": "github" 46 | }, 47 | "original": { 48 | "owner": "NixOS", 49 | "ref": "nixpkgs-unstable", 50 | "repo": "nixpkgs", 51 | "type": "github" 52 | } 53 | }, 54 | "root": { 55 | "inputs": { 56 | "naersk": "naersk", 57 | "nixpkgs": "nixpkgs_2", 58 | "utils": "utils" 59 | } 60 | }, 61 | "systems": { 62 | "locked": { 63 | "lastModified": 1681028828, 64 | "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", 65 | "owner": "nix-systems", 66 | "repo": "default", 67 | "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", 68 | "type": "github" 69 | }, 70 | "original": { 71 | "owner": "nix-systems", 72 | "repo": "default", 73 | "type": "github" 74 | } 75 | }, 76 | "utils": { 77 | "inputs": { 78 | "systems": "systems" 79 | }, 80 | "locked": { 81 | "lastModified": 1731533236, 82 | "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", 83 | "owner": "numtide", 84 | "repo": "flake-utils", 85 | "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", 86 | "type": "github" 87 | }, 88 | "original": { 89 | "owner": "numtide", 90 | "repo": "flake-utils", 91 | "type": "github" 92 | } 93 | } 94 | }, 95 | "root": "root", 96 | "version": 7 97 | } 98 | -------------------------------------------------------------------------------- /src/funcs/butterfly.rs: -------------------------------------------------------------------------------- 1 | use super::errors::ErrorKind; 2 | use crate::{ 3 | memory::Memory, 4 | types::{Type, TypeName, Vars}, 5 | }; 6 | 7 | pub fn map( 8 | memory: &mut Memory, 9 | vars: &mut Vars, 10 | cmd: Vec<&str>, 11 | statement: &str, 12 | ) -> Result<(), ErrorKind> { 13 | if cmd.len() < 3 { 14 | return Err(ErrorKind::ArgErr); 15 | } 16 | match cmd[0] { 17 | "ram" => vars.add_map(cmd[1].to_string()), 18 | "get" => { 19 | let t: Type = vars.get_from_map(cmd[1].to_string(), cmd[2].to_string(), memory)?; 20 | let mut assign_var = vars.get_type(cmd[4].to_string())?; 21 | match t.name { 22 | TypeName::String => { 23 | if assign_var.name != TypeName::String { 24 | return Err(ErrorKind::ExpectedStr(cmd[4].to_string())); 25 | } 26 | let old_str_addr = memory.load(assign_var.location).to_owned(); 27 | let t_addr = memory.load(t.location).to_owned(); 28 | memory.stack_mod(assign_var.location, &t_addr); 29 | memory.free(u32::from_be_bytes(old_str_addr.try_into().unwrap())); 30 | } 31 | TypeName::I32 => { 32 | if assign_var.name != TypeName::I32 { 33 | return Err(ErrorKind::ExpectedInt(cmd[4].to_string())); 34 | } 35 | let t_data = memory.load(t.location).to_owned(); 36 | memory.stack_mod(assign_var.location, &t_data); 37 | } 38 | TypeName::ButterFly(t_butterfly) => match &mut assign_var.name { 39 | TypeName::ButterFly(b) => { 40 | *b = t_butterfly; 41 | vars.replace_map(cmd[4].to_string(), assign_var)? 42 | } 43 | _ => return Err(ErrorKind::ExpectedMap(cmd[1].to_string())), 44 | }, 45 | _ => unimplemented!(), 46 | } 47 | } 48 | "insert" => { 49 | let kv = Kv::new(statement)?; 50 | vars.insert_to_map(cmd[1].to_string(), kv.key, kv.value, memory)? 51 | } 52 | "delete" => vars.remove_from_map(cmd[1].to_string(), cmd[2].to_string(), memory)?, 53 | _ => return Err(ErrorKind::ArgErr), 54 | } 55 | Ok(()) 56 | } 57 | 58 | struct Kv { 59 | key: String, 60 | value: String, 61 | } 62 | 63 | impl Kv { 64 | pub fn new(statement: &str) -> Result { 65 | let key = statement.split(':').collect::>()[0] 66 | .split('{') 67 | .collect::>()[1] 68 | .trim(); 69 | 70 | let value = statement.split(':').collect::>()[1] 71 | .split('}') 72 | .collect::>()[0] 73 | .trim(); 74 | 75 | if value.len() < 1 || key.len() < 1 { 76 | return Err(ErrorKind::ArgErr); 77 | } 78 | 79 | Ok(Self { 80 | key: key.to_string(), 81 | value: value.to_string(), 82 | }) 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/parser.rs: -------------------------------------------------------------------------------- 1 | use regex::Regex; 2 | use std::collections::HashMap; 3 | use std::io::prelude::*; 4 | use std::{fs, path::Path, process}; 5 | 6 | #[derive(Debug)] 7 | pub struct LabelMap { 8 | pub map: HashMap, 9 | pub instructions: Vec, 10 | } 11 | 12 | pub fn parse_lines(p_lines: Vec<&str>) -> LabelMap { 13 | let mut _final_lines: Vec<&str> = vec![]; 14 | _final_lines = p_lines.clone(); 15 | 16 | let mut final_contents = String::new(); 17 | 18 | let imports = has_includes(p_lines); 19 | 20 | // check if the files exist 21 | for path in imports { 22 | if !Path::new(path).exists() { 23 | println!("File '{}' not found", path); 24 | process::exit(1); 25 | } 26 | 27 | // read the file 28 | 29 | let mut file = fs::File::open(path).unwrap_or_else(|_| { 30 | panic!("{}", format!("Error opening '{}'", path).trim().to_string()) 31 | }); 32 | let mut contents = String::new(); 33 | 34 | file.read_to_string(&mut contents).unwrap_or_else(|_| { 35 | panic!("{}", format!("Error reading '{}'", path).trim().to_string()) 36 | }); 37 | 38 | final_contents += &contents; 39 | final_contents += "\n"; 40 | } 41 | 42 | let mut final_import_vec: Vec<&str> = final_contents.split('\n').collect(); 43 | _final_lines.append(&mut final_import_vec); 44 | let program: LabelMap = populate_labels(_final_lines); 45 | program 46 | } 47 | 48 | // takes in all the lines and send imports of a file 49 | pub fn has_includes(p_lines: Vec<&str>) -> Vec<&str> { 50 | let mut has_included: Vec<&str> = vec![]; 51 | for mut line in p_lines { 52 | line = line.trim(); 53 | if !line.is_empty() { 54 | let cmd = line.split_whitespace().collect::>(); 55 | if cmd[0] == "include" { 56 | let includes = &cmd[1].split('\"').collect::>()[1]; 57 | has_included.push(includes); 58 | } 59 | } 60 | } 61 | 62 | has_included 63 | } 64 | 65 | pub fn populate_labels(p_lines: Vec<&str>) -> LabelMap { 66 | let mut map: HashMap = HashMap::new(); 67 | let mut instructions: Vec = vec![]; 68 | let exp = Regex::new(r"^[a-zA-Z0-9_]+:$").unwrap(); 69 | let mut i = 0u32; 70 | 71 | for mut line in p_lines { 72 | let mut incr: bool = true; 73 | line = line.trim(); 74 | if !line.is_empty() && line.split_whitespace().collect::>()[0] == "include" { 75 | incr = false; 76 | line = ""; 77 | } else if line.len() > 1 && &line[..2] == "//" { 78 | incr = false; 79 | line = ""; 80 | } 81 | if exp.is_match(line) { 82 | if i == 0 && line != "main:" { 83 | panic!("No main label at the beginning of the file."); 84 | } 85 | map.insert(line.to_string(), i as isize); 86 | } else if !line.is_empty() && incr { 87 | i += 1; 88 | instructions.push(line.to_string()) 89 | } 90 | } 91 | 92 | LabelMap { map, instructions } 93 | } 94 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "aho-corasick" 7 | version = "0.7.18" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" 10 | dependencies = [ 11 | "memchr", 12 | ] 13 | 14 | [[package]] 15 | name = "cfg-if" 16 | version = "1.0.0" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 19 | 20 | [[package]] 21 | name = "getrandom" 22 | version = "0.2.8" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" 25 | dependencies = [ 26 | "cfg-if", 27 | "libc", 28 | "wasi", 29 | ] 30 | 31 | [[package]] 32 | name = "libc" 33 | version = "0.2.137" 34 | source = "registry+https://github.com/rust-lang/crates.io-index" 35 | checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" 36 | 37 | [[package]] 38 | name = "memchr" 39 | version = "2.5.0" 40 | source = "registry+https://github.com/rust-lang/crates.io-index" 41 | checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" 42 | 43 | [[package]] 44 | name = "ppv-lite86" 45 | version = "0.2.17" 46 | source = "registry+https://github.com/rust-lang/crates.io-index" 47 | checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" 48 | 49 | [[package]] 50 | name = "ram" 51 | version = "0.1.0" 52 | dependencies = [ 53 | "rand", 54 | "regex", 55 | ] 56 | 57 | [[package]] 58 | name = "rand" 59 | version = "0.8.5" 60 | source = "registry+https://github.com/rust-lang/crates.io-index" 61 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 62 | dependencies = [ 63 | "libc", 64 | "rand_chacha", 65 | "rand_core", 66 | ] 67 | 68 | [[package]] 69 | name = "rand_chacha" 70 | version = "0.3.1" 71 | source = "registry+https://github.com/rust-lang/crates.io-index" 72 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 73 | dependencies = [ 74 | "ppv-lite86", 75 | "rand_core", 76 | ] 77 | 78 | [[package]] 79 | name = "rand_core" 80 | version = "0.6.4" 81 | source = "registry+https://github.com/rust-lang/crates.io-index" 82 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 83 | dependencies = [ 84 | "getrandom", 85 | ] 86 | 87 | [[package]] 88 | name = "regex" 89 | version = "1.5.6" 90 | source = "registry+https://github.com/rust-lang/crates.io-index" 91 | checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1" 92 | dependencies = [ 93 | "aho-corasick", 94 | "memchr", 95 | "regex-syntax", 96 | ] 97 | 98 | [[package]] 99 | name = "regex-syntax" 100 | version = "0.6.26" 101 | source = "registry+https://github.com/rust-lang/crates.io-index" 102 | checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64" 103 | 104 | [[package]] 105 | name = "wasi" 106 | version = "0.11.0+wasi-snapshot-preview1" 107 | source = "registry+https://github.com/rust-lang/crates.io-index" 108 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 109 | -------------------------------------------------------------------------------- /src/tests/std/parse.rs: -------------------------------------------------------------------------------- 1 | use crate::funcs::stdf::parse::*; 2 | use crate::{memory::Memory, types::Vars, CPU}; 3 | 4 | // parse lx :str 5 | // parse rv :str 6 | 7 | // parse string :int 8 | // parse lxstring :int 9 | 10 | // parse var :int 11 | // parse var :str 12 | 13 | #[test] 14 | fn parse_lx() { 15 | let mut memory: Memory = Memory::new(); 16 | let mut registers: CPU = CPU::new(); 17 | let mut vars: Vars = Vars::new(); 18 | 19 | registers.lx = 5; 20 | let statement: &str = "parse lx :str"; 21 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 22 | 23 | parse(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 24 | assert_eq!(registers.string, "5".to_string()) 25 | } 26 | 27 | #[test] 28 | fn parse_rv() { 29 | let mut memory: Memory = Memory::new(); 30 | let mut registers: CPU = CPU::new(); 31 | let mut vars: Vars = Vars::new(); 32 | 33 | registers.rv = 5; 34 | let statement: &str = "parse rv :str"; 35 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 36 | 37 | parse(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 38 | assert_eq!(registers.string, "5".to_string()) 39 | } 40 | 41 | #[test] 42 | fn parse_string() { 43 | let mut memory: Memory = Memory::new(); 44 | let mut registers: CPU = CPU::new(); 45 | let mut vars: Vars = Vars::new(); 46 | 47 | registers.string = "10".to_string(); 48 | let statement: &str = "parse string :int"; 49 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 50 | 51 | parse(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 52 | assert_eq!(registers.lx, 10) 53 | } 54 | 55 | #[test] 56 | fn parse_lxstring() { 57 | let mut memory: Memory = Memory::new(); 58 | let mut registers: CPU = CPU::new(); 59 | let mut vars: Vars = Vars::new(); 60 | 61 | registers.lxstring = "10".to_string(); 62 | let statement: &str = "parse lxstring :int"; 63 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 64 | 65 | parse(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 66 | assert_eq!(registers.lx, 10) 67 | } 68 | 69 | #[test] 70 | fn parse_var_int() { 71 | let mut memory: Memory = Memory::new(); 72 | let mut registers: CPU = CPU::new(); 73 | let mut vars: Vars = Vars::new(); 74 | 75 | vars.set_string("x".to_string(), "10", &mut memory); 76 | let statement: &str = "parse x :int"; 77 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 78 | 79 | parse(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 80 | assert_eq!(registers.lx, 10) 81 | } 82 | 83 | #[test] 84 | #[should_panic] 85 | fn parse_int_err() { 86 | let mut memory: Memory = Memory::new(); 87 | let mut registers: CPU = CPU::new(); 88 | let mut vars: Vars = Vars::new(); 89 | 90 | vars.set_string("x".to_string(), "ww", &mut memory); 91 | let statement: &str = "parse x :int"; 92 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 93 | 94 | parse(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 95 | } 96 | 97 | #[test] 98 | fn parse_var_str() { 99 | let mut memory: Memory = Memory::new(); 100 | let mut registers: CPU = CPU::new(); 101 | let mut vars: Vars = Vars::new(); 102 | 103 | vars.set_int("x".to_string(), "10", &mut memory).unwrap(); 104 | let statement: &str = "parse x :str"; 105 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 106 | 107 | parse(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 108 | assert_eq!(registers.string, "10".to_string()) 109 | } 110 | -------------------------------------------------------------------------------- /src/funcs/jump.rs: -------------------------------------------------------------------------------- 1 | use crate::memory::Memory; 2 | use crate::CPU; 3 | 4 | use super::errors::ErrorKind; 5 | use std::collections::HashMap; 6 | 7 | fn get_dest_counter(lmap: HashMap, label: &str) -> Result { 8 | match lmap.get(label) { 9 | Some(&c) => Ok(c), 10 | _ => Err(ErrorKind::LabelNotFound(label.to_string())), 11 | } 12 | } 13 | 14 | pub fn jmp( 15 | cpu: &mut CPU, 16 | cmd: Vec<&str>, 17 | label_map: HashMap, 18 | ) -> Result<(), ErrorKind> { 19 | if cmd.len() != 2 { 20 | return Err(ErrorKind::ArgErr); 21 | } 22 | let label = cmd[1].trim(); 23 | let dest_counter = get_dest_counter(label_map, label)?; 24 | cpu.callstack.push(cpu.program_counter + 1); 25 | cpu.program_counter = dest_counter as i32 - 1; 26 | Ok(()) 27 | } 28 | 29 | pub fn je( 30 | cpu: &mut CPU, 31 | cmd: Vec<&str>, 32 | label_map: HashMap, 33 | memory: &mut Memory, 34 | ) -> Result<(), ErrorKind> { 35 | if cmd.len() != 2 { 36 | return Err(ErrorKind::ArgErr); 37 | } 38 | if memory.get_int_from_stack()? == 0 { 39 | let label = cmd[1].trim(); 40 | let dest_counter = get_dest_counter(label_map, label)?; 41 | cpu.callstack.push(cpu.program_counter + 1); 42 | cpu.program_counter = dest_counter as i32 - 1; 43 | } 44 | let sub = memory.stack.len().saturating_sub(4); 45 | memory.stack.truncate(sub); 46 | Ok(()) 47 | } 48 | 49 | pub fn jne( 50 | cpu: &mut CPU, 51 | cmd: Vec<&str>, 52 | label_map: HashMap, 53 | memory: &mut Memory, 54 | ) -> Result<(), ErrorKind> { 55 | if cmd.len() != 2 { 56 | return Err(ErrorKind::ArgErr); 57 | } 58 | if memory.get_int_from_stack()? != 0 { 59 | let label = cmd[1].trim(); 60 | let dest_counter = get_dest_counter(label_map, label)?; 61 | cpu.callstack.push(cpu.program_counter + 1); 62 | cpu.program_counter = dest_counter as i32 - 1; 63 | } 64 | let sub = memory.stack.len().saturating_sub(4); 65 | memory.stack.truncate(sub); 66 | Ok(()) 67 | } 68 | 69 | pub fn jgr( 70 | cpu: &mut CPU, 71 | cmd: Vec<&str>, 72 | label_map: HashMap, 73 | memory: &mut Memory, 74 | ) -> Result<(), ErrorKind> { 75 | if cmd.len() != 2 { 76 | return Err(ErrorKind::ArgErr); 77 | } 78 | if memory.get_int_from_stack()? == 1 { 79 | let label = cmd[1].trim(); 80 | let dest_counter = get_dest_counter(label_map, label)?; 81 | cpu.callstack.push(cpu.program_counter + 1); 82 | cpu.program_counter = dest_counter as i32 - 1; 83 | } 84 | let sub = memory.stack.len().saturating_sub(4); 85 | memory.stack.truncate(sub); 86 | Ok(()) 87 | } 88 | 89 | pub fn jsm( 90 | cpu: &mut CPU, 91 | cmd: Vec<&str>, 92 | label_map: HashMap, 93 | memory: &mut Memory, 94 | ) -> Result<(), ErrorKind> { 95 | if cmd.len() != 2 { 96 | return Err(ErrorKind::ArgErr); 97 | } 98 | if memory.get_int_from_stack()? == -1 { 99 | let label = cmd[1].trim(); 100 | let dest_counter = get_dest_counter(label_map, label)?; 101 | cpu.callstack.push(cpu.program_counter + 1); 102 | cpu.program_counter = dest_counter as i32 - 1; 103 | } 104 | let sub = memory.stack.len().saturating_sub(4); 105 | memory.stack.truncate(sub); 106 | Ok(()) 107 | } 108 | 109 | pub fn ret(cpu: &mut CPU) -> Result<(), ErrorKind> { 110 | if cpu.callstack.is_empty() { 111 | return Err(ErrorKind::EmptyCallstack); 112 | } 113 | cpu.program_counter = cpu.callstack[cpu.callstack.len() - 1] - 1; 114 | cpu.callstack.pop(); 115 | Ok(()) 116 | } 117 | -------------------------------------------------------------------------------- /examples/interpreter/interpreter.ram: -------------------------------------------------------------------------------- 1 | include "examples/interpreter/parser.ram" 2 | include "examples/interpreter/var.ram" 3 | include "examples/interpreter/jump.ram" 4 | 5 | main: 6 | ram labelMap :map 7 | ram stack :vec :int = [] 8 | ram callstask :vec :int = [] 9 | ram vars_int :map 10 | ram vars_str :map 11 | ram i :int = 0 12 | ram parser_ip :int = 0 13 | ram pc :int = 0 14 | ram lxstring = "./examples/interpreter/test.txt" 15 | stdfs open lxstring = string 16 | ram program :vec :str = [] 17 | ram plen :int = 0 18 | split string > "\n" = program 19 | vec program len 20 | ram lx prev 21 | copy plen = lx 22 | ram instructions :vec :str = [] 23 | jmp parser_loop: 24 | jmp program_loop: 25 | halt 26 | 27 | program_loop: 28 | ram statement :str = "" 29 | vec statement = instructions[pc] 30 | jmp match: 31 | 32 | ram lx 1 33 | add lx pc 34 | ram lx prev 35 | copy pc = lx 36 | 37 | cmp pc parser_ip 38 | jne program_loop: 39 | ret 40 | 41 | match: 42 | ram matchstr :str = "" 43 | ram cmd :vec :str = [] 44 | split statement > " " = cmd 45 | vec matchstr = cmd[0] 46 | trim matchstr 47 | 48 | ram string = "push" 49 | cmp string matchstr 50 | je push: 51 | 52 | ram string = "print" 53 | cmp string matchstr 54 | je print: 55 | 56 | ram string = "println" 57 | cmp string matchstr 58 | je println: 59 | 60 | ram string = "add" 61 | cmp string matchstr 62 | je add: 63 | 64 | ram string = "sub" 65 | cmp string matchstr 66 | je sub: 67 | 68 | ram string = "mul" 69 | cmp string matchstr 70 | je mul: 71 | 72 | ram string = "div" 73 | cmp string matchstr 74 | je div: 75 | 76 | ram string = "pop" 77 | cmp string matchstr 78 | je pop: 79 | 80 | ram string = "halt" 81 | cmp string matchstr 82 | je halt: 83 | 84 | ram string = "var" 85 | cmp string matchstr 86 | je var: 87 | 88 | ram string = "cmp" 89 | cmp string matchstr 90 | je cmp: 91 | 92 | ram string = "jmp" 93 | cmp string matchstr 94 | je jmp: 95 | 96 | ram string = "je" 97 | cmp string matchstr 98 | je je: 99 | 100 | ram string = "jne" 101 | cmp string matchstr 102 | je jne: 103 | 104 | ram string = "jgr" 105 | cmp string matchstr 106 | je jgr: 107 | 108 | ram string = "jsm" 109 | cmp string matchstr 110 | je jsm: 111 | 112 | ram string = "ret" 113 | cmp string matchstr 114 | je ret: 115 | 116 | ret 117 | 118 | push: 119 | vec cmd len 120 | ram 2 121 | cmp 122 | jgr push_var: 123 | vec cmd len 124 | ram 2 125 | cmp 126 | je push_int: 127 | ret 128 | 129 | push_var: 130 | ram v_name :str = "" 131 | vec v_name = cmd[2] 132 | ram v_value :int = 0 133 | get vars_int v_name = v_value 134 | copy lx = v_value 135 | vec stack push lx 136 | drop v_name 137 | drop v_value 138 | ret 139 | 140 | push_int: 141 | ram numstr :str = "" 142 | vec numstr = cmd[1] 143 | parse numstr :int 144 | vec stack push lx 145 | drop numstr 146 | ret 147 | 148 | pop: 149 | vec stack pop 150 | ret 151 | 152 | print: 153 | vec stack len 154 | ram 1 155 | sub 156 | ram lx prev 157 | ram num :int = 0 158 | vec num = stack[lx] 159 | print var num 160 | vec stack pop 161 | drop num 162 | ret 163 | 164 | println: 165 | vec cmd shift 166 | join cmd > " " = string 167 | print var string 168 | ret 169 | 170 | get_last_two: 171 | ram n1 :int = 0 172 | ram n2 :int = 0 173 | vec stack len 174 | ram 1 175 | sub 176 | ram lx prev 177 | vec n1 = stack[lx] 178 | vec stack len 179 | ram 2 180 | sub 181 | ram lx prev 182 | vec n2 = stack[lx] 183 | vec stack pop 184 | vec stack pop 185 | ret 186 | 187 | add: 188 | jmp get_last_two: 189 | add n1 n2 190 | ram lx prev 191 | vec stack push lx 192 | drop n1 193 | drop n2 194 | ret 195 | 196 | sub: 197 | jmp get_last_two: 198 | sub n2 n1 199 | ram lx prev 200 | vec stack push lx 201 | drop n1 202 | drop n2 203 | ret 204 | 205 | halt: 206 | halt 207 | 208 | cmp: 209 | jmp get_last_two: 210 | 211 | cmp n2 n1 212 | jgr cmp_gr: 213 | 214 | cmp n2 n1 215 | je cmp_je: 216 | 217 | cmp n2 n1 218 | jsm cmp_sm: 219 | drop n1 220 | drop n2 221 | ret 222 | 223 | cmp_gr: 224 | ram lx 1 225 | vec stack push lx 226 | ret 227 | 228 | cmp_je: 229 | ram lx 0 230 | vec stack push lx 231 | ret 232 | 233 | cmp_sm: 234 | ram lx -1 235 | vec stack push lx 236 | ret -------------------------------------------------------------------------------- /src/funcs/operations/mul.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | funcs::errors::ErrorKind, 3 | memory::Memory, 4 | types::{Type, TypeName, Vars}, 5 | CPU, 6 | }; 7 | 8 | pub fn mul( 9 | memory: &mut Memory, 10 | vars: &mut Vars, 11 | registers: &mut CPU, 12 | cmd: Vec<&str>, 13 | ) -> Result<(), ErrorKind> { 14 | if cmd.len() == 1 { 15 | let n1: i32 = memory.get_int_from_stack()?; 16 | let sub = memory.stack.len().saturating_sub(4); 17 | memory.stack.truncate(sub); 18 | 19 | let n2: i32 = memory.get_int_from_stack()?; 20 | let sub = memory.stack.len().saturating_sub(4); 21 | memory.stack.truncate(sub); 22 | memory.set_int_to_stack(n1 * n2); 23 | Ok(()) 24 | } else { 25 | match cmd[1] { 26 | "lx" => { 27 | if cmd.len() == 2 { 28 | let n: i32 = memory.get_int_from_stack()?; 29 | let sub = memory.stack.len().saturating_sub(4); 30 | memory.stack.truncate(sub); 31 | memory.set_int_to_stack(registers.lx * n); 32 | Ok(()) 33 | } else { 34 | match cmd[2] { 35 | "rv" => memory.set_int_to_stack(registers.lx * registers.rv), 36 | "lx" => memory.set_int_to_stack(registers.lx * registers.lx), 37 | _ => { 38 | let n: i32; 39 | let t: Type = vars.get_type(cmd[2].to_string())?; 40 | match t.name { 41 | TypeName::I32 => n = memory.yeild_i32(t.location), 42 | _ => return Err(ErrorKind::ExpectedInt(cmd[2].to_string())), 43 | } 44 | memory.set_int_to_stack(registers.lx * n) 45 | } 46 | } 47 | Ok(()) 48 | } 49 | } 50 | "rv" => { 51 | if cmd.len() == 2 { 52 | let n: i32 = memory.get_int_from_stack()?; 53 | let sub = memory.stack.len().saturating_sub(4); 54 | memory.stack.truncate(sub); 55 | memory.set_int_to_stack(registers.rv * n); 56 | Ok(()) 57 | } else { 58 | match cmd[2] { 59 | "rv" => memory.set_int_to_stack(registers.rv * registers.rv), 60 | "lx" => memory.set_int_to_stack(registers.rv * registers.lx), 61 | _ => { 62 | let n: i32; 63 | let t: Type = vars.get_type(cmd[2].to_string())?; 64 | match t.name { 65 | TypeName::I32 => n = memory.yeild_i32(t.location), 66 | _ => return Err(ErrorKind::ExpectedInt(cmd[2].to_string())), 67 | } 68 | memory.set_int_to_stack(registers.rv * n) 69 | } 70 | } 71 | Ok(()) 72 | } 73 | } 74 | _ => { 75 | if cmd.len() == 2 { 76 | let var: i32; 77 | let t: Type = vars.get_type(cmd[1].to_string())?; 78 | match t.name { 79 | TypeName::I32 => var = memory.yeild_i32(t.location), 80 | _ => return Err(ErrorKind::ExpectedInt(cmd[2].to_string())), 81 | } 82 | let n: i32 = memory.get_int_from_stack()?; 83 | let sub = memory.stack.len().saturating_sub(4); 84 | memory.stack.truncate(sub); 85 | memory.set_int_to_stack(var * n); 86 | Ok(()) 87 | } else if cmd.len() == 3 { 88 | let var: i32; 89 | let t: Type = vars.get_type(cmd[1].to_string())?; 90 | match t.name { 91 | TypeName::I32 => var = memory.yeild_i32(t.location), 92 | _ => return Err(ErrorKind::ExpectedInt(cmd[2].to_string())), 93 | } 94 | match cmd[2] { 95 | "lx" => memory.set_int_to_stack(registers.lx * var), 96 | "rv" => memory.set_int_to_stack(registers.rv * var), 97 | _ => { 98 | let var2: i32; 99 | let t2: Type = vars.get_type(cmd[2].to_string())?; 100 | match t2.name { 101 | TypeName::I32 => var2 = memory.yeild_i32(t2.location), 102 | _ => return Err(ErrorKind::ExpectedInt(cmd[2].to_string())), 103 | } 104 | memory.set_int_to_stack(var * var2) 105 | } 106 | } 107 | Ok(()) 108 | } else { 109 | Ok(()) 110 | } 111 | } 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/funcs/operations/sub.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | funcs::errors::ErrorKind, 3 | memory::Memory, 4 | types::{Type, TypeName, Vars}, 5 | CPU, 6 | }; 7 | 8 | pub fn sub( 9 | memory: &mut Memory, 10 | vars: &mut Vars, 11 | registers: &mut CPU, 12 | cmd: Vec<&str>, 13 | ) -> Result<(), ErrorKind> { 14 | if cmd.len() == 1 { 15 | let n1: i32 = memory.get_int_from_stack()?; 16 | let sub = memory.stack.len().saturating_sub(4); 17 | memory.stack.truncate(sub); 18 | 19 | let n2: i32 = memory.get_int_from_stack()?; 20 | let sub = memory.stack.len().saturating_sub(4); 21 | memory.stack.truncate(sub); 22 | memory.set_int_to_stack(n2 - n1); 23 | Ok(()) 24 | } else { 25 | match cmd[1] { 26 | "lx" => { 27 | if cmd.len() == 2 { 28 | let n: i32 = memory.get_int_from_stack()?; 29 | let sub = memory.stack.len().saturating_sub(4); 30 | memory.stack.truncate(sub); 31 | memory.set_int_to_stack(n - registers.lx); 32 | Ok(()) 33 | } else { 34 | match cmd[2] { 35 | "rv" => memory.set_int_to_stack(registers.lx - registers.rv), 36 | "lx" => memory.set_int_to_stack(registers.lx - registers.lx), 37 | _ => { 38 | let n: i32; 39 | let t: Type = vars.get_type(cmd[2].to_string())?; 40 | match t.name { 41 | TypeName::I32 => n = memory.yeild_i32(t.location), 42 | _ => return Err(ErrorKind::ExpectedInt(cmd[2].to_string())), 43 | } 44 | memory.set_int_to_stack(registers.lx - n) 45 | } 46 | } 47 | Ok(()) 48 | } 49 | } 50 | "rv" => { 51 | if cmd.len() == 2 { 52 | let n: i32 = memory.get_int_from_stack()?; 53 | let sub = memory.stack.len().saturating_sub(4); 54 | memory.stack.truncate(sub); 55 | memory.set_int_to_stack(n - registers.rv); 56 | Ok(()) 57 | } else { 58 | match cmd[2] { 59 | "rv" => memory.set_int_to_stack(registers.rv - registers.rv), 60 | "lx" => memory.set_int_to_stack(registers.rv - registers.lx), 61 | _ => { 62 | let n: i32; 63 | let t: Type = vars.get_type(cmd[2].to_string())?; 64 | match t.name { 65 | TypeName::I32 => n = memory.yeild_i32(t.location), 66 | _ => return Err(ErrorKind::ExpectedInt(cmd[2].to_string())), 67 | } 68 | memory.set_int_to_stack(registers.rv - n) 69 | } 70 | } 71 | Ok(()) 72 | } 73 | } 74 | _ => { 75 | if cmd.len() == 2 { 76 | let var: i32; 77 | let t: Type = vars.get_type(cmd[1].to_string())?; 78 | match t.name { 79 | TypeName::I32 => var = memory.yeild_i32(t.location), 80 | _ => return Err(ErrorKind::ExpectedInt(cmd[2].to_string())), 81 | } 82 | let n: i32 = memory.get_int_from_stack()?; 83 | let sub = memory.stack.len().saturating_sub(4); 84 | memory.stack.truncate(sub); 85 | memory.set_int_to_stack(var - n); 86 | Ok(()) 87 | } else if cmd.len() == 3 { 88 | let var: i32; 89 | let t: Type = vars.get_type(cmd[1].to_string())?; 90 | match t.name { 91 | TypeName::I32 => var = memory.yeild_i32(t.location), 92 | _ => return Err(ErrorKind::ExpectedInt(cmd[2].to_string())), 93 | } 94 | match cmd[2] { 95 | "lx" => memory.set_int_to_stack(var - registers.lx), 96 | "rv" => memory.set_int_to_stack(var - registers.rv), 97 | _ => { 98 | let var2: i32; 99 | let t2: Type = vars.get_type(cmd[2].to_string())?; 100 | match t2.name { 101 | TypeName::I32 => var2 = memory.yeild_i32(t2.location), 102 | _ => return Err(ErrorKind::ExpectedInt(cmd[2].to_string())), 103 | } 104 | memory.set_int_to_stack(var - var2); 105 | } 106 | } 107 | Ok(()) 108 | } else { 109 | Ok(()) 110 | } 111 | } 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/funcs/operations/add.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | funcs::errors::ErrorKind, 3 | memory::Memory, 4 | types::{Type, TypeName, Vars}, 5 | CPU, 6 | }; 7 | 8 | pub fn add( 9 | memory: &mut Memory, 10 | vars: &mut Vars, 11 | registers: &mut CPU, 12 | cmd: Vec<&str>, 13 | ) -> Result<(), ErrorKind> { 14 | if cmd.len() == 1 { 15 | let n1: i32 = memory.get_int_from_stack()?; 16 | let sub = memory.stack.len().saturating_sub(4); 17 | memory.stack.truncate(sub); 18 | 19 | let n2: i32 = memory.get_int_from_stack()?; 20 | let sub = memory.stack.len().saturating_sub(4); 21 | memory.stack.truncate(sub); 22 | memory.set_int_to_stack(n1 + n2); 23 | Ok(()) 24 | } else { 25 | match cmd[1] { 26 | "lx" => { 27 | if cmd.len() == 2 { 28 | let n: i32 = memory.get_int_from_stack()?; 29 | let sub = memory.stack.len().saturating_sub(4); 30 | memory.stack.truncate(sub); 31 | memory.set_int_to_stack(registers.lx + n); 32 | Ok(()) 33 | } else { 34 | match cmd[2] { 35 | "rv" => memory.set_int_to_stack(registers.lx + registers.rv), 36 | "lx" => memory.set_int_to_stack(registers.lx + registers.lx), 37 | _ => { 38 | let n: i32; 39 | let t: Type = vars.get_type(cmd[2].to_string())?; 40 | match t.name { 41 | TypeName::I32 => n = memory.yeild_i32(t.location), 42 | _ => return Err(ErrorKind::ExpectedInt(cmd[2].to_string())), 43 | } 44 | memory.set_int_to_stack(registers.lx + n); 45 | } 46 | } 47 | Ok(()) 48 | } 49 | } 50 | "rv" => { 51 | if cmd.len() == 2 { 52 | let n: i32 = memory.get_int_from_stack()?; 53 | let sub = memory.stack.len().saturating_sub(4); 54 | memory.stack.truncate(sub); 55 | memory.set_int_to_stack(registers.rv + n); 56 | Ok(()) 57 | } else { 58 | match cmd[2] { 59 | "rv" => memory.set_int_to_stack(registers.rv + registers.rv), 60 | "lx" => memory.set_int_to_stack(registers.rv + registers.lx), 61 | _ => { 62 | let n: i32; 63 | let t: Type = vars.get_type(cmd[2].to_string())?; 64 | match t.name { 65 | TypeName::I32 => n = memory.yeild_i32(t.location), 66 | _ => return Err(ErrorKind::ExpectedInt(cmd[2].to_string())), 67 | } 68 | memory.set_int_to_stack(registers.rv + n); 69 | } 70 | } 71 | Ok(()) 72 | } 73 | } 74 | _ => { 75 | if cmd.len() == 2 { 76 | let var: i32; 77 | let t: Type = vars.get_type(cmd[1].to_string())?; 78 | match t.name { 79 | TypeName::I32 => var = memory.yeild_i32(t.location), 80 | _ => return Err(ErrorKind::ExpectedInt(cmd[2].to_string())), 81 | } 82 | let n: i32 = memory.get_int_from_stack()?; 83 | let sub = memory.stack.len().saturating_sub(4); 84 | memory.stack.truncate(sub); 85 | memory.set_int_to_stack(var + n); 86 | Ok(()) 87 | } else if cmd.len() == 3 { 88 | let var: i32; 89 | let t: Type = vars.get_type(cmd[1].to_string())?; 90 | match t.name { 91 | TypeName::I32 => var = memory.yeild_i32(t.location), 92 | _ => return Err(ErrorKind::ExpectedInt(cmd[2].to_string())), 93 | } 94 | match cmd[2] { 95 | "lx" => memory.set_int_to_stack(registers.lx + var), 96 | "rv" => memory.set_int_to_stack(registers.rv + var), 97 | _ => { 98 | let var2: i32; 99 | let t2: Type = vars.get_type(cmd[2].to_string())?; 100 | match t2.name { 101 | TypeName::I32 => var2 = memory.yeild_i32(t2.location), 102 | _ => return Err(ErrorKind::ExpectedInt(cmd[2].to_string())), 103 | } 104 | memory.set_int_to_stack(var + var2); 105 | } 106 | } 107 | Ok(()) 108 | } else { 109 | Ok(()) 110 | } 111 | } 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/funcs/operations/div.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | funcs::errors::ErrorKind, 3 | memory::Memory, 4 | types::{Type, TypeName, Vars}, 5 | CPU, 6 | }; 7 | 8 | pub fn div( 9 | memory: &mut Memory, 10 | vars: &mut Vars, 11 | registers: &mut CPU, 12 | cmd: Vec<&str>, 13 | ) -> Result<(), ErrorKind> { 14 | if cmd.len() == 1 { 15 | let n1: i32 = memory.get_int_from_stack()?; 16 | let sub = memory.stack.len().saturating_sub(4); 17 | memory.stack.truncate(sub); 18 | 19 | let n2: i32 = memory.get_int_from_stack()?; 20 | let sub = memory.stack.len().saturating_sub(4); 21 | memory.stack.truncate(sub); 22 | 23 | memory.set_int_to_stack(n2 / n1); 24 | Ok(()) 25 | } else { 26 | match cmd[1] { 27 | "lx" => { 28 | if cmd.len() == 2 { 29 | let n: i32 = memory.get_int_from_stack()?; 30 | let sub = memory.stack.len().saturating_sub(4); 31 | memory.stack.truncate(sub); 32 | memory.set_int_to_stack(n / registers.lx); 33 | Ok(()) 34 | } else { 35 | match cmd[2] { 36 | "rv" => memory.set_int_to_stack(registers.lx / registers.rv), 37 | "lx" => memory.set_int_to_stack(registers.lx / registers.lx), 38 | _ => { 39 | let n: i32; 40 | let t: Type = vars.get_type(cmd[2].to_string())?; 41 | match t.name { 42 | TypeName::I32 => n = memory.yeild_i32(t.location), 43 | _ => return Err(ErrorKind::ExpectedInt(cmd[2].to_string())), 44 | } 45 | memory.set_int_to_stack(registers.lx / n); 46 | } 47 | } 48 | Ok(()) 49 | } 50 | } 51 | "rv" => { 52 | if cmd.len() == 2 { 53 | let n: i32 = memory.get_int_from_stack()?; 54 | let sub = memory.stack.len().saturating_sub(4); 55 | memory.stack.truncate(sub); 56 | memory.set_int_to_stack(n / registers.rv); 57 | Ok(()) 58 | } else { 59 | match cmd[2] { 60 | "rv" => { 61 | memory.set_int_to_stack(registers.rv / registers.rv); 62 | Ok(()) 63 | } 64 | "lx" => { 65 | memory.set_int_to_stack(registers.rv / registers.lx); 66 | Ok(()) 67 | } 68 | _ => { 69 | let n: i32; 70 | let t: Type = vars.get_type(cmd[2].to_string())?; 71 | match t.name { 72 | TypeName::I32 => n = memory.yeild_i32(t.location), 73 | _ => return Err(ErrorKind::ExpectedInt(cmd[2].to_string())), 74 | } 75 | memory.set_int_to_stack(registers.rv / n); 76 | Ok(()) 77 | } 78 | } 79 | } 80 | } 81 | _ => { 82 | if cmd.len() == 2 { 83 | let var: i32; 84 | let t: Type = vars.get_type(cmd[1].to_string())?; 85 | match t.name { 86 | TypeName::I32 => var = memory.yeild_i32(t.location), 87 | _ => return Err(ErrorKind::ExpectedInt(cmd[2].to_string())), 88 | } 89 | let n: i32 = memory.get_int_from_stack()?; 90 | let sub = memory.stack.len().saturating_sub(4); 91 | memory.stack.truncate(sub); 92 | memory.set_int_to_stack(n / var); 93 | Ok(()) 94 | } else if cmd.len() == 3 { 95 | let var: i32; 96 | let t: Type = vars.get_type(cmd[1].to_string())?; 97 | match t.name { 98 | TypeName::I32 => var = memory.yeild_i32(t.location), 99 | _ => return Err(ErrorKind::ExpectedInt(cmd[2].to_string())), 100 | } 101 | match cmd[2] { 102 | "lx" => { 103 | memory.set_int_to_stack(var / registers.lx); 104 | Ok(()) 105 | } 106 | "rv" => { 107 | memory.set_int_to_stack(var / registers.rv); 108 | Ok(()) 109 | } 110 | _ => { 111 | let var2: i32; 112 | let t2: Type = vars.get_type(cmd[2].to_string())?; 113 | match t2.name { 114 | TypeName::I32 => var2 = memory.yeild_i32(t2.location), 115 | _ => return Err(ErrorKind::ExpectedInt(cmd[2].to_string())), 116 | } 117 | memory.set_int_to_stack(var / var2); 118 | Ok(()) 119 | } 120 | } 121 | } else { 122 | Ok(()) 123 | } 124 | } 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/tests/stack/stack_test.rs: -------------------------------------------------------------------------------- 1 | use crate::funcs::stack; 2 | use crate::{memory::Memory, types::Vars, CPU}; 3 | 4 | #[test] 5 | fn ram_10() { 6 | let mut memory: Memory = Memory::new(); 7 | let mut registers: CPU = CPU::new(); 8 | let mut vars: Vars = Vars::new(); 9 | 10 | let statement = "ram 10"; 11 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 12 | stack::ram(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 13 | assert_eq!(memory.get_int_from_stack().unwrap(), 10) 14 | } 15 | 16 | #[test] 17 | fn ram_lx_10() { 18 | let mut memory: Memory = Memory::new(); 19 | let mut registers: CPU = CPU::new(); 20 | let mut vars: Vars = Vars::new(); 21 | 22 | let statement = "ram lx 10"; 23 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 24 | stack::ram(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 25 | 26 | assert_eq!(registers.lx, 10) 27 | } 28 | 29 | #[test] 30 | fn ram_rv_10() { 31 | let mut memory: Memory = Memory::new(); 32 | let mut registers: CPU = CPU::new(); 33 | let mut vars: Vars = Vars::new(); 34 | 35 | let statement = "ram rv 10"; 36 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 37 | stack::ram(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 38 | 39 | assert_eq!(registers.rv, 10) 40 | } 41 | 42 | #[test] 43 | fn ram_lx_prev() { 44 | let mut memory: Memory = Memory::new(); 45 | let mut registers: CPU = CPU::new(); 46 | let mut vars: Vars = Vars::new(); 47 | 48 | vars.set_int_to_stack(&mut memory, "10").unwrap(); 49 | let statement = "ram lx prev"; 50 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 51 | stack::ram(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 52 | 53 | assert_eq!(registers.lx, 10) 54 | } 55 | 56 | #[test] 57 | fn ram_rv_prev() { 58 | let mut memory: Memory = Memory::new(); 59 | let mut registers: CPU = CPU::new(); 60 | let mut vars: Vars = Vars::new(); 61 | 62 | vars.set_int_to_stack(&mut memory, "10").unwrap(); 63 | let statement = "ram rv prev"; 64 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 65 | stack::ram(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 66 | 67 | assert_eq!(registers.rv, 10) 68 | } 69 | 70 | #[test] 71 | fn ram_lx() { 72 | let mut memory: Memory = Memory::new(); 73 | let mut registers: CPU = CPU::new(); 74 | let mut vars: Vars = Vars::new(); 75 | 76 | registers.lx = 10; 77 | let statement = "ram lx"; 78 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 79 | stack::ram(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 80 | 81 | assert_eq!(memory.get_int_from_stack().unwrap(), registers.lx) 82 | } 83 | 84 | #[test] 85 | fn ram_rv() { 86 | let mut memory: Memory = Memory::new(); 87 | let mut registers: CPU = CPU::new(); 88 | let mut vars: Vars = Vars::new(); 89 | 90 | registers.rv = 10; 91 | let statement = "ram rv"; 92 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 93 | stack::ram(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 94 | 95 | assert_eq!(memory.get_int_from_stack().unwrap(), registers.rv) 96 | } 97 | 98 | #[test] 99 | fn ram_string_eq_hellow() { 100 | let mut memory: Memory = Memory::new(); 101 | let mut registers: CPU = CPU::new(); 102 | let mut vars: Vars = Vars::new(); 103 | 104 | registers.rv = 10; 105 | let statement = "ram string = 'hello'"; 106 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 107 | stack::ram(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 108 | 109 | assert_eq!(registers.string, "hello".to_string()) 110 | } 111 | 112 | #[test] 113 | fn ram_lxstring_eq_hellow() { 114 | let mut memory: Memory = Memory::new(); 115 | let mut registers: CPU = CPU::new(); 116 | let mut vars: Vars = Vars::new(); 117 | 118 | registers.rv = 10; 119 | let statement = "ram lxstring = 'hello'"; 120 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 121 | stack::ram(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 122 | 123 | assert_eq!(registers.lxstring, "hello".to_string()) 124 | } 125 | 126 | #[test] 127 | fn ram_var_int() { 128 | let mut memory: Memory = Memory::new(); 129 | let mut registers: CPU = CPU::new(); 130 | let mut vars: Vars = Vars::new(); 131 | 132 | let statement = "ram x :int = 5"; 133 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 134 | stack::ram(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 135 | 136 | let t = vars.get_type("x".to_string()).unwrap(); 137 | assert_eq!(memory.yeild_i32(t.location), 5) 138 | } 139 | 140 | #[test] 141 | fn ram_var_str() { 142 | let mut memory: Memory = Memory::new(); 143 | let mut registers: CPU = CPU::new(); 144 | let mut vars: Vars = Vars::new(); 145 | 146 | let statement = "ram x :str = 'meow'"; 147 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 148 | stack::ram(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 149 | 150 | let t = vars.get_type("x".to_string()).unwrap(); 151 | assert_eq!(memory.yeild_string(t.location), "meow".to_string()) 152 | } 153 | 154 | #[test] 155 | fn ram_vec_int() { 156 | let mut memory: Memory = Memory::new(); 157 | let mut registers: CPU = CPU::new(); 158 | let mut vars: Vars = Vars::new(); 159 | 160 | let statement = "ram x :vec :int = [1, 2]"; 161 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 162 | stack::ram(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 163 | 164 | let t = vars.get_type("x".to_string()).unwrap(); 165 | assert_eq!(memory.yeild_int_vec(t.location), [1, 2].to_vec()) 166 | } 167 | 168 | #[test] 169 | fn ram_vec_str() { 170 | let mut memory: Memory = Memory::new(); 171 | let mut registers: CPU = CPU::new(); 172 | let mut vars: Vars = Vars::new(); 173 | 174 | let statement = "ram x :vec :str = ['ok', 'meow']"; 175 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 176 | stack::ram(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 177 | 178 | let t = vars.get_type("x".to_string()).unwrap(); 179 | assert_eq!( 180 | memory.yeild_str_vec(t.location), 181 | ["ok".to_string(), "meow".to_string()].to_vec() 182 | ) 183 | } 184 | -------------------------------------------------------------------------------- /src/tests/operations/div.rs: -------------------------------------------------------------------------------- 1 | use crate::funcs::operations; 2 | use crate::{memory::Memory, types::Vars, CPU}; 3 | 4 | // div 5 | // div lx 6 | // div rv 7 | // div var 8 | // div lx rv 9 | // div rv lx 10 | // div var1 var2 11 | // div var lx 12 | // div var rv 13 | // div rv var 14 | // div lx var 15 | 16 | #[test] 17 | fn div() { 18 | let mut memory: Memory = Memory::new(); 19 | let mut registers: CPU = CPU::new(); 20 | let mut vars: Vars = Vars::new(); 21 | 22 | memory.set_int_to_stack(10); 23 | memory.set_int_to_stack(2); 24 | 25 | let statement = "div"; 26 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 27 | 28 | operations::div::div(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 29 | 30 | assert_eq!(memory.get_int_from_stack().unwrap(), 5) 31 | } 32 | 33 | #[test] 34 | fn div_lx() { 35 | let mut memory: Memory = Memory::new(); 36 | let mut registers: CPU = CPU::new(); 37 | let mut vars: Vars = Vars::new(); 38 | 39 | memory.set_int_to_stack(10); 40 | registers.lx = 2; 41 | 42 | let statement = "div lx"; 43 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 44 | 45 | operations::div::div(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 46 | 47 | assert_eq!(memory.get_int_from_stack().unwrap(), 5) 48 | } 49 | 50 | #[test] 51 | fn div_rv() { 52 | let mut memory: Memory = Memory::new(); 53 | let mut registers: CPU = CPU::new(); 54 | let mut vars: Vars = Vars::new(); 55 | 56 | memory.set_int_to_stack(20); 57 | registers.rv = 5; 58 | 59 | let statement = "div rv"; 60 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 61 | 62 | operations::div::div(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 63 | 64 | assert_eq!(memory.get_int_from_stack().unwrap(), 4) 65 | } 66 | 67 | #[test] 68 | fn div_var() { 69 | let mut memory: Memory = Memory::new(); 70 | let mut registers: CPU = CPU::new(); 71 | let mut vars: Vars = Vars::new(); 72 | 73 | vars.set_int("x".to_string(), "2", &mut memory).unwrap(); 74 | memory.set_int_to_stack(6); 75 | 76 | let statement = "div x"; 77 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 78 | 79 | operations::div::div(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 80 | 81 | assert_eq!(memory.get_int_from_stack().unwrap(), 3) 82 | } 83 | 84 | #[test] 85 | fn div_lx_rv() { 86 | let mut memory: Memory = Memory::new(); 87 | let mut registers: CPU = CPU::new(); 88 | let mut vars: Vars = Vars::new(); 89 | 90 | registers.lx = 2; 91 | registers.rv = 2; 92 | 93 | let statement = "div lx rv"; 94 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 95 | 96 | operations::div::div(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 97 | 98 | assert_eq!(memory.get_int_from_stack().unwrap(), 1) 99 | } 100 | 101 | #[test] 102 | fn div_rv_lx() { 103 | let mut memory: Memory = Memory::new(); 104 | let mut registers: CPU = CPU::new(); 105 | let mut vars: Vars = Vars::new(); 106 | 107 | registers.lx = 2; 108 | registers.rv = 2; 109 | 110 | let statement = "div rv lx"; 111 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 112 | 113 | operations::div::div(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 114 | 115 | assert_eq!(memory.get_int_from_stack().unwrap(), 1) 116 | } 117 | 118 | #[test] 119 | fn div_var_var() { 120 | let mut memory: Memory = Memory::new(); 121 | let mut registers: CPU = CPU::new(); 122 | let mut vars: Vars = Vars::new(); 123 | 124 | vars.set_int("x".to_string(), "2", &mut memory).unwrap(); 125 | vars.set_int("y".to_string(), "2", &mut memory).unwrap(); 126 | 127 | let statement = "div x y"; 128 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 129 | 130 | operations::div::div(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 131 | 132 | assert_eq!(memory.get_int_from_stack().unwrap(), 1) 133 | } 134 | 135 | #[test] 136 | fn div_var_lx() { 137 | let mut memory: Memory = Memory::new(); 138 | let mut registers: CPU = CPU::new(); 139 | let mut vars: Vars = Vars::new(); 140 | 141 | vars.set_int("x".to_string(), "2", &mut memory).unwrap(); 142 | registers.lx = 2; 143 | 144 | let statement = "div x lx"; 145 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 146 | 147 | operations::div::div(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 148 | 149 | assert_eq!(memory.get_int_from_stack().unwrap(), 1) 150 | } 151 | 152 | #[test] 153 | fn div_var_rv() { 154 | let mut memory: Memory = Memory::new(); 155 | let mut registers: CPU = CPU::new(); 156 | let mut vars: Vars = Vars::new(); 157 | 158 | vars.set_int("x".to_string(), "2", &mut memory).unwrap(); 159 | registers.rv = 2; 160 | 161 | let statement = "div x rv"; 162 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 163 | 164 | operations::div::div(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 165 | 166 | assert_eq!(memory.get_int_from_stack().unwrap(), 1) 167 | } 168 | 169 | #[test] 170 | fn div_lx_var() { 171 | let mut memory: Memory = Memory::new(); 172 | let mut registers: CPU = CPU::new(); 173 | let mut vars: Vars = Vars::new(); 174 | 175 | vars.set_int("x".to_string(), "2", &mut memory).unwrap(); 176 | registers.lx = 10; 177 | 178 | let statement = "div lx x"; 179 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 180 | 181 | operations::div::div(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 182 | 183 | assert_eq!(memory.get_int_from_stack().unwrap(), 5) 184 | } 185 | 186 | #[test] 187 | fn div_rv_var() { 188 | let mut memory: Memory = Memory::new(); 189 | let mut registers: CPU = CPU::new(); 190 | let mut vars: Vars = Vars::new(); 191 | 192 | vars.set_int("x".to_string(), "4", &mut memory).unwrap(); 193 | registers.rv = 8; 194 | 195 | let statement = "div rv x"; 196 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 197 | 198 | operations::div::div(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 199 | 200 | assert_eq!(memory.get_int_from_stack().unwrap(), 2) 201 | } 202 | 203 | #[test] 204 | fn div_lx_lx() { 205 | let mut memory: Memory = Memory::new(); 206 | let mut registers: CPU = CPU::new(); 207 | let mut vars: Vars = Vars::new(); 208 | 209 | registers.lx = 3; 210 | 211 | let statement = "div lx lx"; 212 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 213 | 214 | operations::div::div(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 215 | 216 | assert_eq!(memory.get_int_from_stack().unwrap(), 1) 217 | } 218 | 219 | #[test] 220 | fn div_rv_rv() { 221 | let mut memory: Memory = Memory::new(); 222 | let mut registers: CPU = CPU::new(); 223 | let mut vars: Vars = Vars::new(); 224 | 225 | registers.rv = 3; 226 | 227 | let statement = "div rv rv"; 228 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 229 | 230 | operations::div::div(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 231 | 232 | assert_eq!(memory.get_int_from_stack().unwrap(), 1) 233 | } 234 | -------------------------------------------------------------------------------- /src/tests/operations/mul.rs: -------------------------------------------------------------------------------- 1 | use crate::funcs::operations; 2 | use crate::{memory::Memory, types::Vars, CPU}; 3 | 4 | // mul 5 | // mul lx 6 | // mul rv 7 | // mul var 8 | // mul lx rv 9 | // mul rv lx 10 | // mul var1 var2 11 | // mul var lx 12 | // mul var rv 13 | // mul rv var 14 | // mul lx var 15 | 16 | #[test] 17 | fn mul() { 18 | let mut memory: Memory = Memory::new(); 19 | let mut registers: CPU = CPU::new(); 20 | let mut vars: Vars = Vars::new(); 21 | 22 | memory.set_int_to_stack(2); 23 | memory.set_int_to_stack(2); 24 | 25 | let statement = "mul"; 26 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 27 | 28 | operations::mul::mul(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 29 | 30 | assert_eq!(memory.get_int_from_stack().unwrap(), 4) 31 | } 32 | 33 | #[test] 34 | fn mul_lx() { 35 | let mut memory: Memory = Memory::new(); 36 | let mut registers: CPU = CPU::new(); 37 | let mut vars: Vars = Vars::new(); 38 | 39 | memory.set_int_to_stack(2); 40 | registers.lx = 2; 41 | 42 | let statement = "mul lx"; 43 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 44 | 45 | operations::mul::mul(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 46 | 47 | assert_eq!(memory.get_int_from_stack().unwrap(), 4) 48 | } 49 | 50 | #[test] 51 | fn mul_rv() { 52 | let mut memory: Memory = Memory::new(); 53 | let mut registers: CPU = CPU::new(); 54 | let mut vars: Vars = Vars::new(); 55 | 56 | memory.set_int_to_stack(11); 57 | registers.rv = 2; 58 | 59 | let statement = "mul rv"; 60 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 61 | 62 | operations::mul::mul(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 63 | 64 | assert_eq!(memory.get_int_from_stack().unwrap(), 22) 65 | } 66 | 67 | #[test] 68 | fn mul_var() { 69 | let mut memory: Memory = Memory::new(); 70 | let mut registers: CPU = CPU::new(); 71 | let mut vars: Vars = Vars::new(); 72 | 73 | vars.set_int("x".to_string(), "2", &mut memory).unwrap(); 74 | memory.set_int_to_stack(3); 75 | 76 | let statement = "mul x"; 77 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 78 | 79 | operations::mul::mul(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 80 | 81 | assert_eq!(memory.get_int_from_stack().unwrap(), 6) 82 | } 83 | 84 | #[test] 85 | fn mul_lx_rv() { 86 | let mut memory: Memory = Memory::new(); 87 | let mut registers: CPU = CPU::new(); 88 | let mut vars: Vars = Vars::new(); 89 | 90 | registers.lx = 2; 91 | registers.rv = 2; 92 | 93 | let statement = "mul lx rv"; 94 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 95 | 96 | operations::mul::mul(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 97 | 98 | assert_eq!(memory.get_int_from_stack().unwrap(), 4) 99 | } 100 | 101 | #[test] 102 | fn mul_rv_lx() { 103 | let mut memory: Memory = Memory::new(); 104 | let mut registers: CPU = CPU::new(); 105 | let mut vars: Vars = Vars::new(); 106 | 107 | registers.lx = 2; 108 | registers.rv = 2; 109 | 110 | let statement = "mul rv lx"; 111 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 112 | 113 | operations::mul::mul(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 114 | 115 | assert_eq!(memory.get_int_from_stack().unwrap(), 4) 116 | } 117 | 118 | #[test] 119 | fn mul_var_var() { 120 | let mut memory: Memory = Memory::new(); 121 | let mut registers: CPU = CPU::new(); 122 | let mut vars: Vars = Vars::new(); 123 | 124 | vars.set_int("x".to_string(), "2", &mut memory).unwrap(); 125 | vars.set_int("y".to_string(), "2", &mut memory).unwrap(); 126 | 127 | let statement = "mul x y"; 128 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 129 | 130 | operations::mul::mul(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 131 | 132 | assert_eq!(memory.get_int_from_stack().unwrap(), 4) 133 | } 134 | 135 | #[test] 136 | fn mul_var_lx() { 137 | let mut memory: Memory = Memory::new(); 138 | let mut registers: CPU = CPU::new(); 139 | let mut vars: Vars = Vars::new(); 140 | 141 | vars.set_int("x".to_string(), "2", &mut memory).unwrap(); 142 | registers.lx = 2; 143 | 144 | let statement = "mul x lx"; 145 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 146 | 147 | operations::mul::mul(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 148 | 149 | assert_eq!(memory.get_int_from_stack().unwrap(), 4) 150 | } 151 | 152 | #[test] 153 | fn mul_var_rv() { 154 | let mut memory: Memory = Memory::new(); 155 | let mut registers: CPU = CPU::new(); 156 | let mut vars: Vars = Vars::new(); 157 | 158 | vars.set_int("x".to_string(), "2", &mut memory).unwrap(); 159 | registers.rv = 2; 160 | 161 | let statement = "mul x rv"; 162 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 163 | 164 | operations::mul::mul(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 165 | 166 | assert_eq!(memory.get_int_from_stack().unwrap(), 4) 167 | } 168 | 169 | #[test] 170 | fn mul_lx_var() { 171 | let mut memory: Memory = Memory::new(); 172 | let mut registers: CPU = CPU::new(); 173 | let mut vars: Vars = Vars::new(); 174 | 175 | vars.set_int("x".to_string(), "2", &mut memory).unwrap(); 176 | registers.lx = 2; 177 | 178 | let statement = "mul lx x"; 179 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 180 | 181 | operations::mul::mul(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 182 | 183 | assert_eq!(memory.get_int_from_stack().unwrap(), 4) 184 | } 185 | 186 | #[test] 187 | fn mul_rv_var() { 188 | let mut memory: Memory = Memory::new(); 189 | let mut registers: CPU = CPU::new(); 190 | let mut vars: Vars = Vars::new(); 191 | 192 | vars.set_int("x".to_string(), "1", &mut memory).unwrap(); 193 | registers.rv = 2; 194 | 195 | let statement = "mul rv x"; 196 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 197 | 198 | operations::mul::mul(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 199 | 200 | assert_eq!(memory.get_int_from_stack().unwrap(), 2) 201 | } 202 | 203 | #[test] 204 | fn mul_lx_lx() { 205 | let mut memory: Memory = Memory::new(); 206 | let mut registers: CPU = CPU::new(); 207 | let mut vars: Vars = Vars::new(); 208 | 209 | registers.lx = 3; 210 | 211 | let statement = "mul lx lx"; 212 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 213 | 214 | operations::mul::mul(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 215 | 216 | assert_eq!(memory.get_int_from_stack().unwrap(), 9) 217 | } 218 | 219 | #[test] 220 | fn mul_rv_rv() { 221 | let mut memory: Memory = Memory::new(); 222 | let mut registers: CPU = CPU::new(); 223 | let mut vars: Vars = Vars::new(); 224 | 225 | registers.rv = 3; 226 | 227 | let statement = "mul rv rv"; 228 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 229 | 230 | operations::mul::mul(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 231 | 232 | assert_eq!(memory.get_int_from_stack().unwrap(), 9) 233 | } 234 | -------------------------------------------------------------------------------- /src/tests/operations/sub.rs: -------------------------------------------------------------------------------- 1 | use crate::funcs::operations; 2 | use crate::{memory::Memory, types::Vars, CPU}; 3 | 4 | // sub 5 | // sub lx 6 | // sub rv 7 | // sub var 8 | // sub lx rv 9 | // sub rv lx 10 | // sub var1 var2 11 | // sub var lx 12 | // sub var rv 13 | // sub lx var 14 | // sub rv var 15 | 16 | #[test] 17 | fn sub() { 18 | let mut memory: Memory = Memory::new(); 19 | let mut registers: CPU = CPU::new(); 20 | let mut vars: Vars = Vars::new(); 21 | 22 | memory.set_int_to_stack(5); 23 | memory.set_int_to_stack(1); 24 | 25 | let statement = "sub"; 26 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 27 | 28 | operations::sub::sub(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 29 | 30 | assert_eq!(memory.get_int_from_stack().unwrap(), 4) 31 | } 32 | 33 | #[test] 34 | fn sub_lx() { 35 | let mut memory: Memory = Memory::new(); 36 | let mut registers: CPU = CPU::new(); 37 | let mut vars: Vars = Vars::new(); 38 | 39 | memory.set_int_to_stack(1); 40 | registers.lx = 2; 41 | 42 | let statement = "sub lx"; 43 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 44 | 45 | operations::sub::sub(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 46 | 47 | assert_eq!(memory.get_int_from_stack().unwrap(), -1) 48 | } 49 | 50 | #[test] 51 | fn sub_rv() { 52 | let mut memory: Memory = Memory::new(); 53 | let mut registers: CPU = CPU::new(); 54 | let mut vars: Vars = Vars::new(); 55 | 56 | memory.set_int_to_stack(1); 57 | registers.rv = 2; 58 | 59 | let statement = "sub rv"; 60 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 61 | 62 | operations::sub::sub(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 63 | 64 | assert_eq!(memory.get_int_from_stack().unwrap(), -1) 65 | } 66 | 67 | #[test] 68 | fn sub_var() { 69 | let mut memory: Memory = Memory::new(); 70 | let mut registers: CPU = CPU::new(); 71 | let mut vars: Vars = Vars::new(); 72 | 73 | vars.set_int("x".to_string(), "2", &mut memory).unwrap(); 74 | memory.set_int_to_stack(1); 75 | 76 | let statement = "sub x"; 77 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 78 | 79 | operations::sub::sub(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 80 | 81 | assert_eq!(memory.get_int_from_stack().unwrap(), 1) 82 | } 83 | 84 | #[test] 85 | fn sub_lx_rv() { 86 | let mut memory: Memory = Memory::new(); 87 | let mut registers: CPU = CPU::new(); 88 | let mut vars: Vars = Vars::new(); 89 | 90 | registers.lx = 1; 91 | registers.rv = 2; 92 | 93 | let statement = "sub lx rv"; 94 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 95 | 96 | operations::sub::sub(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 97 | 98 | assert_eq!(memory.get_int_from_stack().unwrap(), -1) 99 | } 100 | 101 | #[test] 102 | fn sub_rv_lx() { 103 | let mut memory: Memory = Memory::new(); 104 | let mut registers: CPU = CPU::new(); 105 | let mut vars: Vars = Vars::new(); 106 | 107 | registers.lx = 1; 108 | registers.rv = 2; 109 | 110 | let statement = "sub rv lx"; 111 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 112 | 113 | operations::sub::sub(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 114 | 115 | assert_eq!(memory.get_int_from_stack().unwrap(), 1) 116 | } 117 | 118 | #[test] 119 | fn sub_var_var() { 120 | let mut memory: Memory = Memory::new(); 121 | let mut registers: CPU = CPU::new(); 122 | let mut vars: Vars = Vars::new(); 123 | 124 | vars.set_int("x".to_string(), "1", &mut memory).unwrap(); 125 | vars.set_int("y".to_string(), "2", &mut memory).unwrap(); 126 | 127 | let statement = "sub x y"; 128 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 129 | 130 | operations::sub::sub(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 131 | 132 | assert_eq!(memory.get_int_from_stack().unwrap(), -1) 133 | } 134 | 135 | #[test] 136 | fn sub_var_lx() { 137 | let mut memory: Memory = Memory::new(); 138 | let mut registers: CPU = CPU::new(); 139 | let mut vars: Vars = Vars::new(); 140 | 141 | vars.set_int("x".to_string(), "1", &mut memory).unwrap(); 142 | registers.lx = 2; 143 | 144 | let statement = "sub x lx"; 145 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 146 | 147 | operations::sub::sub(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 148 | 149 | assert_eq!(memory.get_int_from_stack().unwrap(), -1) 150 | } 151 | 152 | #[test] 153 | fn sub_var_rv() { 154 | let mut memory: Memory = Memory::new(); 155 | let mut registers: CPU = CPU::new(); 156 | let mut vars: Vars = Vars::new(); 157 | 158 | vars.set_int("x".to_string(), "1", &mut memory).unwrap(); 159 | registers.rv = 2; 160 | 161 | let statement = "sub x rv"; 162 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 163 | 164 | operations::sub::sub(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 165 | 166 | assert_eq!(memory.get_int_from_stack().unwrap(), -1) 167 | } 168 | 169 | #[test] 170 | fn sub_lx_var() { 171 | let mut memory: Memory = Memory::new(); 172 | let mut registers: CPU = CPU::new(); 173 | let mut vars: Vars = Vars::new(); 174 | 175 | vars.set_int("x".to_string(), "1", &mut memory).unwrap(); 176 | registers.lx = 2; 177 | 178 | let statement = "sub lx x"; 179 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 180 | 181 | operations::sub::sub(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 182 | 183 | assert_eq!(memory.get_int_from_stack().unwrap(), 1) 184 | } 185 | 186 | #[test] 187 | fn sub_rv_var() { 188 | let mut memory: Memory = Memory::new(); 189 | let mut registers: CPU = CPU::new(); 190 | let mut vars: Vars = Vars::new(); 191 | 192 | vars.set_int("x".to_string(), "1", &mut memory).unwrap(); 193 | registers.rv = 2; 194 | 195 | let statement = "sub rv x"; 196 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 197 | 198 | operations::sub::sub(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 199 | 200 | assert_eq!(memory.get_int_from_stack().unwrap(), 1) 201 | } 202 | 203 | #[test] 204 | fn sub_lx_lx() { 205 | let mut memory: Memory = Memory::new(); 206 | let mut registers: CPU = CPU::new(); 207 | let mut vars: Vars = Vars::new(); 208 | 209 | registers.lx = 3; 210 | 211 | let statement = "sub lx lx"; 212 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 213 | 214 | operations::sub::sub(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 215 | 216 | assert_eq!(memory.get_int_from_stack().unwrap(), 0) 217 | } 218 | 219 | #[test] 220 | fn sub_rv_rv() { 221 | let mut memory: Memory = Memory::new(); 222 | let mut registers: CPU = CPU::new(); 223 | let mut vars: Vars = Vars::new(); 224 | 225 | registers.rv = 3; 226 | 227 | let statement = "add rv rv"; 228 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 229 | 230 | operations::sub::sub(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 231 | 232 | assert_eq!(memory.get_int_from_stack().unwrap(), 0) 233 | } 234 | -------------------------------------------------------------------------------- /src/tests/operations/add.rs: -------------------------------------------------------------------------------- 1 | use crate::funcs::operations; 2 | use crate::{memory::Memory, types::Vars, CPU}; 3 | 4 | // add 5 | 6 | // add lx 7 | // add lx rv 8 | // add lx lx 9 | // add lx var 10 | 11 | // add rv 12 | // add rv lx 13 | // add rv rv 14 | // add rv var 15 | 16 | // add var 17 | // add var1 var2 18 | // add var lx 19 | // add var rv 20 | 21 | #[test] 22 | fn add() { 23 | let mut memory: Memory = Memory::new(); 24 | let mut registers: CPU = CPU::new(); 25 | let mut vars: Vars = Vars::new(); 26 | 27 | memory.set_int_to_stack(1); 28 | memory.set_int_to_stack(2); 29 | 30 | let statement = "add"; 31 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 32 | 33 | operations::add::add(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 34 | 35 | assert_eq!(memory.get_int_from_stack().unwrap(), 3) 36 | } 37 | 38 | #[test] 39 | fn add_lx() { 40 | let mut memory: Memory = Memory::new(); 41 | let mut registers: CPU = CPU::new(); 42 | let mut vars: Vars = Vars::new(); 43 | 44 | memory.set_int_to_stack(1); 45 | registers.lx = 2; 46 | 47 | let statement = "add lx"; 48 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 49 | 50 | operations::add::add(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 51 | 52 | assert_eq!(memory.get_int_from_stack().unwrap(), 3) 53 | } 54 | 55 | #[test] 56 | fn add_rv() { 57 | let mut memory: Memory = Memory::new(); 58 | let mut registers: CPU = CPU::new(); 59 | let mut vars: Vars = Vars::new(); 60 | 61 | memory.set_int_to_stack(1); 62 | registers.rv = 2; 63 | 64 | let statement = "add rv"; 65 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 66 | 67 | operations::add::add(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 68 | 69 | assert_eq!(memory.get_int_from_stack().unwrap(), 3) 70 | } 71 | 72 | #[test] 73 | fn add_var() { 74 | let mut memory: Memory = Memory::new(); 75 | let mut registers: CPU = CPU::new(); 76 | let mut vars: Vars = Vars::new(); 77 | 78 | vars.set_int("x".to_string(), "2", &mut memory).unwrap(); 79 | memory.set_int_to_stack(1); 80 | 81 | let statement = "add x"; 82 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 83 | 84 | operations::add::add(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 85 | 86 | assert_eq!(memory.get_int_from_stack().unwrap(), 3) 87 | } 88 | 89 | #[test] 90 | fn add_lx_rv() { 91 | let mut memory: Memory = Memory::new(); 92 | let mut registers: CPU = CPU::new(); 93 | let mut vars: Vars = Vars::new(); 94 | 95 | registers.lx = 1; 96 | registers.rv = 2; 97 | 98 | let statement = "add lx rv"; 99 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 100 | 101 | operations::add::add(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 102 | 103 | assert_eq!(memory.get_int_from_stack().unwrap(), 3) 104 | } 105 | 106 | #[test] 107 | fn add_rv_lx() { 108 | let mut memory: Memory = Memory::new(); 109 | let mut registers: CPU = CPU::new(); 110 | let mut vars: Vars = Vars::new(); 111 | 112 | registers.lx = 1; 113 | registers.rv = 2; 114 | 115 | let statement = "add rv lx"; 116 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 117 | 118 | operations::add::add(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 119 | 120 | assert_eq!(memory.get_int_from_stack().unwrap(), 3) 121 | } 122 | 123 | #[test] 124 | fn add_var_var() { 125 | let mut memory: Memory = Memory::new(); 126 | let mut registers: CPU = CPU::new(); 127 | let mut vars: Vars = Vars::new(); 128 | 129 | vars.set_int("x".to_string(), "1", &mut memory).unwrap(); 130 | vars.set_int("y".to_string(), "2", &mut memory).unwrap(); 131 | 132 | let statement = "add x y"; 133 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 134 | 135 | operations::add::add(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 136 | 137 | assert_eq!(memory.get_int_from_stack().unwrap(), 3) 138 | } 139 | 140 | #[test] 141 | fn add_var_lx() { 142 | let mut memory: Memory = Memory::new(); 143 | let mut registers: CPU = CPU::new(); 144 | let mut vars: Vars = Vars::new(); 145 | 146 | vars.set_int("x".to_string(), "1", &mut memory).unwrap(); 147 | registers.lx = 2; 148 | 149 | let statement = "add x lx"; 150 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 151 | 152 | operations::add::add(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 153 | 154 | assert_eq!(memory.get_int_from_stack().unwrap(), 3) 155 | } 156 | 157 | #[test] 158 | fn add_var_rv() { 159 | let mut memory: Memory = Memory::new(); 160 | let mut registers: CPU = CPU::new(); 161 | let mut vars: Vars = Vars::new(); 162 | 163 | vars.set_int("x".to_string(), "1", &mut memory).unwrap(); 164 | registers.rv = 2; 165 | 166 | let statement = "add x rv"; 167 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 168 | 169 | operations::add::add(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 170 | 171 | assert_eq!(memory.get_int_from_stack().unwrap(), 3) 172 | } 173 | 174 | #[test] 175 | fn add_lx_var() { 176 | let mut memory: Memory = Memory::new(); 177 | let mut registers: CPU = CPU::new(); 178 | let mut vars: Vars = Vars::new(); 179 | 180 | vars.set_int("x".to_string(), "1", &mut memory).unwrap(); 181 | registers.lx = 2; 182 | 183 | let statement = "add lx x"; 184 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 185 | 186 | operations::add::add(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 187 | 188 | assert_eq!(memory.get_int_from_stack().unwrap(), 3) 189 | } 190 | 191 | #[test] 192 | fn add_rv_var() { 193 | let mut memory: Memory = Memory::new(); 194 | let mut registers: CPU = CPU::new(); 195 | let mut vars: Vars = Vars::new(); 196 | 197 | vars.set_int("x".to_string(), "1", &mut memory).unwrap(); 198 | registers.rv = 2; 199 | 200 | let statement = "add rv x"; 201 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 202 | 203 | operations::add::add(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 204 | 205 | assert_eq!(memory.get_int_from_stack().unwrap(), 3) 206 | } 207 | 208 | #[test] 209 | fn add_lx_lx() { 210 | let mut memory: Memory = Memory::new(); 211 | let mut registers: CPU = CPU::new(); 212 | let mut vars: Vars = Vars::new(); 213 | 214 | registers.lx = 3; 215 | 216 | let statement = "add lx lx"; 217 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 218 | 219 | operations::add::add(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 220 | 221 | assert_eq!(memory.get_int_from_stack().unwrap(), 6) 222 | } 223 | 224 | #[test] 225 | fn add_rv_rv() { 226 | let mut memory: Memory = Memory::new(); 227 | let mut registers: CPU = CPU::new(); 228 | let mut vars: Vars = Vars::new(); 229 | 230 | registers.rv = 3; 231 | 232 | let statement = "add rv rv"; 233 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 234 | 235 | operations::add::add(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 236 | 237 | assert_eq!(memory.get_int_from_stack().unwrap(), 6) 238 | } 239 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod funcs; 2 | pub mod memory; 3 | pub mod parser; 4 | 5 | #[cfg(test)] 6 | pub mod tests; 7 | pub mod types; 8 | 9 | use funcs::errors::ErrorKind; 10 | use funcs::*; 11 | use memory::Memory; 12 | use types::Vars; 13 | 14 | use std::collections::HashMap; 15 | use std::process; 16 | 17 | #[derive(Debug, Clone)] 18 | pub struct CPU { 19 | pub lx: i32, 20 | pub rv: i32, 21 | pub string: String, 22 | pub lxstring: String, 23 | pub program_counter: i32, 24 | pub callstack: Vec, 25 | } 26 | 27 | impl CPU { 28 | pub fn new() -> Self { 29 | Self { 30 | lx: 0, 31 | rv: 0, 32 | string: String::new(), 33 | lxstring: String::new(), 34 | program_counter: 0i32, 35 | callstack: vec![], 36 | } 37 | } 38 | 39 | pub fn execute( 40 | &mut self, 41 | instructions: Vec, 42 | label_map: HashMap, 43 | memory: &mut Memory, 44 | vars: &mut Vars, 45 | ) { 46 | loop { 47 | let ret_val: Result<(), errors::ErrorKind>; 48 | let statement = instructions[self.program_counter as usize].trim(); 49 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 50 | ret_val = match cmd[0] { 51 | "dbg" => { 52 | println!("Stack: "); 53 | for i in memory.stack.chunks(8) { 54 | println!("{:?}", i) 55 | } 56 | println!("{:#?} \n {:#?} \n HEAP: {:#?} \n", vars, self, memory.heap); 57 | println!("{:?}", instructions); 58 | Ok(()) 59 | } 60 | "print" => print::print(memory, vars, self, cmd), 61 | "ram" => stack::ram(memory, vars, self, cmd, statement), 62 | "drop" => stack::drop(memory, vars, cmd), 63 | "add" => operations::add::add(memory, vars, self, cmd), 64 | "div" => operations::div::div(memory, vars, self, cmd), 65 | "sub" => operations::sub::sub(memory, vars, self, cmd), 66 | "mul" => operations::mul::mul(memory, vars, self, cmd), 67 | "reset" => { 68 | memory.reset_stack(); 69 | Ok(()) 70 | } 71 | "pop" => { 72 | memory.pop_stack(); 73 | Ok(()) 74 | } 75 | "parse" => stdf::parse::parse(memory, vars, self, cmd), 76 | "rand" => stdf::rand::rand(memory, self, cmd, statement), 77 | "split" => stdf::string::split(memory, vars, self, cmd, statement), 78 | "concat" => stdf::string::concat(memory, vars, self, cmd), 79 | "copy" => stack::copy(memory, vars, self, cmd, statement), 80 | "vec" => vec::vec(memory, vars, self, cmd, statement), 81 | "join" => stdf::string::join(memory, vars, self, cmd, statement), 82 | "trim" => stdf::string::trim(memory, vars, self, cmd), 83 | "insert" => butterfly::map(memory, vars, cmd, statement), 84 | "delete" => butterfly::map(memory, vars, cmd, statement), 85 | "get" => butterfly::map(memory, vars, cmd, statement), 86 | "stdin" => stdf::stdin::stdin(memory, vars, self, cmd, statement), 87 | "stdfs" => stdf::stdfs::stdfs(memory, vars, self, cmd), 88 | 89 | "cmp" => operations::cmp::cmp(memory, vars, self, cmd), 90 | "jmp" => jump::jmp(self, cmd, label_map.clone()), 91 | "je" => jump::je(self, cmd, label_map.clone(), memory), 92 | "jgr" => jump::jgr(self, cmd, label_map.clone(), memory), 93 | "jsm" => jump::jsm(self, cmd, label_map.clone(), memory), 94 | "jne" => jump::jne(self, cmd, label_map.clone(), memory), 95 | "ret" => jump::ret(self), 96 | "halt" => process::exit(0), 97 | _ => { 98 | println!("Cant recognize statement: {}", statement); 99 | process::exit(1) 100 | } 101 | }; 102 | 103 | match ret_val { 104 | Ok(()) => (), 105 | Err(e) => { 106 | let label = errors::get_label(self.program_counter, label_map); 107 | match e { 108 | ErrorKind::ArgErr => { 109 | println!("Invalid arguments at {} {}", label, statement) 110 | } 111 | ErrorKind::ParseInt => println!("Expected Int at {} {}", label, statement), 112 | ErrorKind::StackLen => { 113 | println!("Not enough items in stack at {} {}", label, statement) 114 | } 115 | ErrorKind::VarNotFound(var) => { 116 | println!("Var '{}' not found at {} {}", var, label, statement) 117 | } 118 | ErrorKind::Casting { src, dest } => println!( 119 | "Cannot cast '{}' to '{}' at {} {}", 120 | src, dest, label, statement 121 | ), 122 | ErrorKind::ExpectedInt(var) => { 123 | println!("Expected '{}' to be int at {} {}", var, label, statement) 124 | } 125 | ErrorKind::ExpectedVec(var) => { 126 | println!("Expected '{}' to be int at {} {}", var, label, statement) 127 | } 128 | ErrorKind::ExpectedStr(var) => { 129 | println!("Expected '{}' to be int at {} {}", var, label, statement) 130 | } 131 | ErrorKind::RangeNegative => println!( 132 | "Range should be non-zero and positive at {} {}", 133 | label, statement 134 | ), 135 | ErrorKind::EmptyCallstack => { 136 | println!("Nowhere to return to at {} {}", label, statement) 137 | } 138 | ErrorKind::LabelNotFound(l) => { 139 | println!("Label '{}' not found at {}: {}", l, label, statement) 140 | } 141 | ErrorKind::VecLen(name) => { 142 | println!( 143 | "'{}' dosent have enough length at {}: {}", 144 | name, label, statement 145 | ) 146 | } 147 | ErrorKind::ExpectedMap(name) => { 148 | println!( 149 | "Expected '{}' to be a map at {}: {}", 150 | name, label, statement 151 | ) 152 | } 153 | ErrorKind::MapValueNotFound => println!("Property Not found on map"), 154 | ErrorKind::ExpectedFloat => println!("Expected float/int at {}: {} ", label, statement) 155 | } 156 | process::exit(1) 157 | } 158 | } 159 | self.program_counter += 1; 160 | if self.program_counter == instructions.len() as i32 { 161 | break; 162 | } 163 | } 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /src/funcs/stdf/string.rs: -------------------------------------------------------------------------------- 1 | use crate::funcs::errors::ErrorKind; 2 | use crate::types::{TypeName, Vars, Vector}; 3 | use crate::{memory::Memory, CPU}; 4 | 5 | pub fn split( 6 | memory: &mut Memory, 7 | vars: &mut Vars, 8 | registers: &mut CPU, 9 | cmd: Vec<&str>, 10 | statement: &str, 11 | ) -> Result<(), ErrorKind> { 12 | if cmd.len() < 6 { 13 | return Err(ErrorKind::ArgErr); 14 | } 15 | let var_str = cmd[cmd.len() - 1].trim(); 16 | let t = vars.get_type(var_str.to_string())?; 17 | if t.name != TypeName::Vector(Vector::String) { 18 | return Err(ErrorKind::ExpectedVec(var_str.to_string())); 19 | } 20 | let mut qc = 0i32; 21 | let mut delimiter = String::from(""); 22 | for c in statement.chars() { 23 | if c == '"' { 24 | qc += 1; 25 | } 26 | if qc == 1 && c != '"' { 27 | delimiter.push(c) 28 | } 29 | } 30 | let binding = append_escapes(&delimiter); 31 | delimiter = binding; 32 | match cmd[1] { 33 | "string" => vars.set_raw_str_vec( 34 | var_str.to_string(), 35 | registers 36 | .string 37 | .split(delimiter.as_str()) 38 | .filter(|&x| x != delimiter) 39 | .collect::>(), 40 | memory, 41 | ), 42 | "lxstring" => vars.set_raw_str_vec( 43 | var_str.to_string(), 44 | registers 45 | .lxstring 46 | .split(delimiter.as_str()) 47 | .filter(|&x| x != delimiter) 48 | .collect::>(), 49 | memory, 50 | ), 51 | _ => { 52 | let split_var_str = cmd[1]; 53 | let split_var_str_type = vars.get_type(split_var_str.to_string())?; 54 | if split_var_str_type.name == TypeName::String { 55 | let split_var = memory.yeild_string(split_var_str_type.location); 56 | vars.set_raw_str_vec( 57 | var_str.to_string(), 58 | split_var 59 | .split(delimiter.as_str()) 60 | .filter(|&x| x != delimiter) 61 | .collect::>(), 62 | memory, 63 | ); 64 | } else { 65 | return Err(ErrorKind::ExpectedStr(split_var_str.to_string())); 66 | } 67 | } 68 | } 69 | Ok(()) 70 | } 71 | 72 | fn append_escapes(del: &str) -> String { 73 | let mut x = del.replacen(r"\n", "\n", del.len()); 74 | x = x.replacen(r"\r", "\r", del.len()); 75 | x = x.replacen(r"\t", "\t", del.len()); 76 | x 77 | } 78 | 79 | pub fn join( 80 | memory: &mut Memory, 81 | vars: &mut Vars, 82 | registers: &mut CPU, 83 | cmd: Vec<&str>, 84 | statement: &str, 85 | ) -> Result<(), ErrorKind> { 86 | if cmd.len() < 6 { 87 | return Err(ErrorKind::ArgErr); 88 | } 89 | let assign_to = cmd[cmd.len() - 1].to_string(); 90 | let vec_str = cmd[1].to_string(); 91 | let del_exp = statement.split('=').collect::>()[0] 92 | .trim() 93 | .split('>') 94 | .collect::>()[1] 95 | .trim(); 96 | let delimiter: &str = &del_exp[1..del_exp.len() - 1]; 97 | let var = vars.get_type(vec_str.clone())?; 98 | if var.name != TypeName::Vector(Vector::String) { 99 | return Err(ErrorKind::ExpectedStr(vec_str)); 100 | } 101 | match assign_to.trim() { 102 | "string" => registers.string = memory.yeild_str_vec(var.location).join(delimiter), 103 | "lxstring" => registers.string = memory.yeild_str_vec(var.location).join(delimiter), 104 | _ => { 105 | let t = vars.get_type(assign_to.clone())?; 106 | if t.name == TypeName::String { 107 | let heap_addr = u32::from_be_bytes(memory.load(t.location).try_into().unwrap()); 108 | let vec = memory.yeild_str_vec(var.location); 109 | memory.heap_mod(heap_addr, vec.join(delimiter).as_bytes()) 110 | } else { 111 | return Err(ErrorKind::ExpectedStr(assign_to)); 112 | } 113 | } 114 | } 115 | Ok(()) 116 | } 117 | 118 | pub fn concat( 119 | memory: &mut Memory, 120 | vars: &mut Vars, 121 | registers: &mut CPU, 122 | cmd: Vec<&str>, 123 | ) -> Result<(), ErrorKind> { 124 | if cmd.len() > 3 { 125 | return Err(ErrorKind::ArgErr); 126 | } 127 | 128 | match cmd[1] { 129 | "string" => match cmd[2] { 130 | "string" => registers.string = format!("{}{}", registers.string, registers.string), 131 | "lxstring" => registers.string = format!("{}{}", registers.string, registers.lxstring), 132 | _ => { 133 | let t = vars.get_type(cmd[2].to_string())?; 134 | if t.name == TypeName::String { 135 | registers.string = 136 | format!("{}{}", registers.string, memory.yeild_string(t.location)) 137 | } else { 138 | return Err(ErrorKind::ExpectedStr(cmd[2].to_string())); 139 | } 140 | } 141 | }, 142 | "lxstring" => match cmd[2] { 143 | "string" => registers.string = format!("{}{}", registers.lxstring, registers.string), 144 | "lxstring" => { 145 | registers.string = format!("{}{}", registers.lxstring, registers.lxstring) 146 | } 147 | _ => { 148 | let t = vars.get_type(cmd[2].to_string())?; 149 | if t.name == TypeName::String { 150 | registers.string = 151 | format!("{}{}", registers.lxstring, memory.yeild_string(t.location)) 152 | } else { 153 | return Err(ErrorKind::ExpectedStr(cmd[2].to_string())); 154 | } 155 | } 156 | }, 157 | _ => { 158 | let t = vars.get_type(cmd[1].to_string())?; 159 | match cmd[2] { 160 | "string" => { 161 | registers.string = 162 | format!("{}{}", memory.yeild_string(t.location), registers.string) 163 | } 164 | "lxstring" => { 165 | registers.string = 166 | format!("{}{}", memory.yeild_string(t.location), registers.lxstring) 167 | } 168 | _ => { 169 | let t2 = vars.get_type(cmd[2].to_string())?; 170 | registers.string = format!( 171 | "{}{}", 172 | memory.yeild_string(t.location), 173 | memory.yeild_string(t2.location) 174 | ) 175 | } 176 | } 177 | } 178 | } 179 | Ok(()) 180 | } 181 | 182 | pub fn trim( 183 | memory: &mut Memory, 184 | vars: &mut Vars, 185 | registers: &mut CPU, 186 | cmd: Vec<&str>, 187 | ) -> Result<(), ErrorKind> { 188 | if cmd.len() != 2 { 189 | return Err(ErrorKind::ArgErr); 190 | } 191 | match cmd[1] { 192 | "string" => registers.string = registers.string.trim().to_string(), 193 | "lxstring" => registers.lxstring = registers.lxstring.trim().to_string(), 194 | _ => { 195 | let t = vars.get_type(cmd[1].to_string())?; 196 | if t.name == TypeName::String { 197 | let value = memory.yeild_string(t.location); 198 | vars.set_string(cmd[1].to_string(), value.trim(), memory); 199 | } else { 200 | return Err(ErrorKind::ExpectedStr(cmd[1].to_string())); 201 | } 202 | } 203 | } 204 | Ok(()) 205 | } 206 | -------------------------------------------------------------------------------- /src/tests/stack/copy.rs: -------------------------------------------------------------------------------- 1 | use crate::funcs::stack::copy; 2 | use crate::{memory::Memory, types::Vars, CPU}; 3 | 4 | // copy lx = rv 5 | // copy lx = var 6 | 7 | // copy rv = lx 8 | // copy rv = var 9 | 10 | // copy string = lxstring 11 | // copy string = var 12 | 13 | // copy lxstring = string 14 | // copy lxstring = var 15 | 16 | // copy var = lx 17 | // copy var = rv 18 | // copy var = string 19 | // copy var = lxstring 20 | // copy var1 = var2 21 | 22 | #[test] 23 | fn copy_lx_rv() { 24 | let mut memory: Memory = Memory::new(); 25 | let mut registers: CPU = CPU::new(); 26 | let mut vars: Vars = Vars::new(); 27 | 28 | registers.rv = 5; 29 | let statement: &str = "copy lx = rv"; 30 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 31 | 32 | copy(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 33 | assert_eq!(registers.rv, registers.lx) 34 | } 35 | 36 | #[test] 37 | fn copy_lx_var() { 38 | let mut memory: Memory = Memory::new(); 39 | let mut registers: CPU = CPU::new(); 40 | let mut vars: Vars = Vars::new(); 41 | 42 | registers.lx = 5; 43 | vars.set_int("x".to_string(), "1", &mut memory).unwrap(); 44 | 45 | let statement: &str = "copy lx = x"; 46 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 47 | 48 | copy(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 49 | assert_eq!(registers.lx, 1) 50 | } 51 | 52 | #[test] 53 | fn copy_rv_lx() { 54 | let mut memory: Memory = Memory::new(); 55 | let mut registers: CPU = CPU::new(); 56 | let mut vars: Vars = Vars::new(); 57 | 58 | registers.lx = 5; 59 | let statement: &str = "copy rv = lx"; 60 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 61 | 62 | copy(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 63 | assert_eq!(registers.rv, registers.lx) 64 | } 65 | 66 | #[test] 67 | fn copy_rv_var() { 68 | let mut memory: Memory = Memory::new(); 69 | let mut registers: CPU = CPU::new(); 70 | let mut vars: Vars = Vars::new(); 71 | 72 | registers.rv = 5; 73 | vars.set_int("x".to_string(), "1", &mut memory).unwrap(); 74 | 75 | let statement: &str = "copy rv = x"; 76 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 77 | 78 | copy(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 79 | assert_eq!(registers.rv, 1) 80 | } 81 | 82 | #[test] 83 | fn copy_string_lxstring() { 84 | let mut memory: Memory = Memory::new(); 85 | let mut registers: CPU = CPU::new(); 86 | let mut vars: Vars = Vars::new(); 87 | 88 | registers.lxstring = "hello".to_string(); 89 | 90 | let statement: &str = "copy string = lxstring"; 91 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 92 | 93 | copy(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 94 | assert_eq!(registers.string, registers.lxstring) 95 | } 96 | 97 | #[test] 98 | fn copy_string_var() { 99 | let mut memory: Memory = Memory::new(); 100 | let mut registers: CPU = CPU::new(); 101 | let mut vars: Vars = Vars::new(); 102 | 103 | vars.set_string("x".to_string(), "hello", &mut memory); 104 | 105 | let statement: &str = "copy string = x"; 106 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 107 | 108 | copy(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 109 | assert_eq!(registers.string, "hello".to_string()) 110 | } 111 | 112 | #[test] 113 | fn copy_lxstring_string() { 114 | let mut memory: Memory = Memory::new(); 115 | let mut registers: CPU = CPU::new(); 116 | let mut vars: Vars = Vars::new(); 117 | 118 | registers.string = "hello".to_string(); 119 | 120 | let statement: &str = "copy lxstring = string"; 121 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 122 | 123 | copy(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 124 | assert_eq!(registers.string, registers.lxstring) 125 | } 126 | 127 | #[test] 128 | fn copy_lxstring_var() { 129 | let mut memory: Memory = Memory::new(); 130 | let mut registers: CPU = CPU::new(); 131 | let mut vars: Vars = Vars::new(); 132 | 133 | vars.set_string("x".to_string(), "hello", &mut memory); 134 | 135 | let statement: &str = "copy lxstring = x"; 136 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 137 | 138 | copy(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 139 | assert_eq!(registers.lxstring, "hello".to_string()) 140 | } 141 | 142 | #[test] 143 | fn copy_var_lx() { 144 | let mut memory: Memory = Memory::new(); 145 | let mut registers: CPU = CPU::new(); 146 | let mut vars: Vars = Vars::new(); 147 | 148 | vars.set_int("x".to_string(), "0", &mut memory).unwrap(); 149 | registers.lx = 1; 150 | 151 | let statement: &str = "copy x = lx"; 152 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 153 | 154 | copy(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 155 | let t = vars.get_type("x".to_string()).unwrap(); 156 | 157 | assert_eq!(memory.yeild_i32(t.location), 1) 158 | } 159 | 160 | #[test] 161 | fn copy_var_rv() { 162 | let mut memory: Memory = Memory::new(); 163 | let mut registers: CPU = CPU::new(); 164 | let mut vars: Vars = Vars::new(); 165 | 166 | vars.set_int("x".to_string(), "0", &mut memory).unwrap(); 167 | registers.rv = 1; 168 | 169 | let statement: &str = "copy x = rv"; 170 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 171 | 172 | copy(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 173 | let t = vars.get_type("x".to_string()).unwrap(); 174 | 175 | assert_eq!(memory.yeild_i32(t.location), 1) 176 | } 177 | 178 | #[test] 179 | fn copy_var_string() { 180 | let mut memory: Memory = Memory::new(); 181 | let mut registers: CPU = CPU::new(); 182 | let mut vars: Vars = Vars::new(); 183 | 184 | vars.set_string("x".to_string(), "", &mut memory); 185 | registers.string = "hello".to_string(); 186 | 187 | let statement: &str = "copy x = string"; 188 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 189 | 190 | copy(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 191 | let t = vars.get_type("x".to_string()).unwrap(); 192 | 193 | assert_eq!(memory.yeild_string(t.location), "hello".to_string()) 194 | } 195 | 196 | #[test] 197 | fn copy_var_lxstring() { 198 | let mut memory: Memory = Memory::new(); 199 | let mut registers: CPU = CPU::new(); 200 | let mut vars: Vars = Vars::new(); 201 | 202 | vars.set_string("x".to_string(), "", &mut memory); 203 | registers.lxstring = "hello".to_string(); 204 | 205 | let statement: &str = "copy x = lxstring"; 206 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 207 | 208 | copy(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 209 | let t = vars.get_type("x".to_string()).unwrap(); 210 | 211 | assert_eq!(memory.yeild_string(t.location), "hello".to_string()) 212 | } 213 | 214 | #[test] 215 | fn copy_var_var_int() { 216 | let mut memory: Memory = Memory::new(); 217 | let mut registers: CPU = CPU::new(); 218 | let mut vars: Vars = Vars::new(); 219 | 220 | vars.set_int("x".to_string(), "1", &mut memory).unwrap(); 221 | vars.set_int("y".to_string(), "0", &mut memory).unwrap(); 222 | 223 | let statement: &str = "copy y = x"; 224 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 225 | 226 | copy(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 227 | 228 | let t = vars.get_type("y".to_string()).unwrap(); 229 | assert_eq!(memory.yeild_i32(t.location), 1) 230 | } 231 | 232 | #[test] 233 | fn copy_var_var_str() { 234 | let mut memory: Memory = Memory::new(); 235 | let mut registers: CPU = CPU::new(); 236 | let mut vars: Vars = Vars::new(); 237 | 238 | vars.set_string("x".to_string(), "hello", &mut memory); 239 | vars.set_string("y".to_string(), "", &mut memory); 240 | 241 | let statement: &str = "copy y = x"; 242 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 243 | 244 | copy(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 245 | 246 | let t = vars.get_type("y".to_string()).unwrap(); 247 | assert_eq!(memory.yeild_string(t.location), "hello".to_string()) 248 | } 249 | -------------------------------------------------------------------------------- /src/funcs/stack.rs: -------------------------------------------------------------------------------- 1 | use super::errors::ErrorKind; 2 | use super::{butterfly, errors}; 3 | use crate::types::{Type, TypeName, Vars}; 4 | use crate::{memory::Memory, CPU}; 5 | 6 | pub fn ram( 7 | memory: &mut Memory, 8 | vars: &mut Vars, 9 | registers: &mut CPU, 10 | cmd: Vec<&str>, 11 | statement: &str, 12 | ) -> Result<(), ErrorKind> { 13 | // ram 10 14 | // ram lx/rv 10 15 | // ram lx/rv prev 16 | // ram lx 17 | // ram rv 18 | // ram string/lxstring = 'hello world' 19 | // ram :str = 'hello world' 20 | // ram :int = 10 21 | // ram :vec :int = [1,2,3] 22 | // ram :vec :str = ['meow', 'dog'] 23 | 24 | if cmd.len() < 2 { 25 | return Err(ErrorKind::ArgErr); 26 | } 27 | 28 | match cmd[1] { 29 | "lx" => { 30 | if cmd.len() == 2 { 31 | // ram lx 32 | vars.set_int_to_stack(memory, registers.lx.to_string().trim())? 33 | } else if cmd.len() == 3 { 34 | // ram lx prev 35 | if cmd[2] == "prev" { 36 | registers.lx = memory.get_int_from_stack()?; 37 | let sub = memory.stack.len().saturating_sub(4); 38 | memory.stack.truncate(sub); 39 | } else { 40 | registers.lx = errors::parse_int(cmd[2])? 41 | } 42 | } 43 | } 44 | "rv" => { 45 | if cmd.len() == 2 { 46 | // ram rv 47 | vars.set_int_to_stack(memory, registers.rv.to_string().trim())?; 48 | } else if cmd.len() == 3 { 49 | if cmd[2] == "prev" { 50 | // ram lx prev 51 | registers.rv = memory.get_int_from_stack()?; 52 | let sub = memory.stack.len().saturating_sub(4); 53 | memory.stack.truncate(sub); 54 | } else { 55 | registers.rv = errors::parse_int(cmd[2])? 56 | } 57 | } 58 | } 59 | "string" => { 60 | // ram string = 'hello' 61 | let exp = statement.split('=').collect::>()[1].trim(); 62 | let _ = &exp[1..exp.len() - 1].clone_into(&mut registers.string); 63 | } 64 | "lxstring" => { 65 | let exp = statement.split('=').collect::>()[1].trim(); 66 | let _ = &exp[1..exp.len() - 1].clone_into(&mut registers.lxstring); 67 | } 68 | _ => { 69 | if cmd.len() == 3 && cmd[2] == ":map" { 70 | return butterfly::map(memory, vars, cmd.clone(), statement); 71 | } 72 | if cmd.len() > 3 { 73 | if &cmd[2][0..1] == ":" { 74 | let name = cmd[1]; 75 | let exp = statement.split('=').collect::>()[1].trim(); 76 | match &cmd[2][1..cmd[2].len()] { 77 | "str" => vars.set_string(name.to_string(), &exp[1..exp.len() - 1], memory), 78 | "int" => vars.set_int(name.to_string(), exp, memory)?, 79 | "float" => vars.set_float(name.to_string(), exp, memory)?, 80 | "vec" => { 81 | if &cmd[3][0..1] == ":" { 82 | match &cmd[3][1..cmd[3].len()] { 83 | "str" => vars.set_str_vec(name.to_string(), exp, memory), 84 | "int" => vars.set_int_vec(name.to_string(), exp, memory)?, 85 | _ => return Err(ErrorKind::ArgErr), 86 | } 87 | } else { 88 | return Err(ErrorKind::ArgErr); 89 | } 90 | } 91 | _ => return Err(ErrorKind::ArgErr), 92 | } 93 | } else { 94 | return Err(ErrorKind::ArgErr); 95 | } 96 | } else { 97 | // try to parse cmd[1] as int 98 | vars.set_int_to_stack(memory, cmd[1])? 99 | } 100 | } 101 | } 102 | Ok(()) 103 | } 104 | 105 | pub fn copy( 106 | memory: &mut Memory, 107 | vars: &mut Vars, 108 | registers: &mut CPU, 109 | cmd: Vec<&str>, 110 | statement: &str, 111 | ) -> Result<(), ErrorKind> { 112 | if cmd.len() < 4 || cmd[2] != "=" { 113 | return Err(ErrorKind::ArgErr); 114 | } 115 | 116 | let src: &str = statement.split('=').collect::>()[1].trim(); 117 | let dest: &str = cmd[1]; 118 | 119 | match dest { 120 | "lx" => match src { 121 | "rv" => registers.rv = registers.lx, 122 | _ => { 123 | let t = vars.get_type(src.to_string())?; 124 | let var: i32; 125 | if t.name == TypeName::I32 { 126 | var = memory.yeild_i32(t.location); 127 | registers.lx = var 128 | } else { 129 | return Err(ErrorKind::ExpectedInt(src.to_string())); 130 | } 131 | } 132 | }, 133 | 134 | "rv" => match src { 135 | "lx" => registers.lx = registers.rv, 136 | _ => { 137 | let t = vars.get_type(src.to_string())?; 138 | let var: i32; 139 | if t.name == TypeName::I32 { 140 | var = memory.yeild_i32(t.location); 141 | registers.rv = var 142 | } else { 143 | return Err(ErrorKind::ExpectedInt(src.to_string())); 144 | } 145 | } 146 | }, 147 | 148 | "string" => match src { 149 | "lxstring" => registers.string = registers.lxstring.clone(), 150 | _ => { 151 | let t = vars.get_type(src.to_string())?; 152 | let var: String; 153 | if t.name == TypeName::String { 154 | var = memory.yeild_string(t.location); 155 | registers.string = var 156 | } else { 157 | return Err(ErrorKind::ExpectedStr(src.to_string())); 158 | } 159 | } 160 | }, 161 | 162 | "lxstring" => match src { 163 | "string" => registers.lxstring = registers.string.clone(), 164 | _ => { 165 | let t = vars.get_type(src.to_string())?; 166 | let var: String; 167 | if t.name == TypeName::String { 168 | var = memory.yeild_string(t.location); 169 | registers.lxstring = var 170 | } else { 171 | return Err(ErrorKind::ExpectedStr(src.to_string())); 172 | } 173 | } 174 | }, 175 | 176 | _ => { 177 | match src { 178 | "lx" => { 179 | let t: Type = vars.get_type(dest.to_string())?; 180 | if t.name == TypeName::I32 { 181 | memory.stack_mod(t.location, ®isters.lx.to_be_bytes()) 182 | } else { 183 | return Err(ErrorKind::ExpectedInt(dest.to_string())); 184 | } 185 | } 186 | "rv" => { 187 | let t: Type = vars.get_type(dest.to_string())?; 188 | if t.name == TypeName::I32 { 189 | memory.stack_mod(t.location, ®isters.rv.to_be_bytes()) 190 | } else { 191 | return Err(ErrorKind::ExpectedInt(dest.to_string())); 192 | } 193 | } 194 | "string" => { 195 | let t: Type = vars.get_type(dest.to_string())?; 196 | if t.name == TypeName::String { 197 | // gc 198 | let addr: [u8; 4] = memory 199 | .load(t.location) 200 | .try_into() 201 | .expect("Error converting location to addr"); 202 | memory.free(u32::from_be_bytes(addr)); 203 | // end gc 204 | vars.set_string(dest.to_string(), ®isters.string, memory) 205 | } else { 206 | return Err(ErrorKind::ExpectedStr(dest.to_string())); 207 | } 208 | } 209 | "lxstring" => { 210 | let t: Type = vars.get_type(dest.to_string())?; 211 | if t.name == TypeName::String { 212 | // gc 213 | let addr: [u8; 4] = memory 214 | .load(t.location) 215 | .try_into() 216 | .expect("Error converting location to addr"); 217 | memory.free(u32::from_be_bytes(addr)); 218 | // end gc 219 | vars.set_string(dest.to_string(), ®isters.lxstring, memory) 220 | } else { 221 | return Err(ErrorKind::ExpectedStr(dest.to_string())); 222 | } 223 | } 224 | _ => vars.copy(src, dest, memory)?, 225 | } 226 | } 227 | } 228 | Ok(()) 229 | } 230 | 231 | pub fn drop( 232 | memory: &mut Memory, 233 | vars: &mut Vars, 234 | cmd: Vec<&str>, 235 | ) -> Result<(), ErrorKind> { 236 | if cmd.len() < 2 { 237 | return Err(ErrorKind::ArgErr) 238 | } 239 | vars.drop(cmd[1].to_string(), memory) 240 | } -------------------------------------------------------------------------------- /src/tests/std/string.rs: -------------------------------------------------------------------------------- 1 | use crate::funcs::stdf::string::*; 2 | use crate::{memory::Memory, types::Vars, CPU}; 3 | 4 | // split string > "" = var 5 | // split lxstring > " " = var 6 | // split var > "\n" = var 7 | 8 | // join var > "" = string 9 | // join var > " " = lxstring 10 | // join var > "\n" = var 11 | 12 | // concat string lxstring 13 | // concat string var 14 | 15 | // concat lxstring string 16 | // concat lxstring var 17 | 18 | // concat var string 19 | // concat var var 20 | 21 | // trim string 22 | // trim lxstring 23 | // trim var 24 | 25 | #[test] 26 | pub fn trim_string() { 27 | let mut memory: Memory = Memory::new(); 28 | let mut registers: CPU = CPU::new(); 29 | let mut vars: Vars = Vars::new(); 30 | 31 | registers.string = " hello".to_string(); 32 | let statement = "trim string"; 33 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 34 | 35 | trim(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 36 | assert_eq!(registers.string, "hello".to_string()); 37 | } 38 | 39 | #[test] 40 | pub fn trim_lxstring() { 41 | let mut memory: Memory = Memory::new(); 42 | let mut registers: CPU = CPU::new(); 43 | let mut vars: Vars = Vars::new(); 44 | 45 | registers.lxstring = " hello".to_string(); 46 | let statement = "trim lxstring"; 47 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 48 | 49 | trim(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 50 | assert_eq!(registers.lxstring, "hello".to_string()); 51 | } 52 | 53 | #[test] 54 | pub fn trim_var() { 55 | let mut memory: Memory = Memory::new(); 56 | let mut registers: CPU = CPU::new(); 57 | let mut vars: Vars = Vars::new(); 58 | 59 | vars.set_string("x".to_string(), " hello", &mut memory); 60 | let statement = "trim x"; 61 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 62 | 63 | trim(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 64 | let t = vars.get_type("x".to_string()).unwrap(); 65 | assert_eq!(memory.yeild_string(t.location), "hello".to_string()); 66 | } 67 | 68 | 69 | 70 | #[test] 71 | pub fn split_string() { 72 | let mut memory: Memory = Memory::new(); 73 | let mut registers: CPU = CPU::new(); 74 | let mut vars: Vars = Vars::new(); 75 | 76 | registers.string = "he,llo".to_string(); 77 | vars.set_str_vec("x".to_string(), "['']", &mut memory); 78 | let statement = "split string > \",\" = x"; 79 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 80 | 81 | split(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 82 | let t = vars.get_type("x".to_string()).unwrap(); 83 | assert_eq!(memory.yeild_str_vec(t.location), ["he", "llo"]); 84 | } 85 | 86 | 87 | #[test] 88 | pub fn split_string_char() { 89 | let mut memory: Memory = Memory::new(); 90 | let mut registers: CPU = CPU::new(); 91 | let mut vars: Vars = Vars::new(); 92 | 93 | registers.string = "hello".to_string(); 94 | vars.set_str_vec("x".to_string(), "['']", &mut memory); 95 | let statement = "split string > \"\" = x"; 96 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 97 | 98 | split(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 99 | let t = vars.get_type("x".to_string()).unwrap(); 100 | assert_eq!(memory.yeild_str_vec(t.location).len(), 5); 101 | } 102 | 103 | #[test] 104 | pub fn split_lxstring() { 105 | let mut memory: Memory = Memory::new(); 106 | let mut registers: CPU = CPU::new(); 107 | let mut vars: Vars = Vars::new(); 108 | 109 | registers.lxstring = "hello world".to_string(); 110 | vars.set_str_vec("x".to_string(), "['']", &mut memory); 111 | let statement = "split lxstring > \" \" = x"; 112 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 113 | 114 | split(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 115 | let t = vars.get_type("x".to_string()).unwrap(); 116 | assert_eq!(memory.yeild_str_vec(t.location), ["hello", "world"]); 117 | } 118 | 119 | #[test] 120 | pub fn split_var() { 121 | let mut memory: Memory = Memory::new(); 122 | let mut registers: CPU = CPU::new(); 123 | let mut vars: Vars = Vars::new(); 124 | 125 | let statement = "split str > \"\n\" = x"; 126 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 127 | vars.set_string("str".to_string(), "hello\nworld", &mut memory); 128 | vars.set_str_vec("x".to_string(), "['']", &mut memory); 129 | 130 | split(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 131 | let t = vars.get_type("x".to_string()).unwrap(); 132 | assert_eq!(memory.yeild_str_vec(t.location), ["hello", "world"]); 133 | } 134 | 135 | // join var > "" = string 136 | // join var > " " = lxstring 137 | // join var > "\n" = var 138 | 139 | #[test] 140 | fn join_string() { 141 | let mut memory: Memory = Memory::new(); 142 | let mut registers: CPU = CPU::new(); 143 | let mut vars: Vars = Vars::new(); 144 | 145 | vars.set_str_vec("x".to_string(), "['hello', 'world']", &mut memory); 146 | let statement = "join x > \"\" = string"; 147 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 148 | join(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 149 | assert_eq!(registers.string, "helloworld".to_string()); 150 | } 151 | 152 | #[test] 153 | fn join_lxstring() { 154 | let mut memory: Memory = Memory::new(); 155 | let mut registers: CPU = CPU::new(); 156 | let mut vars: Vars = Vars::new(); 157 | 158 | vars.set_str_vec("x".to_string(), "['hello', 'world']", &mut memory); 159 | let statement = "join x > \" \" = lxstring"; 160 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 161 | join(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 162 | assert_eq!(registers.string, "hello world".to_string()); 163 | } 164 | 165 | #[test] 166 | fn join_var() { 167 | let mut memory: Memory = Memory::new(); 168 | let mut registers: CPU = CPU::new(); 169 | let mut vars: Vars = Vars::new(); 170 | 171 | vars.set_str_vec("x".to_string(), "['hello', 'world']", &mut memory); 172 | vars.set_string("y".to_string(), "''", &mut memory); 173 | let statement = "join x > \"\n\" = y"; 174 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 175 | join(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 176 | let t = vars.get_type("y".to_string()).unwrap(); 177 | assert_eq!(memory.yeild_string(t.location), "hello\nworld".to_string()); 178 | } 179 | 180 | #[test] 181 | pub fn concat_string_lxstring() { 182 | let mut memory: Memory = Memory::new(); 183 | let mut registers: CPU = CPU::new(); 184 | let mut vars: Vars = Vars::new(); 185 | 186 | registers.string = "hello ".to_string(); 187 | registers.lxstring = "world".to_string(); 188 | let statement = "concat string lxstring"; 189 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 190 | 191 | concat(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 192 | assert_eq!(registers.string, "hello world".to_string()) 193 | } 194 | 195 | pub fn concat_lxstring_string() { 196 | let mut memory: Memory = Memory::new(); 197 | let mut registers: CPU = CPU::new(); 198 | let mut vars: Vars = Vars::new(); 199 | 200 | registers.lxstring = "hello ".to_string(); 201 | registers.string = "world".to_string(); 202 | let statement = "concat lxstring string"; 203 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 204 | 205 | concat(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 206 | assert_eq!(registers.string, "hello world".to_string()) 207 | } 208 | 209 | pub fn concat_var_string() { 210 | let mut memory: Memory = Memory::new(); 211 | let mut registers: CPU = CPU::new(); 212 | let mut vars: Vars = Vars::new(); 213 | 214 | vars.set_string("x".to_string(), "hello ", &mut memory); 215 | registers.string = "world".to_string(); 216 | let statement = "concat x string"; 217 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 218 | 219 | concat(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 220 | assert_eq!(registers.string, "hello world".to_string()) 221 | } 222 | 223 | #[test] 224 | pub fn concat_string_var() { 225 | let mut memory: Memory = Memory::new(); 226 | let mut registers: CPU = CPU::new(); 227 | let mut vars: Vars = Vars::new(); 228 | 229 | vars.set_string("x".to_string(), "world", &mut memory); 230 | registers.string = "hello ".to_string(); 231 | let statement = "concat string x"; 232 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 233 | 234 | concat(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 235 | assert_eq!(registers.string, "hello world".to_string()) 236 | } 237 | 238 | #[test] 239 | pub fn concat_lxstring_var() { 240 | let mut memory: Memory = Memory::new(); 241 | let mut registers: CPU = CPU::new(); 242 | let mut vars: Vars = Vars::new(); 243 | 244 | vars.set_string("x".to_string(), "world", &mut memory); 245 | registers.lxstring = "hello ".to_string(); 246 | let statement = "concat lxstring x"; 247 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 248 | 249 | concat(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 250 | assert_eq!(registers.string, "hello world".to_string()) 251 | } 252 | 253 | #[test] 254 | pub fn concat_var_var() { 255 | let mut memory: Memory = Memory::new(); 256 | let mut registers: CPU = CPU::new(); 257 | let mut vars: Vars = Vars::new(); 258 | 259 | vars.set_string("x".to_string(), "hello ", &mut memory); 260 | vars.set_string("y".to_string(), "world", &mut memory); 261 | let statement = "concat x y"; 262 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 263 | 264 | concat(&mut memory, &mut vars, &mut registers, cmd).unwrap(); 265 | assert_eq!(registers.string, "hello world".to_string()) 266 | } 267 | -------------------------------------------------------------------------------- /src/memory.rs: -------------------------------------------------------------------------------- 1 | use rand::Rng; 2 | use std::collections::HashMap; 3 | 4 | use crate::funcs::errors::ErrorKind; 5 | 6 | #[derive(Debug)] 7 | pub struct Memory { 8 | pub stack: Vec, 9 | pub heap: HashMap>, 10 | } 11 | 12 | #[derive(Clone, Debug, Copy, PartialEq, Eq)] 13 | pub struct Location { 14 | pub start: usize, 15 | pub size: usize, 16 | } 17 | 18 | impl Memory { 19 | pub fn new() -> Self { 20 | Self { 21 | stack: vec![], 22 | heap: HashMap::from([(0, vec![0, 0, 0, 0])]), 23 | } 24 | } 25 | 26 | // stack operations 27 | 28 | pub fn pop_stack(&mut self) { 29 | let sub = self.stack.len().saturating_sub(4); 30 | self.stack.truncate(sub); 31 | } 32 | 33 | pub fn reset_stack(&mut self) { 34 | self.stack = vec![]; 35 | } 36 | 37 | pub fn load(&mut self, location: Location) -> &[u8] { 38 | &self.stack[location.start..location.start + location.size] as _ 39 | } 40 | 41 | pub fn store(&mut self, val: &[u8]) -> Location { 42 | let address = self.stack.len(); 43 | for byte in val { 44 | self.stack.push(*byte); 45 | } 46 | 47 | Location { 48 | start: address, 49 | size: val.len(), 50 | } 51 | } 52 | 53 | pub fn stack_mod(&mut self, location: Location, data: &[u8]) { 54 | if data.len() != location.size { 55 | panic!("Illegal memory modification"); 56 | } 57 | self.stack.splice( 58 | location.start..location.start + location.size, 59 | data.iter().cloned(), 60 | ); 61 | } 62 | 63 | // heap operations 64 | 65 | pub fn malloc(&mut self, bytes: &[u8]) -> u32 { 66 | let addr_bytes = rand::thread_rng().gen::<[u8; 4]>(); 67 | let addr: u32 = u32::from_be_bytes(addr_bytes); 68 | self.heap.insert(addr, bytes.to_vec()); 69 | addr 70 | } 71 | 72 | pub fn free(&mut self, addr: u32) { 73 | self.heap.remove(&addr); 74 | } 75 | 76 | pub fn heap_load(&mut self, addr: u32) -> Vec { 77 | let bytes: Vec; 78 | match self.heap.get(&addr) { 79 | Some(data) => bytes = data.to_vec(), 80 | _ => panic!("Illegal heap pointer"), 81 | } 82 | bytes 83 | } 84 | 85 | pub fn heap_mod(&mut self, addr: u32, data: &[u8]) { 86 | self.free(addr); 87 | self.heap.insert(addr, data.to_vec()); 88 | } 89 | 90 | // stack yeilds 91 | 92 | // ints 93 | 94 | pub fn get_int_from_stack(&mut self) -> Result { 95 | if self.stack.len() < 4 { 96 | return Err(ErrorKind::StackLen); 97 | } 98 | let location = Location { 99 | start: self.stack.len() - 4, 100 | size: 4, 101 | }; 102 | let bytes = self.load(location); 103 | let num: i32 = i32::from_be_bytes(bytes.try_into().expect("invalid i32 len")); 104 | Ok(num) 105 | } 106 | 107 | pub fn set_int_to_stack(&mut self, value: i32) { 108 | let bytes = value.to_be_bytes(); 109 | self.store(&bytes); 110 | } 111 | 112 | pub fn yeild_i32(&mut self, location: Location) -> i32 { 113 | let bytes = self.load(location); 114 | let num: i32 = i32::from_be_bytes(bytes.try_into().expect("invalid i32 len")); 115 | num 116 | } 117 | 118 | pub fn yeild_float(&mut self, location: Location) -> f32 { 119 | let addr_bytes = self.load(location); 120 | let heap_addr = u32::from_be_bytes(addr_bytes.try_into().expect("Invalid head addr")); 121 | let f32_bytes = self.heap_load(heap_addr); 122 | let float = f32::from_be_bytes(f32_bytes.try_into().expect("Incorrect F32 format")); 123 | float 124 | } 125 | 126 | // heap yeilds 127 | 128 | // strings 129 | pub fn yeild_string(&mut self, location: Location) -> String { 130 | let addr_bytes = self.load(location); 131 | let heap_addr = u32::from_be_bytes(addr_bytes.try_into().expect("invalid heap addr len")); 132 | let str_bytes = self.heap_load(heap_addr); 133 | let final_str = String::from_utf8_lossy(&str_bytes); 134 | final_str.into_owned() 135 | } 136 | 137 | pub fn yeild_int_vec(&mut self, location: Location) -> Vec { 138 | let addr_bytes = self.load(location); 139 | let heap_addr = u32::from_be_bytes( 140 | addr_bytes 141 | .try_into() 142 | .expect("invalid vec int heap addr len"), 143 | ); 144 | 145 | let mut final_vec: Vec = vec![]; 146 | let vec_bytes = self.heap_load(heap_addr); 147 | for num_bytes in vec_bytes.chunks(4) { 148 | let num = i32::from_be_bytes(num_bytes.try_into().expect("Invalid vec int chunk len")); 149 | final_vec.push(num); 150 | } 151 | final_vec 152 | } 153 | 154 | pub fn yeild_str_vec(&mut self, location: Location) -> Vec { 155 | let addr_bytes = self.load(location); 156 | let heap_addr = u32::from_be_bytes( 157 | addr_bytes 158 | .try_into() 159 | .expect("invalid vec str heap addr len"), 160 | ); 161 | let mut final_vec: Vec = vec![]; 162 | let vec_addr_bytes = self.heap_load(heap_addr); 163 | for addr_bytes in vec_addr_bytes.chunks(4) { 164 | let str_addr = 165 | u32::from_be_bytes(addr_bytes.try_into().expect("invalid vec str heap str len")); 166 | let str_bytes = self.heap_load(str_addr); 167 | let final_str = String::from_utf8_lossy(&str_bytes); 168 | final_vec.push(final_str.into_owned()); 169 | } 170 | final_vec 171 | } 172 | } 173 | 174 | // vec ops 175 | 176 | impl Memory { 177 | // push 178 | 179 | pub fn vec_int_push(&mut self, heap_bytes: &[u8], value: [u8; 4]) { 180 | let heap_value = &mut *self 181 | .heap 182 | .get_mut(&u32::from_be_bytes( 183 | heap_bytes.try_into().expect("Illegal heap pointer"), 184 | )) 185 | .expect("Illegal heap pointer"); 186 | 187 | for byte in value { 188 | heap_value.push(byte) 189 | } 190 | } 191 | 192 | pub fn vec_str_push(&mut self, heap_bytes: &[u8], new_str_addr: &[u8; 4]) { 193 | let heap_value = &mut *self 194 | .heap 195 | .get_mut(&u32::from_be_bytes( 196 | heap_bytes.try_into().expect("Illegal heap pointer"), 197 | )) 198 | .expect("Illegal heap pointer"); 199 | 200 | for byte in new_str_addr { 201 | heap_value.push(*byte) 202 | } 203 | } 204 | 205 | // modify using index 206 | 207 | pub fn mod_vec_int(&mut self, heap_bytes: &[u8], idx: usize, value: &[u8]) -> Result<(), ()> { 208 | let heap_value = &mut *self 209 | .heap 210 | .get_mut(&u32::from_be_bytes( 211 | heap_bytes.try_into().expect("Illegal heap pointer"), 212 | )) 213 | .expect("Illegal heap pointer"); 214 | 215 | if idx < heap_value.len() / 4 { 216 | heap_value.splice(idx * 4..idx * 4 + 4, value.to_vec()); 217 | } else { 218 | return Err(()); 219 | } 220 | Ok(()) 221 | } 222 | 223 | pub fn mod_vec_str( 224 | &mut self, 225 | heap_bytes: &[u8], 226 | idx: usize, 227 | str_addr: &[u8], 228 | ) -> Result<(), ()> { 229 | let heap_value = &mut *self 230 | .heap 231 | .get_mut(&u32::from_be_bytes( 232 | heap_bytes.try_into().expect("Illegal heap pointer"), 233 | )) 234 | .expect("Illegal heap pointer"); 235 | 236 | if idx < heap_value.len() / 4 { 237 | let str_addr_bytes = &heap_value[idx * 4..idx * 4 + 4]; 238 | let old_str_addr = 239 | u32::from_be_bytes(str_addr_bytes.try_into().expect("invalid heap addr")); 240 | heap_value.splice(idx * 4..idx * 4 + 4, str_addr.to_vec()); 241 | self.free(old_str_addr); 242 | } else { 243 | return Err(()); 244 | } 245 | Ok(()) 246 | } 247 | 248 | // pop 249 | 250 | pub fn pop_vec_int(&mut self, heap_bytes: &[u8]) { 251 | let heap_value = &mut *self 252 | .heap 253 | .get_mut(&u32::from_be_bytes( 254 | heap_bytes.try_into().expect("Illegal heap pointer"), 255 | )) 256 | .expect("Illegal heap pointer"); 257 | 258 | let sub = heap_value.len().saturating_sub(4); 259 | heap_value.truncate(sub); 260 | } 261 | 262 | pub fn pop_vec_str(&mut self, heap_bytes: &[u8]) { 263 | let heap_value = &mut *self 264 | .heap 265 | .get_mut(&u32::from_be_bytes( 266 | heap_bytes.try_into().expect("Illegal heap pointer"), 267 | )) 268 | .expect("Illegal heap pointer"); 269 | 270 | let str_addr_bytes = heap_value 271 | .drain(heap_value.len() - 4..heap_value.len()) 272 | .collect::>(); 273 | let str_addr = u32::from_be_bytes(str_addr_bytes.try_into().expect("invalid heap addr")); 274 | self.free(str_addr); 275 | } 276 | 277 | // shift 278 | 279 | pub fn shift_vec_int(&mut self, heap_bytes: &[u8]) { 280 | let heap_value = &mut *self.heap.get_mut( 281 | &u32::from_be_bytes(heap_bytes.try_into().unwrap()) 282 | ).unwrap(); 283 | let old_int: Vec = heap_value.drain(0..4).collect(); 284 | self.stack.extend(old_int); 285 | } 286 | 287 | pub fn shift_vec_str(&mut self, heap_bytes: &[u8]) { 288 | let heap_value = &mut *self.heap.get_mut( 289 | &u32::from_be_bytes(heap_bytes.try_into().unwrap()) 290 | ).unwrap(); 291 | let old_str_addr = heap_value.drain(0..4).collect::>(); 292 | self.free(u32::from_be_bytes(old_str_addr.try_into().unwrap())); 293 | } 294 | } 295 | -------------------------------------------------------------------------------- /src/funcs/operations/cmp.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | funcs::errors::ErrorKind, 3 | memory::Memory, 4 | types::{TypeName, Vars}, 5 | CPU, 6 | }; 7 | 8 | pub fn cmp( 9 | memory: &mut Memory, 10 | vars: &mut Vars, 11 | registers: &mut CPU, 12 | cmd: Vec<&str>, 13 | ) -> Result<(), ErrorKind> { 14 | if cmd.len() == 1 { 15 | let num_1 = memory.get_int_from_stack()?; 16 | let sub = memory.stack.len().saturating_sub(4); 17 | memory.stack.truncate(sub); 18 | 19 | let num_2 = memory.get_int_from_stack()?; 20 | let sub = memory.stack.len().saturating_sub(4); 21 | memory.stack.truncate(sub); 22 | let diff = num_2 - num_1; 23 | if diff == 0 { 24 | memory.set_int_to_stack(0); 25 | } else if diff > 0 { 26 | memory.set_int_to_stack(1); 27 | } else if diff < 0 { 28 | memory.set_int_to_stack(-1); 29 | } 30 | Ok(()) 31 | } else if cmd.len() == 3 { 32 | match cmd[1] { 33 | "lx" => { 34 | if cmd[2] == "rv" { 35 | let diff = registers.lx - registers.rv; 36 | if diff == 0 { 37 | memory.set_int_to_stack(0) 38 | } else if diff > 0 { 39 | memory.set_int_to_stack(1) 40 | } else if diff < 0 { 41 | memory.set_int_to_stack(-1) 42 | } 43 | } else { 44 | let var = vars.get_type(cmd[2].to_string())?; 45 | if var.name == TypeName::I32 { 46 | let value = memory.yeild_i32(var.location); 47 | let diff = registers.lx - value; 48 | if diff == 0 { 49 | memory.set_int_to_stack(0) 50 | } else if diff > 0 { 51 | memory.set_int_to_stack(1) 52 | } else if diff < 0 { 53 | memory.set_int_to_stack(-1) 54 | } 55 | } else { 56 | return Err(ErrorKind::Casting { 57 | src: cmd[2].to_string(), 58 | dest: "lx".to_string(), 59 | }); 60 | } 61 | } 62 | Ok(()) 63 | } 64 | "rv" => { 65 | if cmd[2] == "lx" { 66 | let diff = registers.rv - registers.lx; 67 | if diff == 0 { 68 | memory.set_int_to_stack(0) 69 | } else if diff > 0 { 70 | memory.set_int_to_stack(1) 71 | } else if diff < 0 { 72 | memory.set_int_to_stack(-1) 73 | } 74 | } else { 75 | let var = vars.get_type(cmd[2].to_string())?; 76 | if var.name == TypeName::I32 { 77 | let value = memory.yeild_i32(var.location); 78 | let diff = registers.rv - value; 79 | if diff == 0 { 80 | memory.set_int_to_stack(0) 81 | } else if diff > 0 { 82 | memory.set_int_to_stack(1) 83 | } else if diff < 0 { 84 | memory.set_int_to_stack(-1) 85 | } 86 | } else { 87 | return Err(ErrorKind::Casting { 88 | src: cmd[2].to_string(), 89 | dest: "lx".to_string(), 90 | }); 91 | } 92 | } 93 | Ok(()) 94 | } 95 | "string" => { 96 | if cmd[2] == "lxstring" { 97 | if registers.string == registers.lxstring { 98 | memory.set_int_to_stack(0) 99 | } else { 100 | memory.set_int_to_stack(-1) 101 | } 102 | } else { 103 | let var = vars.get_type(cmd[2].to_string())?; 104 | if var.name == TypeName::String { 105 | if registers.string == memory.yeild_string(var.location) { 106 | memory.set_int_to_stack(0) 107 | } else { 108 | memory.set_int_to_stack(-1) 109 | } 110 | } else { 111 | return Err(ErrorKind::Casting { 112 | src: cmd[2].to_string(), 113 | dest: "string".to_string(), 114 | }); 115 | } 116 | } 117 | Ok(()) 118 | } 119 | "lxstring" => { 120 | if cmd[2] == "string" { 121 | if registers.string == registers.lxstring { 122 | memory.set_int_to_stack(0) 123 | } else { 124 | memory.set_int_to_stack(-1) 125 | } 126 | } else { 127 | let var = vars.get_type(cmd[2].to_string())?; 128 | if var.name == TypeName::String { 129 | if registers.lxstring == memory.yeild_string(var.location) { 130 | memory.set_int_to_stack(0) 131 | } else { 132 | memory.set_int_to_stack(-1) 133 | } 134 | } else { 135 | return Err(ErrorKind::Casting { 136 | src: cmd[2].to_string(), 137 | dest: "lxstring".to_string(), 138 | }); 139 | } 140 | } 141 | Ok(()) 142 | } 143 | _ => match cmd[2] { 144 | "lx" => { 145 | let var_1 = vars.get_type(cmd[1].to_string())?; 146 | if var_1.name == TypeName::I32 { 147 | let value = memory.yeild_i32(var_1.location); 148 | let diff = value - registers.lx; 149 | if diff == 0 { 150 | memory.set_int_to_stack(0) 151 | } else if diff > 0 { 152 | memory.set_int_to_stack(1) 153 | } else if diff < 0 { 154 | memory.set_int_to_stack(-1) 155 | } 156 | } else { 157 | return Err(ErrorKind::Casting { 158 | src: "lx".to_string(), 159 | dest: cmd[1].to_string(), 160 | }); 161 | } 162 | Ok(()) 163 | } 164 | "rv" => { 165 | let var_1 = vars.get_type(cmd[1].to_string())?; 166 | if var_1.name == TypeName::I32 { 167 | let value = memory.yeild_i32(var_1.location); 168 | let diff = value - registers.rv; 169 | if diff == 0 { 170 | memory.set_int_to_stack(0) 171 | } else if diff > 0 { 172 | memory.set_int_to_stack(1) 173 | } else if diff < 0 { 174 | memory.set_int_to_stack(-1) 175 | } 176 | } else { 177 | return Err(ErrorKind::Casting { 178 | src: "rv".to_string(), 179 | dest: cmd[1].to_string(), 180 | }); 181 | } 182 | Ok(()) 183 | } 184 | "string" => { 185 | let var_1 = vars.get_type(cmd[1].to_string())?; 186 | if var_1.name == TypeName::String { 187 | if registers.string == memory.yeild_string(var_1.location) { 188 | memory.set_int_to_stack(0) 189 | } else { 190 | memory.set_int_to_stack(-1) 191 | } 192 | } else { 193 | return Err(ErrorKind::Casting { 194 | src: "string".to_string(), 195 | dest: cmd[1].to_string(), 196 | }); 197 | } 198 | Ok(()) 199 | } 200 | "lxstring" => { 201 | let var_1 = vars.get_type(cmd[1].to_string())?; 202 | if var_1.name == TypeName::String { 203 | if registers.lxstring == memory.yeild_string(var_1.location) { 204 | memory.set_int_to_stack(0) 205 | } else { 206 | memory.set_int_to_stack(-1) 207 | } 208 | } else { 209 | return Err(ErrorKind::Casting { 210 | src: "string".to_string(), 211 | dest: cmd[1].to_string(), 212 | }); 213 | } 214 | Ok(()) 215 | } 216 | _ => { 217 | let var_1 = vars.get_type(cmd[1].to_string())?; 218 | let var_2 = vars.get_type(cmd[2].to_string())?; 219 | 220 | if var_1.name == var_2.name { 221 | match var_1.name { 222 | TypeName::I32 => { 223 | let num_1 = memory.yeild_i32(var_1.location); 224 | let num_2 = memory.yeild_i32(var_2.location); 225 | let diff = num_1 - num_2; 226 | if diff == 0 { 227 | memory.set_int_to_stack(0) 228 | } else if diff > 0 { 229 | memory.set_int_to_stack(1) 230 | } else if diff < 0 { 231 | memory.set_int_to_stack(-1) 232 | } 233 | } 234 | TypeName::String => { 235 | let str_1 = memory.yeild_string(var_1.location); 236 | let str_2 = memory.yeild_string(var_2.location); 237 | 238 | if str_1 == str_2 { 239 | memory.set_int_to_stack(0) 240 | } else { 241 | memory.set_int_to_stack(-1) 242 | } 243 | } 244 | _ => todo!("Implement for other types"), 245 | } 246 | Ok(()) 247 | } else { 248 | Err(ErrorKind::Casting { 249 | src: cmd[1].to_string(), 250 | dest: cmd[2].to_string(), 251 | }) 252 | } 253 | } 254 | }, 255 | } 256 | } else { 257 | Err(ErrorKind::ArgErr) 258 | } 259 | } 260 | -------------------------------------------------------------------------------- /src/tests/stack/vec.rs: -------------------------------------------------------------------------------- 1 | use crate::funcs::vec; 2 | use crate::{memory::Memory, types::Vars, CPU}; 3 | 4 | // vec x pop 5 | // vec x shift 6 | // vec x push y 7 | // vec x len 8 | // vec y = x[1] 9 | // vec x[1] = y 10 | 11 | #[test] 12 | fn vec_int_shift() { 13 | let mut memory: Memory = Memory::new(); 14 | let mut registers: CPU = CPU::new(); 15 | let mut vars: Vars = Vars::new(); 16 | vars.set_int_vec("x".to_string(), "[1,2]", &mut memory).unwrap(); 17 | let statement = "vec x shift"; 18 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 19 | vec::vec(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 20 | let t = vars.get_type("x".to_string()).unwrap(); 21 | assert_eq!(memory.yeild_int_vec(t.location), [2].to_vec()); 22 | } 23 | 24 | #[test] 25 | fn vec_str_shift() { 26 | let mut memory: Memory = Memory::new(); 27 | let mut registers: CPU = CPU::new(); 28 | let mut vars: Vars = Vars::new(); 29 | vars.set_str_vec("x".to_string(), "['a', 'b']", &mut memory); 30 | let statement = "vec x shift"; 31 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 32 | vec::vec(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 33 | let t = vars.get_type("x".to_string()).unwrap(); 34 | assert_eq!(memory.yeild_str_vec(t.location), ["b"].to_vec()); 35 | } 36 | 37 | #[test] 38 | fn vec_int_shift_pushes_to_stack() { 39 | let mut memory: Memory = Memory::new(); 40 | let mut registers: CPU = CPU::new(); 41 | let mut vars: Vars = Vars::new(); 42 | vars.set_int_vec("x".to_string(), "[1,2]", &mut memory).unwrap(); 43 | let statement = "vec x shift"; 44 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 45 | vec::vec(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 46 | assert_eq!(memory.get_int_from_stack().unwrap(), 1); 47 | } 48 | 49 | #[test] 50 | fn vec_str_shift_pushes_to_register_string() { 51 | let mut memory: Memory = Memory::new(); 52 | let mut registers: CPU = CPU::new(); 53 | let mut vars: Vars = Vars::new(); 54 | vars.set_str_vec("x".to_string(), "['a','b']", &mut memory); 55 | let statement = "vec x shift"; 56 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 57 | vec::vec(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 58 | assert_eq!(registers.string, "a".to_string()); 59 | } 60 | 61 | #[test] 62 | fn vec_int_push_var() { 63 | let mut memory: Memory = Memory::new(); 64 | let mut registers: CPU = CPU::new(); 65 | let mut vars: Vars = Vars::new(); 66 | 67 | vars.set_int_vec("x".to_string(), "[1, 2]", &mut memory) 68 | .unwrap(); 69 | vars.set_int("y".to_string(), "1", &mut memory).unwrap(); 70 | let statement = "vec x push y"; 71 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 72 | vec::vec(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 73 | 74 | let t = vars.get_type("x".to_string()).unwrap(); 75 | assert_eq!(memory.yeild_int_vec(t.location), [1, 2, 1].to_vec()) 76 | } 77 | 78 | #[test] 79 | fn vec_int_push_lx() { 80 | let mut memory: Memory = Memory::new(); 81 | let mut registers: CPU = CPU::new(); 82 | let mut vars: Vars = Vars::new(); 83 | 84 | vars.set_int_vec("x".to_string(), "[1, 2]", &mut memory) 85 | .unwrap(); 86 | registers.lx = 1; 87 | let statement = "vec x push lx"; 88 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 89 | vec::vec(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 90 | 91 | let t = vars.get_type("x".to_string()).unwrap(); 92 | assert_eq!(memory.yeild_int_vec(t.location), [1, 2, 1].to_vec()) 93 | } 94 | 95 | #[test] 96 | fn vec_int_push_rv() { 97 | let mut memory: Memory = Memory::new(); 98 | let mut registers: CPU = CPU::new(); 99 | let mut vars: Vars = Vars::new(); 100 | 101 | vars.set_int_vec("x".to_string(), "[1, 2]", &mut memory) 102 | .unwrap(); 103 | registers.rv = 1; 104 | let statement = "vec x push rv"; 105 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 106 | vec::vec(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 107 | 108 | let t = vars.get_type("x".to_string()).unwrap(); 109 | assert_eq!(memory.yeild_int_vec(t.location), [1, 2, 1].to_vec()) 110 | } 111 | 112 | // str push 113 | 114 | #[test] 115 | fn vec_str_push_string() { 116 | let mut memory: Memory = Memory::new(); 117 | let mut registers: CPU = CPU::new(); 118 | let mut vars: Vars = Vars::new(); 119 | 120 | vars.set_str_vec("x".to_string(), "['a']", &mut memory); 121 | registers.string = "k".to_string(); 122 | let statement = "vec x push string"; 123 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 124 | vec::vec(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 125 | 126 | let t = vars.get_type("x".to_string()).unwrap(); 127 | assert_eq!( 128 | memory.yeild_str_vec(t.location), 129 | ["a".to_string(), "k".to_string()].to_vec() 130 | ) 131 | } 132 | 133 | #[test] 134 | fn vec_str_push_lxstring() { 135 | let mut memory: Memory = Memory::new(); 136 | let mut registers: CPU = CPU::new(); 137 | let mut vars: Vars = Vars::new(); 138 | 139 | vars.set_str_vec("x".to_string(), "['a']", &mut memory); 140 | registers.lxstring = "k".to_string(); 141 | let statement = "vec x push lxstring"; 142 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 143 | vec::vec(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 144 | 145 | let t = vars.get_type("x".to_string()).unwrap(); 146 | assert_eq!( 147 | memory.yeild_str_vec(t.location), 148 | ["a".to_string(), "k".to_string()].to_vec() 149 | ) 150 | } 151 | 152 | #[test] 153 | fn vec_str_push_var() { 154 | let mut memory: Memory = Memory::new(); 155 | let mut registers: CPU = CPU::new(); 156 | let mut vars: Vars = Vars::new(); 157 | 158 | vars.set_str_vec("x".to_string(), "['a']", &mut memory); 159 | vars.set_string("y".to_string(), "k", &mut memory); 160 | let statement = "vec x push y"; 161 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 162 | vec::vec(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 163 | 164 | let t = vars.get_type("x".to_string()).unwrap(); 165 | assert_eq!( 166 | memory.yeild_str_vec(t.location), 167 | ["a".to_string(), "k".to_string()].to_vec() 168 | ) 169 | } 170 | 171 | // return by index 172 | 173 | // vec lx = x[1] 174 | // vec rv = x[1] 175 | // vec lx = x[rv] 176 | 177 | // vec string = x[1] 178 | // vec lxstring = x[1] 179 | // vec string = x[lx] 180 | 181 | // vec y = x[1] 182 | // vec lx = x[y] 183 | 184 | #[test] 185 | fn vec_get_lx_idx() { 186 | let mut memory: Memory = Memory::new(); 187 | let mut registers: CPU = CPU::new(); 188 | let mut vars: Vars = Vars::new(); 189 | 190 | vars.set_int_vec("x".to_string(), "[1, 2]", &mut memory) 191 | .unwrap(); 192 | let statement = "vec lx = x[1]"; 193 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 194 | vec::vec(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 195 | assert_eq!(registers.lx, 2); 196 | } 197 | 198 | #[test] 199 | fn vec_get_rv_idx() { 200 | let mut memory: Memory = Memory::new(); 201 | let mut registers: CPU = CPU::new(); 202 | let mut vars: Vars = Vars::new(); 203 | 204 | vars.set_int_vec("x".to_string(), "[1, 2]", &mut memory) 205 | .unwrap(); 206 | let statement = "vec rv = x[1]"; 207 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 208 | vec::vec(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 209 | assert_eq!(registers.rv, 2); 210 | } 211 | 212 | #[test] 213 | fn vec_get_lx_rv_idx() { 214 | let mut memory: Memory = Memory::new(); 215 | let mut registers: CPU = CPU::new(); 216 | let mut vars: Vars = Vars::new(); 217 | 218 | registers.rv = 1; 219 | vars.set_int_vec("x".to_string(), "[1, 2]", &mut memory) 220 | .unwrap(); 221 | let statement = "vec lx = x[rv]"; 222 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 223 | vec::vec(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 224 | assert_eq!(registers.lx, 2); 225 | } 226 | 227 | #[test] 228 | fn vec_get_string_idx() { 229 | let mut memory: Memory = Memory::new(); 230 | let mut registers: CPU = CPU::new(); 231 | let mut vars: Vars = Vars::new(); 232 | 233 | vars.set_str_vec("x".to_string(), "['ok', 'omk']", &mut memory); 234 | let statement = "vec string = x[1]"; 235 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 236 | vec::vec(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 237 | assert_eq!(registers.string, "omk".to_string()); 238 | } 239 | 240 | #[test] 241 | fn vec_get_lxstring_idx() { 242 | let mut memory: Memory = Memory::new(); 243 | let mut registers: CPU = CPU::new(); 244 | let mut vars: Vars = Vars::new(); 245 | 246 | vars.set_str_vec("x".to_string(), "['ok', 'omk']", &mut memory); 247 | let statement = "vec lxstring = x[1]"; 248 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 249 | vec::vec(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 250 | assert_eq!(registers.lxstring, "omk".to_string()); 251 | } 252 | 253 | #[test] 254 | fn vec_get_string_idx_rv() { 255 | let mut memory: Memory = Memory::new(); 256 | let mut registers: CPU = CPU::new(); 257 | let mut vars: Vars = Vars::new(); 258 | registers.rv = 1; 259 | vars.set_str_vec("x".to_string(), "['ok', 'omk']", &mut memory); 260 | let statement = "vec string = x[rv]"; 261 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 262 | vec::vec(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 263 | assert_eq!(registers.string, "omk".to_string()); 264 | } 265 | 266 | #[test] 267 | fn vec_get_var_idx() { 268 | let mut memory: Memory = Memory::new(); 269 | let mut registers: CPU = CPU::new(); 270 | let mut vars: Vars = Vars::new(); 271 | vars.set_string("y".to_string(), "''", &mut memory); 272 | vars.set_str_vec("x".to_string(), "['ok', 'omk']", &mut memory); 273 | let statement = "vec y = x[1]"; 274 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 275 | vec::vec(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 276 | let t = vars.get_type("y".to_string()).unwrap(); 277 | assert_eq!(memory.yeild_string(t.location), "omk".to_string()); 278 | } 279 | 280 | #[test] 281 | fn vec_get_var_idx_lx() { 282 | let mut memory: Memory = Memory::new(); 283 | let mut registers: CPU = CPU::new(); 284 | let mut vars: Vars = Vars::new(); 285 | vars.set_int("y".to_string(), "1", &mut memory).unwrap(); 286 | vars.set_int_vec("x".to_string(), "[2,4]", &mut memory) 287 | .unwrap(); 288 | let statement = "vec lx = x[y]"; 289 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 290 | vec::vec(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 291 | assert_eq!(registers.lx, 4); 292 | } 293 | 294 | // vec mods 295 | 296 | // vec x[1] = lx 297 | // vec x[lx] = rv 298 | 299 | // vec x[1] = string 300 | // vec x[lx] = lxstring 301 | 302 | // vec x[y] = string 303 | // vec x[1] = y 304 | 305 | #[test] 306 | fn vec_mod_lx() { 307 | let mut memory: Memory = Memory::new(); 308 | let mut registers: CPU = CPU::new(); 309 | let mut vars: Vars = Vars::new(); 310 | registers.lx = 5; 311 | vars.set_int_vec("x".to_string(), "[2,4]", &mut memory) 312 | .unwrap(); 313 | let statement = "vec x[1] = lx"; 314 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 315 | vec::vec(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 316 | let t = vars.get_type("x".to_string()).unwrap(); 317 | assert_eq!(memory.yeild_int_vec(t.location)[1], 5); 318 | } 319 | 320 | #[test] 321 | fn vec_mod_lx_rv() { 322 | let mut memory: Memory = Memory::new(); 323 | let mut registers: CPU = CPU::new(); 324 | let mut vars: Vars = Vars::new(); 325 | registers.lx = 1; 326 | registers.rv = 5; 327 | vars.set_int_vec("x".to_string(), "[2,4]", &mut memory) 328 | .unwrap(); 329 | let statement = "vec x[lx] = rv"; 330 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 331 | vec::vec(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 332 | let t = vars.get_type("x".to_string()).unwrap(); 333 | assert_eq!(memory.yeild_int_vec(t.location)[1], 5); 334 | } 335 | 336 | #[test] 337 | fn vec_mod_string() { 338 | let mut memory: Memory = Memory::new(); 339 | let mut registers: CPU = CPU::new(); 340 | let mut vars: Vars = Vars::new(); 341 | registers.string = "omk".to_string(); 342 | vars.set_str_vec("x".to_string(), "['a', 'k']", &mut memory); 343 | let statement = "vec x[1] = string"; 344 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 345 | vec::vec(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 346 | let t = vars.get_type("x".to_string()).unwrap(); 347 | assert_eq!(memory.yeild_str_vec(t.location)[1], "omk".to_string()); 348 | } 349 | 350 | #[test] 351 | fn vec_mod_lx_string() { 352 | let mut memory: Memory = Memory::new(); 353 | let mut registers: CPU = CPU::new(); 354 | let mut vars: Vars = Vars::new(); 355 | registers.lxstring = "omk".to_string(); 356 | registers.lx = 1; 357 | vars.set_str_vec("x".to_string(), "['a', 'k']", &mut memory); 358 | let statement = "vec x[lx] = lxstring"; 359 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 360 | vec::vec(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 361 | let t = vars.get_type("x".to_string()).unwrap(); 362 | assert_eq!(memory.yeild_str_vec(t.location)[1], "omk".to_string()); 363 | } 364 | 365 | #[test] 366 | fn vec_mod_var_string() { 367 | let mut memory: Memory = Memory::new(); 368 | let mut registers: CPU = CPU::new(); 369 | let mut vars: Vars = Vars::new(); 370 | registers.string = "omk".to_string(); 371 | vars.set_int("y".to_string(), "1", &mut memory).unwrap(); 372 | vars.set_str_vec("x".to_string(), "['a', 'k']", &mut memory); 373 | let statement = "vec x[y] = string"; 374 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 375 | vec::vec(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 376 | let t = vars.get_type("x".to_string()).unwrap(); 377 | assert_eq!(memory.yeild_str_vec(t.location)[1], "omk".to_string()); 378 | } 379 | 380 | #[test] 381 | fn vec_mod_var() { 382 | let mut memory: Memory = Memory::new(); 383 | let mut registers: CPU = CPU::new(); 384 | let mut vars: Vars = Vars::new(); 385 | vars.set_int("y".to_string(), "5", &mut memory).unwrap(); 386 | vars.set_int("i".to_string(), "1", &mut memory).unwrap(); 387 | vars.set_int_vec("x".to_string(), "[0, 1]", &mut memory) 388 | .unwrap(); 389 | let statement = "vec x[i] = y"; 390 | let cmd: Vec<&str> = statement.split_whitespace().collect(); 391 | vec::vec(&mut memory, &mut vars, &mut registers, cmd, statement).unwrap(); 392 | let t = vars.get_type("x".to_string()).unwrap(); 393 | assert_eq!(memory.yeild_int_vec(t.location)[1], 5); 394 | } 395 | -------------------------------------------------------------------------------- /src/funcs/vec.rs: -------------------------------------------------------------------------------- 1 | use super::errors::ErrorKind; 2 | use crate::types::Vector; 3 | use crate::types::{TypeName, Vars}; 4 | use crate::{memory::Memory, CPU}; 5 | 6 | pub fn vec( 7 | memory: &mut Memory, 8 | vars: &mut Vars, 9 | registers: &mut CPU, 10 | cmd: Vec<&str>, 11 | statement: &str, 12 | ) -> Result<(), ErrorKind> { 13 | if cmd.len() < 3 { 14 | return Err(ErrorKind::ArgErr); 15 | } 16 | match cmd[2] { 17 | "push" => { 18 | let var = vars.get_type(cmd[1].to_string()).unwrap(); 19 | let value = cmd[3]; 20 | if var.name == TypeName::Vector(Vector::Int) { 21 | match value { 22 | "lx" => { 23 | let vec_mod = vars.get_vec_int_mod(var, registers.lx, memory); 24 | memory.vec_int_push(&vec_mod.heap_addr, vec_mod.value_bytes); 25 | } 26 | "rv" => { 27 | let vec_mod = vars.get_vec_int_mod(var, registers.rv, memory); 28 | memory.vec_int_push(&vec_mod.heap_addr, vec_mod.value_bytes); 29 | } 30 | _ => { 31 | let var2 = vars.get_type(value.to_string())?; 32 | if var2.name == TypeName::I32 { 33 | let var2_int = memory.yeild_i32(var2.location); 34 | let vec_mod = vars.get_vec_int_mod(var, var2_int, memory); 35 | memory.vec_int_push(&vec_mod.heap_addr, vec_mod.value_bytes); 36 | } else { 37 | return Err(ErrorKind::ExpectedInt(value.to_string())); 38 | } 39 | } 40 | } 41 | } else if var.name == TypeName::Vector(Vector::String) { 42 | match value { 43 | "string" => { 44 | let vec_mod = vars.get_vec_str_mod(var, ®isters.string, memory); 45 | memory.vec_str_push(&vec_mod.heap_addr, &vec_mod.value_bytes); 46 | } 47 | "lxstring" => { 48 | let vec_mod = vars.get_vec_str_mod(var, ®isters.lxstring, memory); 49 | memory.vec_str_push(&vec_mod.heap_addr, &vec_mod.value_bytes); 50 | } 51 | _ => { 52 | let var2 = vars.get_type(value.to_string())?; 53 | if var2.name == TypeName::String { 54 | let str_value = memory.yeild_string(var2.location); 55 | let vec_mod = vars.get_vec_str_mod(var, &str_value, memory); 56 | memory.vec_str_push(&vec_mod.heap_addr, &vec_mod.value_bytes); 57 | } else { 58 | return Err(ErrorKind::ExpectedStr(value.to_string())); 59 | } 60 | } 61 | } 62 | } else { 63 | return Err(ErrorKind::ExpectedVec(cmd[1].to_string())); 64 | } 65 | } 66 | "len" => { 67 | let var = vars.get_type(cmd[1].to_string())?; 68 | if var.name == TypeName::Vector(Vector::Int) { 69 | let len = vars.vec_int_len(var.location, memory); 70 | memory.set_int_to_stack(len); 71 | } else if var.name == TypeName::Vector(Vector::String) { 72 | let len = vars.vec_str_len(var.location, memory); 73 | memory.set_int_to_stack(len); 74 | } else { 75 | return Err(ErrorKind::ExpectedVec(cmd[1].to_string())); 76 | } 77 | } 78 | "shift" => { 79 | let var = vars.get_type(cmd[1].to_string())?; 80 | let heap_addr = memory.load(var.location).to_owned(); 81 | match var.name { 82 | TypeName::Vector(Vector::String) => memory.shift_vec_str(&heap_addr), 83 | TypeName::Vector(Vector::Int) => memory.shift_vec_int(&heap_addr), 84 | _ => return Err(ErrorKind::ExpectedVec(cmd[1].to_string())), 85 | } 86 | } 87 | "pop" => { 88 | let var = vars.get_type(cmd[1].to_string())?; 89 | let heap_addr = memory.load(var.location).to_owned(); 90 | match var.name { 91 | TypeName::Vector(Vector::String) => memory.pop_vec_str(&heap_addr), 92 | TypeName::Vector(Vector::Int) => memory.pop_vec_int(&heap_addr), 93 | _ => return Err(ErrorKind::ExpectedVec(cmd[1].to_string())), 94 | } 95 | } 96 | _ => { 97 | let s = cmd.join(""); 98 | let chars = s.split("").collect::>(); 99 | if !chars.contains(&"[") || !chars.contains(&"]") || !chars.contains(&"=") { 100 | return Err(ErrorKind::ArgErr); 101 | } // performance overhead 102 | 103 | let bracket_i = chars.iter().position(|&r| r == "[").unwrap(); 104 | let equal_i = chars.iter().position(|&r| r == "=").unwrap(); 105 | 106 | if bracket_i > equal_i { 107 | let to_assign = cmd[1]; 108 | let var_exp = statement.split('=').collect::>()[1].trim(); 109 | let var_str = var_exp.split('[').collect::>()[0].trim(); 110 | let idx_str = var_exp.split('[').collect::>()[1] 111 | .trim() 112 | .split(']') 113 | .collect::>()[0] 114 | .trim(); 115 | let index: usize; 116 | match idx_str { 117 | "lx" => index = registers.lx as usize, 118 | "rv" => index = registers.rv as usize, 119 | _ => { 120 | let num = idx_str.parse::(); 121 | match num { 122 | Ok(n) => index = n as usize, 123 | _parse_int_error => { 124 | let idx_var = vars.get_type(idx_str.to_string())?; 125 | if idx_var.name == TypeName::I32 { 126 | index = memory.yeild_i32(idx_var.location) as usize; 127 | } else { 128 | return Err(ErrorKind::ExpectedInt(idx_str.to_string())); 129 | } 130 | } 131 | } 132 | } 133 | } 134 | let var = vars.get_type(var_str.to_string())?; 135 | if var.name == TypeName::Vector(Vector::Int) { 136 | match to_assign { 137 | "lx" => { 138 | registers.lx = 139 | vars.vec_int_item(var.location, var_str.to_string(), index, memory)? 140 | } 141 | "rv" => { 142 | registers.rv = 143 | vars.vec_int_item(var.location, var_str.to_string(), index, memory)? 144 | } 145 | _ => { 146 | let assign_var = vars.get_type(to_assign.to_string())?; 147 | if assign_var.name == TypeName::I32 { 148 | let data: &[u8] = &vars 149 | .vec_int_item(var.location, var_str.to_string(), index, memory)? 150 | .to_be_bytes(); 151 | memory.stack_mod(assign_var.location, data); 152 | } else { 153 | return Err(ErrorKind::ExpectedInt(to_assign.to_string())); 154 | } 155 | } 156 | } 157 | } else if var.name == TypeName::Vector(Vector::String) { 158 | match to_assign { 159 | "string" => { 160 | registers.string = 161 | vars.vec_str_item(var.location, var_str.to_string(), index, memory)? 162 | } 163 | "lxstring" => { 164 | registers.lxstring = 165 | vars.vec_str_item(var.location, var_str.to_string(), index, memory)? 166 | } 167 | _ => { 168 | let assign_var = vars.get_type(to_assign.to_string())?; 169 | if assign_var.name == TypeName::String { 170 | let str = vars.vec_str_item( 171 | var.location, 172 | var_str.to_string(), 173 | index, 174 | memory, 175 | )?; 176 | let new_str_addr = memory.malloc(str.as_bytes()); 177 | let heap_addr: [u8; 4] = memory 178 | .load(assign_var.clone().location) 179 | .try_into() 180 | .expect("illegal heap addr"); 181 | memory.stack_mod(assign_var.location, &new_str_addr.to_be_bytes()); 182 | memory.free(u32::from_be_bytes(heap_addr)); 183 | } else { 184 | return Err(ErrorKind::ExpectedStr(to_assign.to_string())); 185 | } 186 | } 187 | } 188 | } else { 189 | return Err(ErrorKind::ExpectedVec(var_str.to_string())); 190 | } 191 | } else { 192 | let var_exp = statement.split('=').collect::>()[0].trim(); 193 | let var_str_vec = var_exp.split('[').collect::>(); 194 | let idx_str = var_str_vec[1].split(']').collect::>()[0].trim(); 195 | let var_str = var_str_vec[0] 196 | .split_ascii_whitespace() 197 | .collect::>()[1] 198 | .trim(); 199 | let idx: usize; 200 | match idx_str { 201 | "lx" => idx = registers.lx as usize, 202 | "rv" => idx = registers.rv as usize, 203 | _ => { 204 | let num = idx_str.parse::(); 205 | match num { 206 | Ok(n) => idx = n as usize, 207 | _parse_int_error => { 208 | let idx_var = vars.get_type(idx_str.to_string())?; 209 | if idx_var.name == TypeName::I32 { 210 | idx = memory.yeild_i32(idx_var.location) as usize; 211 | } else { 212 | return Err(ErrorKind::ExpectedInt(idx_str.to_string())); 213 | } 214 | } 215 | } 216 | } 217 | } 218 | let var = vars.get_type(var_str.to_string())?; 219 | let assign_to = statement.split('=').collect::>()[1].trim(); 220 | if var.name == TypeName::Vector(Vector::Int) { 221 | match assign_to { 222 | "lx" => { 223 | let vec_mod = vars.get_vec_int_mod(var, registers.lx, memory); 224 | match memory.mod_vec_int(&vec_mod.heap_addr, idx, &vec_mod.value_bytes) 225 | { 226 | Ok(()) => (), 227 | Err(()) => return Err(ErrorKind::VecLen(var_str.to_string())), 228 | } 229 | } 230 | "rv" => { 231 | let vec_mod = vars.get_vec_int_mod(var, registers.rv, memory); 232 | match memory.mod_vec_int(&vec_mod.heap_addr, idx, &vec_mod.value_bytes) 233 | { 234 | Ok(()) => (), 235 | Err(()) => return Err(ErrorKind::VecLen(var_str.to_string())), 236 | } 237 | } 238 | _ => { 239 | let assigned_var = vars.get_type(assign_to.to_string())?; 240 | if assigned_var.name == TypeName::I32 { 241 | let vec_mod = vars.get_vec_int_mod( 242 | var, 243 | memory.yeild_i32(assigned_var.location), 244 | memory, 245 | ); 246 | match memory.mod_vec_int( 247 | &vec_mod.heap_addr, 248 | idx, 249 | &vec_mod.value_bytes, 250 | ) { 251 | Ok(()) => (), 252 | Err(()) => return Err(ErrorKind::VecLen(var_str.to_string())), 253 | } 254 | } else { 255 | return Err(ErrorKind::ExpectedInt(assign_to.to_string())); 256 | } 257 | } 258 | } 259 | } else if var.name == TypeName::Vector(Vector::String) { 260 | match assign_to { 261 | "string" => { 262 | let vec_mod = vars.get_vec_str_mod(var, ®isters.string, memory); 263 | match memory.mod_vec_str(&vec_mod.heap_addr, idx, &vec_mod.value_bytes) 264 | { 265 | Ok(()) => (), 266 | Err(()) => return Err(ErrorKind::VecLen(var_str.to_string())), 267 | } 268 | } 269 | "lxstring" => { 270 | let vec_mod = vars.get_vec_str_mod(var, ®isters.lxstring, memory); 271 | match memory.mod_vec_str(&vec_mod.heap_addr, idx, &vec_mod.value_bytes) 272 | { 273 | Ok(()) => (), 274 | Err(()) => return Err(ErrorKind::VecLen(var_str.to_string())), 275 | } 276 | } 277 | _ => { 278 | let assigned_var = vars.get_type(assign_to.to_string())?; 279 | if assigned_var.name == TypeName::String { 280 | let vec_mod = vars.get_vec_str_mod( 281 | var, 282 | memory.yeild_string(assigned_var.location).trim(), 283 | memory, 284 | ); 285 | match memory.mod_vec_str( 286 | &vec_mod.heap_addr, 287 | idx, 288 | &vec_mod.value_bytes, 289 | ) { 290 | Ok(()) => (), 291 | Err(()) => return Err(ErrorKind::VecLen(var_str.to_string())), 292 | } 293 | } else { 294 | return Err(ErrorKind::ExpectedStr(assign_to.to_string())); 295 | } 296 | } 297 | } 298 | } else { 299 | return Err(ErrorKind::ExpectedVec(var_str.to_string())); 300 | } 301 | } 302 | } 303 | } 304 | 305 | Ok(()) 306 | } 307 | --------------------------------------------------------------------------------