commit 6824676cb22b47125685a6bca17e6458683937c8 Author: Goren Barak Date: Sat Dec 30 15:42:23 2023 -0500 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..e6f1313 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "fourth" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..ea99e11 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "fourth" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/src/backend.rs b/src/backend.rs new file mode 100644 index 0000000..3d4a0f4 --- /dev/null +++ b/src/backend.rs @@ -0,0 +1,170 @@ +use std::collections::HashMap; +use crate::parse::Parser; +use crate::parse::TokenType::*; + +#[derive(Debug)] +pub struct Vm { + stack: Vec, + dictionary: Dictionary +} + +#[derive(Debug, Default)] +struct Dictionary { + dp: u64, + data: HashMap, + words: HashMap +} + +impl<'a> Vm { + pub fn new() -> Self { + Self { + stack: Vec::new(), + dictionary: Default::default() + } + } + + pub fn vmrun(&mut self, parser: &mut Parser) { + macro_rules! unwrap { + () => { + match self.stack.pop() { + Some(v) => { + v + }, + None => { + println!("ERROR: stack empty"); + std::process::exit(1); + } + } + } + } + + while let Some(item) = parser.next() { + match item { + Number(n) => self.stack.push(n), + Word(w) => { + match w { + "." => { + println!("{:?} ok", unwrap!()); + }, + "+" => { + let sum = unwrap!().wrapping_add(unwrap!()); + self.stack.push(sum); + }, + "*" => { + let prod = unwrap!().wrapping_mul(unwrap!()); + self.stack.push(prod); + }, + "/" => { + let stack_top = unwrap!(); + let stack_second = unwrap!(); + let quo = stack_second.wrapping_div(stack_top); + self.stack.push(quo); + }, + "=" => { + if unwrap!() == unwrap!() { + self.stack.push(1); + } else { + self.stack.push(0); + } + }, + "MOD"|"mod" => { + let stack_top = unwrap!(); + let stack_second = unwrap!(); + let rem = stack_second.wrapping_rem(stack_top); + self.stack.push(rem); + }, + "TRACE"|"trace" => { + match parser.inner_next() { + Some("stack") => { + for item in &self.stack { + println!("{:?}", item); + } + }, + Some("data") => { + println!("{:?}", self.dictionary.data); + }, + Some("words") => { + println!("{:?}", self.dictionary.words); + }, + + subcommand => { + println!("Subcommand {:?} is not supported. Supported subcommands are stack or dataspace.", subcommand); + } + } + }, + "/MOD"|"/mod" => { + let stack_top = unwrap!(); + let stack_second = unwrap!(); + let rem = stack_second.wrapping_rem(stack_top); + let quo = stack_second.wrapping_div(stack_top); + self.stack.push(rem); + self.stack.push(quo); + }, + "SWAP"|"swap" => { + let stack_top = unwrap!(); + let stack_second = unwrap!(); + self.stack.push(stack_top); + self.stack.push(stack_second); + }, + "HERE"|"here" => { + self.stack.push(self.dictionary.dp); + }, + "@" => { + let addr = unwrap!(); + self.stack.push(*self.dictionary.data.get(&addr).unwrap_or(&0)); + }, + "!" => { + let addr = unwrap!(); + let content = unwrap!(); + self.dictionary.data.insert(addr, content); + }, + "," => { + let content = unwrap!(); + self.dictionary.dp += 1; + self.dictionary.data.insert(self.dictionary.dp, content); + }, + "ALLOT"|"allot" => { + self.dictionary.dp += unwrap!(); + }, + "CREATE"|"create" => { + self.dictionary.dp += 1; + let Some(Word(word_name)) = parser.next() else { println!("ERROR: Word name not given."); std::process::exit(1) }; + self.dictionary.words.insert(word_name.to_string(), self.dictionary.dp.to_string()); + }, + "VARIABLE"|"variable" => { + self.dictionary.dp += 1; + let Some(Word(word_name)) = parser.next() else { println!("ERROR: Word name not given."); std::process::exit(1) }; + self.dictionary.words.insert(word_name.to_string(), self.dictionary.dp.to_string()); + + }, + "DUP"|"dup" => { + let stack_top = unwrap!(); + self.stack.push(stack_top); + self.stack.push(stack_top); + }, + ":" => { + let mut word_content = String::new(); + let Some(Word(word_name)) = parser.next() else { println!("ERROR: Word name not given."); std::process::exit(1); }; + let mut next = parser.inner_next(); + while next != Some(";") && next != None { + word_content.push_str(next.unwrap()); + word_content.push_str(" "); + next = parser.inner_next(); + } + + self.dictionary.words.insert(word_name.to_string(), word_content); + }, + word => { + let words = self.dictionary.words.clone(); + let Some(word_content) = words.get(word) else { + println!("word {:?} does not exist", word); + std::process::exit(1); + }; + self.vmrun(&mut Parser::new(word_content)); + } + } + } + } + } + } +} diff --git a/src/backend.rs~ b/src/backend.rs~ new file mode 100644 index 0000000..cbf829a --- /dev/null +++ b/src/backend.rs~ @@ -0,0 +1,151 @@ +use std::collections::HashMap; +use crate::parse::Parser; +use crate::parse::TokenType::*; + +#[derive(Debug)] +pub struct Vm { + stack: Vec, + dictionary: Dictionary +} + +#[derive(Debug, Default)] +struct Dictionary { + dp: u64, + data: HashMap, + words: HashMap +} + +impl<'a> Vm { + pub fn new() -> Self { + Self { + stack: Vec::new(), + dictionary: Default::default() + } + } + + pub fn vmrun(&mut self, parser: &mut Parser) { + macro_rules! unwrap { + () => { + match self.stack.pop() { + Some(v) => { + v + }, + None => { + println!("ERROR: stack empty"); + std::process::exit(1); + } + } + } + } + + while let Some(item) = parser.next() { + match item { + Number(n) => self.stack.push(n), + Word(w) => { + match w { + "." => { + println!("{:?} ok", unwrap!()); + }, + "+" => { + let sum = unwrap!().wrapping_add(unwrap!()); + self.stack.push(sum); + }, + "*" => { + let prod = unwrap!().wrapping_mul(unwrap!()); + self.stack.push(prod); + }, + "/" => { + let stack_top = unwrap!(); + let stack_second = unwrap!(); + let quo = stack_second.wrapping_div(stack_top); + self.stack.push(quo); + }, + "=" => { + if unwrap!() == unwrap!() { + self.stack.push(1); + } else { + self.stack.push(0); + } + }, + "MOD"|"mod" => { + let stack_top = unwrap!(); + let stack_second = unwrap!(); + let rem = stack_second.wrapping_rem(stack_top); + self.stack.push(rem); + }, + "/MOD"|"/mod" => { + let stack_top = unwrap!(); + let stack_second = unwrap!(); + let rem = stack_second.wrapping_rem(stack_top); + let quo = stack_second.wrapping_div(stack_top); + self.stack.push(rem); + self.stack.push(quo); + }, + "SWAP"|"swap" => { + let stack_top = unwrap!(); + let stack_second = unwrap!(); + self.stack.push(stack_top); + self.stack.push(stack_second); + }, + "HERE"|"here" => { + self.stack.push(self.dictionary.dp); + }, + "@" => { + let addr = unwrap!(); + self.stack.push(*self.dictionary.data.get(&addr).unwrap_or(&0)); + }, + "!" => { + let addr = unwrap!(); + let content = unwrap!(); + self.dictionary.data.insert(addr, content); + }, + "," => { + let content = unwrap!(); + self.dictionary.dp += 1; + self.dictionary.data.insert(self.dictionary.dp, content); + }, + "ALLOT"|"allot" => { + self.dictionary.dp += unwrap!(); + }, + "CREATE"|"create" => { + self.dictionary.dp += 1; + let Some(Word(word_name)) = parser.next() else { println!("ERROR: Word name not given."); std::process::exit(1) }; + self.dictionary.words.insert(word_name.to_string(), self.dictionary.dp.to_string()); + }, + "VARIABLE"|"variable" => { + self.dictionary.dp += 1; + let Some(Word(word_name)) = parser.next() else { println!("ERROR: Word name not given."); std::process::exit(1) }; + self.dictionary.words.insert(word_name.to_string(), self.dictionary.dp.to_string()); + + }, + "DUP"|"dup" => { + let stack_top = unwrap!(); + self.stack.push(stack_top); + self.stack.push(stack_top); + }, + ":" => { + let mut word_content = String::new(); + let Some(Word(word_name)) = parser.next() else { println!("ERROR: Word name not given."); std::process::exit(1); }; + let mut next = parser.inner_next(); + while next != Some(";") && next != None { + word_content.push_str(next.unwrap()); + word_content.push_str(" "); + next = parser.inner_next(); + } + + self.dictionary.words.insert(word_name.to_string(), word_content); + }, + word => { + let words = self.dictionary.words.clone(); + let Some(word_content) = words.get(word) else { + println!("word {:?} does not exist", word); + std::process::exit(1); + }; + self.vmrun(&mut Parser::new(word_content)); + } + } + } + } + } + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..3a4ec95 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,19 @@ +use std::fs::read_to_string; +pub mod parse; +pub mod backend; +use parse::Parser; +use backend::Vm; + +fn main() -> std::io::Result<()> { + let mut args = std::env::args(); + let command = args.next().unwrap(); + if let Some(filename) = args.next() { + let contents = read_to_string(filename)?; + let contents = contents.as_str(); + Vm::new().vmrun(&mut Parser::new(contents)); + } else { + eprintln!("Usage: {} filename", command); + std::process::exit(1); + } + Ok(()) +} diff --git a/src/parse.rs b/src/parse.rs new file mode 100644 index 0000000..d735c61 --- /dev/null +++ b/src/parse.rs @@ -0,0 +1,37 @@ +use std::str::SplitWhitespace; +use TokenType::*; + +#[derive(Debug)] +pub enum TokenType<'a> { + Number(u64), + Word(&'a str), +} + +#[derive(Clone)] +pub struct Parser<'a> { + pub(crate) split_whitespace: SplitWhitespace<'a> +} + +impl<'a> Iterator for Parser<'a> { + type Item = TokenType<'a>; + + fn next(&mut self) -> Option> { + let item = self.split_whitespace.next()?; + if let Ok(number) = item.parse::() { + return Some(Number(number)); + } else { + return Some(Word(item)); + } + } +} + +impl<'a> Parser<'a> { + pub fn new(source: &'a str) -> Parser { + Parser { + split_whitespace: source.split_whitespace(), + } + } + pub fn inner_next(&mut self) -> Option<&'a str> { + self.split_whitespace.next() + } +} diff --git a/tags b/tags new file mode 100644 index 0000000..c10af82 --- /dev/null +++ b/tags @@ -0,0 +1,155 @@ +!_TAG_EXTRA_DESCRIPTION anonymous /Include tags for non-named objects like lambda/ +!_TAG_EXTRA_DESCRIPTION fileScope /Include tags of file scope/ +!_TAG_EXTRA_DESCRIPTION pseudo /Include pseudo tags/ +!_TAG_EXTRA_DESCRIPTION subparser /Include tags generated by subparsers/ +!_TAG_FIELD_DESCRIPTION epoch /the last modified time of the input file (only for F\/file kind tag)/ +!_TAG_FIELD_DESCRIPTION file /File-restricted scoping/ +!_TAG_FIELD_DESCRIPTION input /input file/ +!_TAG_FIELD_DESCRIPTION name /tag name/ +!_TAG_FIELD_DESCRIPTION pattern /pattern/ +!_TAG_FIELD_DESCRIPTION typeref /Type and name of a variable or typedef/ +!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/ +!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/ +!_TAG_KIND_DESCRIPTION!D M,module /modules/ +!_TAG_KIND_DESCRIPTION!D T,template /templates/ +!_TAG_KIND_DESCRIPTION!D V,version /version statements/ +!_TAG_KIND_DESCRIPTION!D X,mixin /mixins/ +!_TAG_KIND_DESCRIPTION!D a,alias /aliases/ +!_TAG_KIND_DESCRIPTION!D c,class /classes/ +!_TAG_KIND_DESCRIPTION!D e,enumerator /enumerators (values inside an enumeration)/ +!_TAG_KIND_DESCRIPTION!D f,function /function definitions/ +!_TAG_KIND_DESCRIPTION!D g,enum /enumeration names/ +!_TAG_KIND_DESCRIPTION!D i,interface /interfaces/ +!_TAG_KIND_DESCRIPTION!D m,member /class, struct, and union members/ +!_TAG_KIND_DESCRIPTION!D n,namespace /namespaces/ +!_TAG_KIND_DESCRIPTION!D s,struct /structure names/ +!_TAG_KIND_DESCRIPTION!D u,union /union names/ +!_TAG_KIND_DESCRIPTION!D v,variable /variable definitions/ +!_TAG_KIND_DESCRIPTION!JSON a,array /arrays/ +!_TAG_KIND_DESCRIPTION!JSON b,boolean /booleans/ +!_TAG_KIND_DESCRIPTION!JSON n,number /numbers/ +!_TAG_KIND_DESCRIPTION!JSON o,object /objects/ +!_TAG_KIND_DESCRIPTION!JSON s,string /strings/ +!_TAG_KIND_DESCRIPTION!JSON z,null /nulls/ +!_TAG_KIND_DESCRIPTION!Rust C,constant /A constant/ +!_TAG_KIND_DESCRIPTION!Rust M,macro /Macro Definition/ +!_TAG_KIND_DESCRIPTION!Rust P,method /A method/ +!_TAG_KIND_DESCRIPTION!Rust c,implementation /implementation/ +!_TAG_KIND_DESCRIPTION!Rust e,enumerator /An enum variant/ +!_TAG_KIND_DESCRIPTION!Rust f,function /Function/ +!_TAG_KIND_DESCRIPTION!Rust g,enum /Enum/ +!_TAG_KIND_DESCRIPTION!Rust i,interface /trait interface/ +!_TAG_KIND_DESCRIPTION!Rust m,field /A struct field/ +!_TAG_KIND_DESCRIPTION!Rust n,module /module/ +!_TAG_KIND_DESCRIPTION!Rust s,struct /structural type/ +!_TAG_KIND_DESCRIPTION!Rust t,typedef /Type Alias/ +!_TAG_KIND_DESCRIPTION!Rust v,variable /Global variable/ +!_TAG_OUTPUT_EXCMD mixed /number, pattern, mixed, or combineV2/ +!_TAG_OUTPUT_FILESEP slash /slash or backslash/ +!_TAG_OUTPUT_MODE u-ctags /u-ctags or e-ctags/ +!_TAG_OUTPUT_VERSION 0.0 /current.age/ +!_TAG_PARSER_VERSION!D 0.0 /current.age/ +!_TAG_PARSER_VERSION!JSON 0.0 /current.age/ +!_TAG_PARSER_VERSION!Rust 0.0 /current.age/ +!_TAG_PATTERN_LENGTH_LIMIT 96 /0 for no limit/ +!_TAG_PROC_CWD /home/goren/Code/fourth/ // +!_TAG_PROGRAM_AUTHOR Universal Ctags Team // +!_TAG_PROGRAM_NAME Universal Ctags /Derived from Exuberant Ctags/ +!_TAG_PROGRAM_URL https://ctags.io/ /official site/ +!_TAG_PROGRAM_VERSION 6.0.0 /p6.0.20221218.0/ +0 target/debug/.fingerprint/fourth-0eb22537b83d0b36/test-bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":183265222628/;" o array:local +0 target/debug/.fingerprint/fourth-c58712c3665fe72a/bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":110397424744/;" o array:local +0 target/debug/.fingerprint/fourth-d5bfd771d6ea8237/bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":131263742483/;" o array:local +0 target/release/.fingerprint/fourth-96ade2603d15be13/bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":356732962844/;" o array:local +15729799797837862367 target/.rustc_info.json /^{"rustc_fingerprint":15313746258697816560,"outputs":{"15729799797837862367":{"success":true,"sta/;" o object:outputs +4614504638168534921 target/.rustc_info.json /^{"rustc_fingerprint":15313746258697816560,"outputs":{"15729799797837862367":{"success":true,"sta/;" o object:outputs +CheckDepInfo target/debug/.fingerprint/fourth-0eb22537b83d0b36/test-bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":183265222628/;" o object:local.0 +CheckDepInfo target/debug/.fingerprint/fourth-c58712c3665fe72a/bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":110397424744/;" o object:local.0 +CheckDepInfo target/debug/.fingerprint/fourth-d5bfd771d6ea8237/bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":131263742483/;" o object:local.0 +CheckDepInfo target/release/.fingerprint/fourth-96ade2603d15be13/bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":356732962844/;" o object:local.0 +Dictionary src/backend.rs /^struct Dictionary {$/;" s +Item src/parse.rs /^ type Item = TokenType<'a>;$/;" t implementation:Parser +Number src/parse.rs /^ Number(u64),$/;" e enum:TokenType +Parser src/parse.rs /^impl<'a> Iterator for Parser<'a> {$/;" c +Parser src/parse.rs /^impl<'a> Parser<'a> {$/;" c +Parser src/parse.rs /^pub struct Parser<'a> {$/;" s +TokenType src/parse.rs /^pub enum TokenType<'a> {$/;" g +Vm src/backend.rs /^impl<'a> Vm {$/;" c +Vm src/backend.rs /^pub struct Vm {$/;" s +Word src/parse.rs /^ Word(&'a str),$/;" e enum:TokenType +backend src/main.rs /^pub mod backend;$/;" n +code target/.rustc_info.json /^{"rustc_fingerprint":15313746258697816560,"outputs":{"15729799797837862367":{"success":true,"sta/;" n object:outputs.15729799797837862367 +code target/.rustc_info.json /^{"rustc_fingerprint":15313746258697816560,"outputs":{"15729799797837862367":{"success":true,"sta/;" n object:outputs.4614504638168534921 +compile_kind target/debug/.fingerprint/fourth-0eb22537b83d0b36/test-bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":183265222628/;" n +compile_kind target/debug/.fingerprint/fourth-c58712c3665fe72a/bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":110397424744/;" n +compile_kind target/debug/.fingerprint/fourth-d5bfd771d6ea8237/bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":131263742483/;" n +compile_kind target/release/.fingerprint/fourth-96ade2603d15be13/bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":356732962844/;" n +config target/debug/.fingerprint/fourth-0eb22537b83d0b36/test-bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":183265222628/;" n +config target/debug/.fingerprint/fourth-c58712c3665fe72a/bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":110397424744/;" n +config target/debug/.fingerprint/fourth-d5bfd771d6ea8237/bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":131263742483/;" n +config target/release/.fingerprint/fourth-96ade2603d15be13/bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":356732962844/;" n +data src/backend.rs /^ data: HashMap,$/;" m struct:Dictionary +dep_info target/debug/.fingerprint/fourth-0eb22537b83d0b36/test-bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":183265222628/;" s object:local.0.CheckDepInfo +dep_info target/debug/.fingerprint/fourth-c58712c3665fe72a/bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":110397424744/;" s object:local.0.CheckDepInfo +dep_info target/debug/.fingerprint/fourth-d5bfd771d6ea8237/bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":131263742483/;" s object:local.0.CheckDepInfo +dep_info target/release/.fingerprint/fourth-96ade2603d15be13/bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":356732962844/;" s object:local.0.CheckDepInfo +deps target/debug/.fingerprint/fourth-0eb22537b83d0b36/test-bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":183265222628/;" a +deps target/debug/.fingerprint/fourth-c58712c3665fe72a/bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":110397424744/;" a +deps target/debug/.fingerprint/fourth-d5bfd771d6ea8237/bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":131263742483/;" a +deps target/release/.fingerprint/fourth-96ade2603d15be13/bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":356732962844/;" a +dictionary src/backend.rs /^ dictionary: Dictionary$/;" m struct:Vm +dp src/backend.rs /^ dp: u64,$/;" m struct:Dictionary +features target/debug/.fingerprint/fourth-0eb22537b83d0b36/test-bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":183265222628/;" s +features target/debug/.fingerprint/fourth-c58712c3665fe72a/bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":110397424744/;" s +features target/debug/.fingerprint/fourth-d5bfd771d6ea8237/bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":131263742483/;" s +features target/release/.fingerprint/fourth-96ade2603d15be13/bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":356732962844/;" s +inner_next src/parse.rs /^ pub fn inner_next(&mut self) -> Option<&'a str> {$/;" P implementation:Parser +local target/debug/.fingerprint/fourth-0eb22537b83d0b36/test-bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":183265222628/;" a +local target/debug/.fingerprint/fourth-c58712c3665fe72a/bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":110397424744/;" a +local target/debug/.fingerprint/fourth-d5bfd771d6ea8237/bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":131263742483/;" a +local target/release/.fingerprint/fourth-96ade2603d15be13/bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":356732962844/;" a +main src/main.rs /^fn main() -> std::io::Result<()> {$/;" f +metadata target/debug/.fingerprint/fourth-0eb22537b83d0b36/test-bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":183265222628/;" n +metadata target/debug/.fingerprint/fourth-c58712c3665fe72a/bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":110397424744/;" n +metadata target/debug/.fingerprint/fourth-d5bfd771d6ea8237/bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":131263742483/;" n +metadata target/release/.fingerprint/fourth-96ade2603d15be13/bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":356732962844/;" n +new src/backend.rs /^ pub fn new() -> Self {$/;" P implementation:Vm +new src/parse.rs /^ pub fn new(source: &'a str) -> Parser {$/;" P implementation:Parser +next src/parse.rs /^ fn next(&mut self) -> Option> {$/;" P implementation:Parser +outputs target/.rustc_info.json /^{"rustc_fingerprint":15313746258697816560,"outputs":{"15729799797837862367":{"success":true,"sta/;" o +parse src/main.rs /^pub mod parse;$/;" n +path target/debug/.fingerprint/fourth-0eb22537b83d0b36/test-bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":183265222628/;" n +path target/debug/.fingerprint/fourth-c58712c3665fe72a/bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":110397424744/;" n +path target/debug/.fingerprint/fourth-d5bfd771d6ea8237/bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":131263742483/;" n +path target/release/.fingerprint/fourth-96ade2603d15be13/bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":356732962844/;" n +profile target/debug/.fingerprint/fourth-0eb22537b83d0b36/test-bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":183265222628/;" n +profile target/debug/.fingerprint/fourth-c58712c3665fe72a/bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":110397424744/;" n +profile target/debug/.fingerprint/fourth-d5bfd771d6ea8237/bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":131263742483/;" n +profile target/release/.fingerprint/fourth-96ade2603d15be13/bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":356732962844/;" n +rustc target/debug/.fingerprint/fourth-0eb22537b83d0b36/test-bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":183265222628/;" n +rustc target/debug/.fingerprint/fourth-c58712c3665fe72a/bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":110397424744/;" n +rustc target/debug/.fingerprint/fourth-d5bfd771d6ea8237/bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":131263742483/;" n +rustc target/release/.fingerprint/fourth-96ade2603d15be13/bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":356732962844/;" n +rustc_fingerprint target/.rustc_info.json /^{"rustc_fingerprint":15313746258697816560,"outputs":{"15729799797837862367":{"success":true,"sta/;" n +rustflags target/debug/.fingerprint/fourth-0eb22537b83d0b36/test-bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":183265222628/;" a +rustflags target/debug/.fingerprint/fourth-c58712c3665fe72a/bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":110397424744/;" a +rustflags target/debug/.fingerprint/fourth-d5bfd771d6ea8237/bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":131263742483/;" a +rustflags target/release/.fingerprint/fourth-96ade2603d15be13/bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":356732962844/;" a +split_whitespace src/parse.rs /^ pub(crate) split_whitespace: SplitWhitespace<'a>$/;" m struct:Parser +stack src/backend.rs /^ stack: Vec,$/;" m struct:Vm +status target/.rustc_info.json /^{"rustc_fingerprint":15313746258697816560,"outputs":{"15729799797837862367":{"success":true,"sta/;" s object:outputs.15729799797837862367 +status target/.rustc_info.json /^{"rustc_fingerprint":15313746258697816560,"outputs":{"15729799797837862367":{"success":true,"sta/;" s object:outputs.4614504638168534921 +stderr target/.rustc_info.json /^{"rustc_fingerprint":15313746258697816560,"outputs":{"15729799797837862367":{"success":true,"sta/;" s object:outputs.15729799797837862367 +stderr target/.rustc_info.json /^{"rustc_fingerprint":15313746258697816560,"outputs":{"15729799797837862367":{"success":true,"sta/;" s object:outputs.4614504638168534921 +stdout target/.rustc_info.json /^{"rustc_fingerprint":15313746258697816560,"outputs":{"15729799797837862367":{"success":true,"sta/;" s object:outputs.15729799797837862367 +stdout target/.rustc_info.json /^{"rustc_fingerprint":15313746258697816560,"outputs":{"15729799797837862367":{"success":true,"sta/;" s object:outputs.4614504638168534921 +success target/.rustc_info.json /^{"rustc_fingerprint":15313746258697816560,"outputs":{"15729799797837862367":{"success":true,"sta/;" b object:outputs.15729799797837862367 +success target/.rustc_info.json /^{"rustc_fingerprint":15313746258697816560,"outputs":{"15729799797837862367":{"success":true,"sta/;" b object:outputs.4614504638168534921 +successes target/.rustc_info.json /^{"rustc_fingerprint":15313746258697816560,"outputs":{"15729799797837862367":{"success":true,"sta/;" o +target target/debug/.fingerprint/fourth-0eb22537b83d0b36/test-bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":183265222628/;" n +target target/debug/.fingerprint/fourth-c58712c3665fe72a/bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":110397424744/;" n +target target/debug/.fingerprint/fourth-d5bfd771d6ea8237/bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":131263742483/;" n +target target/release/.fingerprint/fourth-96ade2603d15be13/bin-fourth.json /^{"rustc":3462548589188548201,"features":"[]","target":6449572106981162502,"profile":356732962844/;" n +unwrap src/backend.rs /^ macro_rules! unwrap {$/;" M method:Vm::vmrun +vmrun src/backend.rs /^ pub fn vmrun(&mut self, parser: &mut Parser) {$/;" P implementation:Vm +words src/backend.rs /^ words: HashMap$/;" m struct:Dictionary diff --git a/test.fourth b/test.fourth new file mode 100644 index 0000000..e69de29