1
1
Fork 0
mirror of https://github.com/azur1s/bobbylisp.git synced 2024-10-16 02:37:40 -05:00

feat: it works 🎉 🎉

This commit is contained in:
Natapat Samutpong 2022-01-27 12:30:16 +07:00
parent cac125bd1c
commit 697012f0ac
4 changed files with 253 additions and 17 deletions

View file

@ -1,4 +1,4 @@
use std::{fs::{read_to_string, File}, path::{Path, PathBuf}, io::{Write, Seek}, time::Instant};
use std::{fs::{read_to_string, File}, path::{Path, PathBuf}, io::{Write, Seek}, time::Instant, process::exit};
use structopt::StructOpt;
@ -12,7 +12,7 @@ mod compiler;
use compiler::{compile::Compiler, parser::{tokenize, Parser}};
mod vm;
use vm::parser::parse_instr;
use vm::{vm::VM, parser::parse_instr};
fn main() {
let start = Instant::now();
@ -31,7 +31,7 @@ fn main() {
// Run
(false, true) => {
let src = read_to_string(&args.file).unwrap();
run_src(src, start);
run_src(src);
},
(false, false) => {
if args.file.extension() == Some("blsp".as_ref()) {
@ -39,7 +39,7 @@ fn main() {
compile_src(src, args.output, args.file, start);
} else if args.file.extension() == Some("bsm".as_ref()) {
let src = read_to_string(&args.file).unwrap();
run_src(src, start);
run_src(src);
} else {
panic!("No mode specified");
}
@ -84,11 +84,16 @@ fn compile_src(src: String, path: Option<PathBuf>, file: PathBuf, start: Instant
}
}
fn run_src(src: String, start: Instant) {
fn run_src(src: String) {
let instrs = parse_instr(&src);
for i in instrs {
println!("{}", i);
let mut vm = VM::new();
match vm.run(instrs) {
Ok(()) => {
exit(0);
},
Err(e) => {
eprintln!("{}", e);
exit(1);
}
}
let elapsed = start.elapsed();
println!("Executed in {}.{}s", elapsed.as_secs(), elapsed.subsec_millis());
}

View file

@ -1,4 +1,6 @@
use std::{fmt::Display, str::FromStr};
use std::{fmt::Display, str::FromStr, ops::{Add, Sub, Mul, Div}};
use crate::vm::vm::Error::{self, InvalidAriphmeticOperation};
/// Literal types for the assembler.
#[derive(Clone, Debug)]
@ -9,6 +11,92 @@ pub enum Type {
String(String),
}
impl Type {
pub fn as_bool(&self) -> bool {
match self {
Type::Boolean(b) => *b,
Type::Int(i) => *i != 0,
Type::Float(f) => *f != 0.0,
Type::String(s) => !s.is_empty(),
}
}
pub fn trim(&self) -> Type {
match self {
Type::Int(i) => Type::Int(*i),
Type::Float(f) => Type::Float(*f),
Type::Boolean(b) => Type::Boolean(*b),
Type::String(s) => Type::String(s[1..s.len() - 1].to_string()),
}
}
pub fn fmt(&self) -> String {
match self {
Type::Int(i) => i.to_string(),
Type::Float(f) => f.to_string(),
Type::Boolean(b) => b.to_string(),
Type::String(s) => s.clone(),
}
}
}
impl Add for Type {
type Output = Result<Type, Error>;
fn add(self, other: Type) -> Result<Type, Error> {
match (self, other) {
(Type::Int(lhs), Type::Int(rhs)) => Ok(Type::Int(lhs + rhs)),
(Type::Int(lhs), Type::Float(rhs)) => Ok(Type::Float(lhs as f64 + rhs)),
(Type::Float(lhs), Type::Int(rhs)) => Ok(Type::Float(lhs + rhs as f64)),
(Type::Float(lhs), Type::Float(rhs)) => Ok(Type::Float(lhs + rhs)),
(Type::String(lhs), Type::String(rhs)) => Ok(Type::String(format!("{}{}", lhs, rhs))),
_ => Err(InvalidAriphmeticOperation),
}
}
}
impl Sub for Type {
type Output = Result<Type, Error>;
fn sub(self, other: Type) -> Result<Type, Error> {
match (self, other) {
(Type::Int(lhs), Type::Int(rhs)) => Ok(Type::Int(lhs - rhs)),
(Type::Int(lhs), Type::Float(rhs)) => Ok(Type::Float(lhs as f64 - rhs)),
(Type::Float(lhs), Type::Int(rhs)) => Ok(Type::Float(lhs - rhs as f64)),
(Type::Float(lhs), Type::Float(rhs)) => Ok(Type::Float(lhs - rhs)),
_ => Err(InvalidAriphmeticOperation),
}
}
}
impl Mul for Type {
type Output = Result<Type, Error>;
fn mul(self, other: Type) -> Result<Type, Error> {
match (self, other) {
(Type::Int(lhs), Type::Int(rhs)) => Ok(Type::Int(lhs * rhs)),
(Type::Int(lhs), Type::Float(rhs)) => Ok(Type::Float(lhs as f64 * rhs)),
(Type::Float(lhs), Type::Int(rhs)) => Ok(Type::Float(lhs * rhs as f64)),
(Type::Float(lhs), Type::Float(rhs)) => Ok(Type::Float(lhs * rhs)),
_ => Err(InvalidAriphmeticOperation),
}
}
}
impl Div for Type {
type Output = Result<Type, Error>;
fn div(self, other: Type) -> Result<Type, Error> {
match (self, other) {
(Type::Int(lhs), Type::Int(rhs)) => Ok(Type::Int(lhs / rhs)),
(Type::Int(lhs), Type::Float(rhs)) => Ok(Type::Float(lhs as f64 / rhs)),
(Type::Float(lhs), Type::Int(rhs)) => Ok(Type::Float(lhs / rhs as f64)),
(Type::Float(lhs), Type::Float(rhs)) => Ok(Type::Float(lhs / rhs)),
_ => Err(InvalidAriphmeticOperation),
}
}
}
impl Display for Type {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
@ -33,13 +121,13 @@ impl FromStr for Type {
"true" => Ok(Type::Boolean(true)),
"false" => Ok(Type::Boolean(false)),
_ => {
let fl = s.parse::<f64>();
if fl.is_ok() {
Ok(Type::Float(fl.unwrap()))
} else {
let i = s.parse::<i64>();
if i.is_ok() {
Ok(Type::Int(i.unwrap()))
} else {
let fl = s.parse::<f64>();
if fl.is_ok() {
Ok(Type::Float(fl.unwrap()))
} else {
Ok(Type::String(s.to_string()))
}
@ -52,6 +140,10 @@ impl FromStr for Type {
#[derive(Clone, Copy, Debug)]
pub struct Register { pub value: usize }
impl Register {
pub fn value(&self) -> usize { self.value }
}
impl Display for Register {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "r{}", self.value)

View file

@ -2,3 +2,5 @@
pub mod instr;
/// Definition of the instruction parser.
pub mod parser;
/// Definition of the virtual machine.
pub mod vm;

137
blspc/src/vm/vm.rs Normal file
View file

@ -0,0 +1,137 @@
use std::fmt::Display;
use crate::vm::instr::{Instr::{self, *}, Type, Register};
pub enum Error {
StackOverflow,
UnknownFunctionCall(isize, isize),
InvalidAriphmeticOperation,
}
impl Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Error::StackOverflow => write!(f, "Stack overflow"),
Error::UnknownFunctionCall(l, e) => write!(f, "Unknown function call at {}: {}", l, e),
Error::InvalidAriphmeticOperation => write!(f, "Invalid ariphmetic operation"),
}
}
}
#[derive(Debug)]
pub struct VM {
pub instr_pointer: isize,
pub registers: Vec<Type>,
pub stack: Vec<Type>,
}
pub type VMReturn = Result<(), Error>;
impl VM {
pub fn new() -> Self {
VM {
instr_pointer: 0,
registers: vec![Type::Int(0); 1024],
stack: Vec::new(),
}
}
pub fn run(&mut self, instrs: Vec<Instr>) -> VMReturn {
'tco: loop {
self.instr_pointer += 1;
if self.instr_pointer - 1 == instrs.len() as isize {
dbg!("VM: HALT");
return Ok(());
}
let instr = &instrs[self.instr_pointer as usize - 1];
match instr {
Store { address, value, .. } => {
self.store(&address, &value)?;
continue 'tco;
},
Call { address, args, .. } => {
let args = &self.registers[args.value()];
let address = &self.registers[address.value()];
call(address, args, self.instr_pointer)?;
continue 'tco;
},
Push { value, .. } => {
self.push(value.trim().clone())?;
continue 'tco;
},
Pop { address, .. } => {
let value = self.stack.pop();
self.store(&address, &value.unwrap())?;
continue 'tco;
},
Add { .. } => {
let lhs = self.stack.pop().unwrap();
let rhs = self.stack.pop().unwrap();
self.push((lhs + rhs)?)?;
continue 'tco;
},
Sub { .. } => {
let lhs = self.stack.pop().unwrap();
let rhs = self.stack.pop().unwrap();
self.push((lhs - rhs)?)?;
continue 'tco;
},
Mul { .. } => {
let lhs = self.stack.pop().unwrap();
let rhs = self.stack.pop().unwrap();
self.push((lhs * rhs)?)?;
continue 'tco;
},
Div { .. } => {
let lhs = self.stack.pop().unwrap();
let rhs = self.stack.pop().unwrap();
self.push((lhs / rhs)?)?;
continue 'tco;
},
Jump { to, .. } => {
self.instr_pointer = *to as isize;
continue 'tco;
},
PopJumpIfFalse { to, .. } => {
let value = self.stack.pop().unwrap();
if !value.as_bool() {
self.instr_pointer = *to as isize;
}
continue 'tco;
},
Return { .. } => {
return Ok(());
},
};
}
}
fn push(&mut self, value: Type) -> Result<(), Error> {
if self.stack.len() >= 1024 {
return Err(Error::StackOverflow);
}
Ok(self.stack.push(value))
}
fn store(&mut self, address: &Register, value: &Type) -> Result<(), Error> {
// TODO: Remove .clone()
Ok(self.registers[address.value()] = value.clone())
}
}
fn call(index: &Type, args: &Type, line: isize) -> Result<(), Error> {
match index {
Type::Int(i) => {
match i {
0 => Err(Error::UnknownFunctionCall(line, 0)),
1 => {
println!("{}", args.fmt());
Ok(())
},
_ => Err(Error::UnknownFunctionCall(line, *i as isize)),
}
}
_ => {dbg!(index); Err(Error::UnknownFunctionCall(line, -1))},
}
}