diff --git a/Cargo.toml b/Cargo.toml index 2715837..25701e9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,5 +10,10 @@ categories = ["command-line-utilities", "parsing"] keywords = ["compiler", "language", "scripting", "parsing", "virtual machine"] edition = "2018" +[features] +default = ["compiler"] + +compiler = [] + [dependencies] argh = "0.1.3" \ No newline at end of file diff --git a/src/args.rs b/src/args.rs index 66bfc99..df8db09 100644 --- a/src/args.rs +++ b/src/args.rs @@ -5,12 +5,20 @@ use argh::FromArgs; #[derive(FromArgs, PartialEq, Debug)] #[argh(description = "reid compiler and Virtual Machine")] pub struct MainOpt { + #[cfg(feature = "compiler")] #[argh(positional, description = "run compiled .reidc from ")] pub run_path: Option, + + #[cfg(not(feature = "compiler"))] + #[argh(positional, description = "run compiled .reidc from ")] + pub run_path: PathBuf, + #[argh(subcommand)] + #[cfg(feature = "compiler")] pub subcommand: Option, } +#[cfg(feature = "compiler")] #[derive(FromArgs, PartialEq, Debug)] #[argh(subcommand)] pub enum Subcommand { diff --git a/src/compiler.rs b/src/compiler.rs index 361bf50..981b57a 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -3,27 +3,10 @@ use std::collections::HashMap; use std::num::ParseIntError; use super::errors::CompilerError; -use super::parser::{Expression, LiteralPattern, ParsedReid, Pattern, Position, Statement}; -use super::vm::{FunctionSignature, VariableType}; +use super::parser::{Expression, LiteralPattern, ParsedReid, Pattern, Statement}; +use super::vm::{Command, CompiledReid, FuncID, FunctionSignature, HeapID, Position, VariableType}; -type Variable = (HeapID, VariableType); -pub type FuncID = u16; -pub type HeapID = u16; -pub type RegID = u8; - -#[derive(Debug, Clone)] -pub enum Command { - InitializeVariable(HeapID, VariableType), // Initializes new variable to HeapID at VariableType - BeginScope, // Begins new Scope - EndScope, // Ends Scope - Pop(RegID), // Pop into registery at RegID - Push(RegID), // Push out of registery at RegID - AssignVariable(HeapID, RegID), // Assign variable from registery at RegID - VarToReg(HeapID, RegID), // Bring Variable to registery at RegID - StringLit(String), // Bring String Literal to Stack - I32Lit(i32), // Bring i32 Literal to Stack - FunctionCall(FuncID), // Call Function at FuncID -} +pub type Variable = (HeapID, VariableType); pub struct Compiler { parsed: ParsedReid, @@ -31,11 +14,6 @@ pub struct Compiler { list: Vec, } -#[derive(Debug)] -pub struct CompiledReid { - pub list: Vec, -} - impl Compiler { pub fn from(parsed: ParsedReid) -> Compiler { Compiler { diff --git a/src/errors.rs b/src/errors.rs index 28a543c..916dfc1 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -1,16 +1,21 @@ -use super::parser::Position; use std::fmt; use std::fmt::Display; use std::io; + +#[cfg(feature = "compiler")] use std::num::ParseIntError; +#[cfg(feature = "compiler")] +use super::vm::Position; use super::vm::VariableType; #[derive(Debug)] pub enum GenericError { StdIOError(io::Error), CorruptedBytecode, + #[cfg(feature = "compiler")] SyntaxError(SyntaxError), + #[cfg(feature = "compiler")] CompilerError(CompilerError), } @@ -20,12 +25,14 @@ impl From for GenericError { } } +#[cfg(feature = "compiler")] impl From for GenericError { fn from(error: SyntaxError) -> Self { Self::SyntaxError(error) } } +#[cfg(feature = "compiler")] impl From for GenericError { fn from(error: CompilerError) -> Self { Self::CompilerError(error) @@ -39,7 +46,9 @@ impl Display for GenericError { GenericError::CorruptedBytecode => { "Failed to read bytecode. Bytecode might be corrupted.".to_string() } + #[cfg(feature = "compiler")] GenericError::SyntaxError(err) => format!("Syntax Error: {}", err), + #[cfg(feature = "compiler")] GenericError::CompilerError(err) => format!("Compiler Error: {}", err), }; write!(f, "{}", text) @@ -47,6 +56,7 @@ impl Display for GenericError { } #[derive(Debug)] +#[cfg(feature = "compiler")] pub enum SyntaxError { #[allow(dead_code)] Fatal, @@ -57,6 +67,7 @@ pub enum SyntaxError { ExpectedPattern(Position), } +#[cfg(feature = "compiler")] impl SyntaxError { fn from_opt(from: &Option>) -> String { if let Some(err) = from { @@ -67,6 +78,7 @@ impl SyntaxError { } } +#[cfg(feature = "compiler")] impl Display for SyntaxError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let text = match self { @@ -90,6 +102,7 @@ impl Display for SyntaxError { } #[derive(Debug)] +#[cfg(feature = "compiler")] pub enum CompilerError { #[allow(dead_code)] Fatal, @@ -102,6 +115,7 @@ pub enum CompilerError { ParseIntError(ParseIntError), } +#[cfg(feature = "compiler")] impl Display for CompilerError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let text = match self { diff --git a/src/file_io.rs b/src/file_io.rs index cabbd40..013a18d 100644 --- a/src/file_io.rs +++ b/src/file_io.rs @@ -3,10 +3,11 @@ use std::io::prelude::*; use std::io::BufReader; use std::path::Path; -use super::compiler::{Command, CompiledReid}; use super::errors::GenericError; use super::vm::VariableType; +use super::vm::{Command, CompiledReid}; +#[cfg(feature = "compiler")] pub fn open_source(path: &Path) -> Result { let file = File::open(path)?; let mut reader = BufReader::new(file); @@ -15,6 +16,7 @@ pub fn open_source(path: &Path) -> Result { Ok(text) } +#[cfg(feature = "compiler")] pub fn into_bytecode(compiled: &CompiledReid) -> Vec { let mut list = Vec::new(); let iter = compiled.list.iter(); @@ -24,6 +26,7 @@ pub fn into_bytecode(compiled: &CompiledReid) -> Vec { list } +#[cfg(feature = "compiler")] pub fn write_bytecode(bytecode: Vec, path: &Path) -> Result<(), GenericError> { let mut file = File::create(path)?; file.write_all(&bytecode)?; @@ -46,6 +49,7 @@ pub fn open_bytecode(path: &Path) -> Result { } impl VariableType { + #[cfg(feature = "compiler")] fn into_u8(&self) -> u8 { match self { VariableType::TypeString => 0, @@ -63,6 +67,7 @@ impl VariableType { } impl Command { + #[cfg(feature = "compiler")] fn id(&self) -> u8 { match *self { Command::InitializeVariable(..) => 0, @@ -127,6 +132,7 @@ impl Command { } } + #[cfg(feature = "compiler")] fn into_u8(&self) -> Vec { let mut list = Vec::new(); list.push(self.id()); diff --git a/src/main.rs b/src/main.rs index 0a000a7..1749f6c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,25 +2,34 @@ #![warn(clippy::all)] mod args; +#[cfg(feature = "compiler")] mod compiler; mod errors; mod file_io; +#[cfg(feature = "compiler")] mod parser; mod vm; -use file_io::{into_bytecode, open_bytecode, open_source, write_bytecode}; +use file_io::open_bytecode; +#[cfg(feature = "compiler")] +use file_io::{into_bytecode, open_source, write_bytecode}; +#[cfg(feature = "compiler")] use std::env; -use std::path::{Path, PathBuf}; +use std::path::Path; +#[cfg(feature = "compiler")] +use std::path::PathBuf; use args::*; -use compiler::{CompiledReid, Compiler}; +#[cfg(feature = "compiler")] +use compiler::Compiler; +#[cfg(feature = "compiler")] use errors::GenericError; +#[cfg(feature = "compiler")] use parser::Parser; -use vm::{ - BuiltinFunctionDef, BuiltinFunctions, FunctionSignature, Value, VariableType, VirtualMachine, -}; +#[cfg(feature = "compiler")] +use vm::FunctionSignature; +use vm::{BuiltinFunctionDef, BuiltinFunctions, CompiledReid, Value, VariableType, VirtualMachine}; -// cargo run c_run reid_src/test.reid for previous functionality fn main() { let print = BuiltinFunctionDef::new( "print", @@ -35,15 +44,9 @@ fn main() { let opt: MainOpt = argh::from_env(); + #[cfg(feature = "compiler")] if let Some(run_path) = opt.run_path { - let compiled = open_bytecode(&run_path); - match compiled { - Ok(compiled) => run(compiled, builtin_functions), - Err(error) => { - eprintln!("{}", error); - std::process::exit(1); - } - } + run_bytecode(&run_path, builtin_functions); } else if let Some(subcommand) = opt.subcommand { match subcommand { Subcommand::Compile(opt) => { @@ -86,8 +89,23 @@ fn main() { eprintln!(" {} ", command); eprintln!(" {} help", command); } + + #[cfg(not(feature = "compiler"))] + run_bytecode(&opt.run_path, builtin_functions); } +fn run_bytecode(run_path: &Path, builtin_functions: BuiltinFunctions) { + let compiled = open_bytecode(run_path); + match compiled { + Ok(compiled) => run(compiled, builtin_functions), + Err(error) => { + eprintln!("{}", error); + std::process::exit(1); + } + } +} + +#[cfg(feature = "compiler")] fn compile(path: &Path, builtin: Vec) -> Result { let parsed = Parser::from(open_source(&path)?).parse()?; //dbg!(&parsed); diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 0ae0fed..465a103 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -1,9 +1,8 @@ mod parsed_reid; use super::errors::SyntaxError; +use super::vm::Position; pub use parsed_reid::*; -use std::fmt; -use std::fmt::Display; const ALLOWED_IDENT_CHARS: [char; 38] = [ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', @@ -312,12 +311,3 @@ impl<'a> Expects<'a> { self.texts } } - -#[derive(Debug, Copy, Clone)] -pub struct Position(usize, usize); - -impl Display for Position { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "line {}, column {}", self.0, self.1) - } -} diff --git a/src/vm/compiled.rs b/src/vm/compiled.rs new file mode 100644 index 0000000..41b737d --- /dev/null +++ b/src/vm/compiled.rs @@ -0,0 +1,64 @@ +use std::fmt; +use std::fmt::Display; + +pub type FuncID = u16; +pub type HeapID = u16; +pub type RegID = u8; + +#[derive(Debug, Clone)] +pub enum Command { + InitializeVariable(HeapID, VariableType), // Initializes new variable to HeapID at VariableType + BeginScope, // Begins new Scope + EndScope, // Ends Scope + Pop(RegID), // Pop into registery at RegID + Push(RegID), // Push out of registery at RegID + AssignVariable(HeapID, RegID), // Assign variable from registery at RegID + VarToReg(HeapID, RegID), // Bring Variable to registery at RegID + StringLit(String), // Bring String Literal to Stack + I32Lit(i32), // Bring i32 Literal to Stack + FunctionCall(FuncID), // Call Function at FuncID +} + +#[derive(Debug)] +pub struct CompiledReid { + pub list: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum Value { + StringVal(String), + I32Val(i32), +} + +impl Value { + pub fn get_type(&self) -> VariableType { + match self { + Value::StringVal(_) => VariableType::TypeString, + Value::I32Val(_) => VariableType::TypeI32, + } + } +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum VariableType { + TypeString, + TypeI32, +} + +impl ToString for VariableType { + fn to_string(&self) -> String { + match self { + VariableType::TypeString => "String".to_string(), + VariableType::TypeI32 => "i32".to_string(), + } + } +} + +#[derive(Debug, Copy, Clone)] +pub struct Position(pub usize, pub usize); + +impl Display for Position { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "line {}, column {}", self.0, self.1) + } +} diff --git a/src/vm/mod.rs b/src/vm/mod.rs index 9bbc95a..f8d81d7 100644 --- a/src/vm/mod.rs +++ b/src/vm/mod.rs @@ -1,10 +1,11 @@ +pub mod compiled; pub mod functions; use std::collections::HashMap; -use super::compiler::{Command, CompiledReid, HeapID}; use super::errors::RuntimePanic; +pub use compiled::*; pub use functions::*; pub struct VirtualMachine { @@ -197,32 +198,3 @@ impl AllocatedVar { } } } -#[derive(Clone, Debug, PartialEq, Eq)] -pub enum Value { - StringVal(String), - I32Val(i32), -} - -impl Value { - fn get_type(&self) -> VariableType { - match self { - Value::StringVal(_) => VariableType::TypeString, - Value::I32Val(_) => VariableType::TypeI32, - } - } -} - -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub enum VariableType { - TypeString, - TypeI32, -} - -impl ToString for VariableType { - fn to_string(&self) -> String { - match self { - VariableType::TypeString => "String".to_string(), - VariableType::TypeI32 => "i32".to_string(), - } - } -}