From 5d9d0f700b42bee9f9b4a702272329bad58ef2b1 Mon Sep 17 00:00:00 2001 From: Natapat Samutpong Date: Sun, 6 Feb 2022 19:00:12 +0700 Subject: [PATCH] feat: `throw` --- README.md | 3 +- blspc/src/compiler/compile.rs | 56 ++++++++++++++++------------------- blspc/src/main.rs | 5 +++- blspc/src/vm/types.rs | 2 +- blspc/src/vm/vm.rs | 8 ++++- example/hello.blsp | 7 ++--- example/math.blsp | 3 -- example/throw.blsp | 2 ++ 8 files changed, 45 insertions(+), 41 deletions(-) delete mode 100644 example/math.blsp create mode 100644 example/throw.blsp diff --git a/README.md b/README.md index 822474e..88a7852 100644 --- a/README.md +++ b/README.md @@ -22,13 +22,14 @@ Hello, World! DONE: - Parsing, Compiling, Running(VM) - Intrinsic: - - Function definition: `fun` + - Function definition: `fun` (no arguments yet) - Variable definition: `def` - Do blocks: `do` - User input: `read` - Printing: `print` - Condition: `if` - Loops: `while` + - Erroring: `throw` - Math: - `+` , `add` - `-` , `sub` diff --git a/blspc/src/compiler/compile.rs b/blspc/src/compiler/compile.rs index 2586d28..ccc00d7 100644 --- a/blspc/src/compiler/compile.rs +++ b/blspc/src/compiler/compile.rs @@ -113,6 +113,28 @@ impl Compiler { Ok(result) } + + fn compile_atom(&mut self, atom: &Sexpr) -> Result, String> { + let mut result = Vec::new(); + + match atom { + Int(i) => { result.push(Instr::Push { value: Type::Int(*i) }); }, + Float(f) => { result.push(Instr::Push { value: Type::Float(*f) }); }, + Str(s) => { result.push(Instr::Push { value: Type::String(s.to_string()) }); }, + Boolean(b) => { result.push(Instr::Push { value: Type::Boolean(*b) }); }, + Symbol(s) => { + let var_pointer = match self.variables.iter().find(|&(ref name, _)| name == s) { + Some((_, pointer)) => *pointer, + None => return Err(format!("Undefined variable {}", s)), + }; + result.push(Instr::Comment { text: format!("`{}` variable", s) }); + result.push(Instr::Load { address: var_pointer }); + }, + _ => { result.append(&mut self.compile(atom.clone())?); } + } + + Ok(result) + } fn compile_intrinsic(&mut self, intrinsic: &String, args: &[Sexpr]) -> Result, String> { let mut result = Vec::new(); @@ -127,6 +149,10 @@ impl Compiler { result.append(&mut self.compile(args[0].clone())?); result.push(Instr::Call { function: "slurp".to_string() }); }, + "throw" => { + result.append(&mut self.compile(args[0].clone())?); + result.push(Instr::Call { function: "throw".to_string() }); + } "add" | "+" => { let mut lhs = self.compile_atom(&args[0])?; @@ -189,36 +215,6 @@ impl Compiler { Ok(result) } - - fn compile_atom(&mut self, atom: &Sexpr) -> Result, String> { - let mut result = Vec::new(); - - match atom { - Int(i) => { - result.push(Instr::Push { value: Type::Int(*i) }); - }, - Float(f) => { - result.push(Instr::Push { value: Type::Float(*f) }); - }, - Str(s) => { - result.push(Instr::Push { value: Type::String(s.to_string()) }); - }, - Boolean(b) => { - result.push(Instr::Push { value: Type::Boolean(*b) }); - }, - Symbol(s) => { - let var_pointer = match self.variables.iter().find(|&(ref name, _)| name == s) { - Some((_, pointer)) => *pointer, - None => return Err(format!("Undefined variable {}", s)), - }; - result.push(Instr::Comment { text: format!("`{}` variable", s) }); - result.push(Instr::Load { address: var_pointer }); - }, - _ => { result.append(&mut self.compile(atom.clone())?); } - } - - Ok(result) - } } fn quoted_sexpr(cdr: &Sexpr) -> Result { diff --git a/blspc/src/main.rs b/blspc/src/main.rs index 69f28ea..001d53b 100644 --- a/blspc/src/main.rs +++ b/blspc/src/main.rs @@ -34,7 +34,7 @@ fn compile_src(src: String, path: Option, file: PathBuf, debug: bool) { let file_name = match path { Some(path) => path, None => Path::new(&file).to_path_buf(), - }.file_stem().unwrap().to_str().unwrap().to_string(); + }.file_stem().unwrap().to_str().unwrap().to_string(); // what let start = Instant::now(); let tokens = tokenize(&cover_paren(src)); @@ -57,14 +57,17 @@ fn compile_src(src: String, path: Option, file: PathBuf, debug: bool) { let elapsed = start.elapsed(); println!("Compiled in {}.{}s", elapsed.as_secs(), elapsed.subsec_millis()); + exit(0); }, Err(err) => { eprintln!("{}", err); + exit(1); } } }, Err(e) => { eprintln!("{}", e); + exit(1); } } } diff --git a/blspc/src/vm/types.rs b/blspc/src/vm/types.rs index fd8bef4..447dcf1 100644 --- a/blspc/src/vm/types.rs +++ b/blspc/src/vm/types.rs @@ -35,7 +35,7 @@ impl Type { s.push('('); for (i, t) in v.iter().enumerate() { if i != 0 { s.push(' '); } - s.push_str(&t.print().to_string()); + s.push_str(&t.print()); } s.push(')'); s diff --git a/blspc/src/vm/vm.rs b/blspc/src/vm/vm.rs index 250bcc6..8a6da0b 100644 --- a/blspc/src/vm/vm.rs +++ b/blspc/src/vm/vm.rs @@ -9,6 +9,7 @@ pub enum Error { UnknownFunctionCall(String), InvalidAriphmeticOperation, FileError(String), + Throw(String), } impl Display for Error { @@ -20,6 +21,7 @@ impl Display for Error { Error::UnknownFunctionCall(function) => write!(f, "Unknown function call: {}", function), Error::InvalidAriphmeticOperation => write!(f, "Invalid ariphmetic operation"), Error::FileError(msg) => write!(f, "Could not open file: {}", msg), + Error::Throw(msg) => write!(f, "{}", msg), } } } @@ -226,7 +228,11 @@ impl VM { Ok(_) => Ok(self.stack.push(Type::String(result))), Err(e) => Err(Error::FileError(e.to_string())), } - } + }, + "throw" => { + let value = self.stack.pop().unwrap(); + return Err(Error::Throw(value.print())); + }, _ => { dbg!(function); Err(Error::UnknownFunctionCall(function.to_string())) }, } } diff --git a/example/hello.blsp b/example/hello.blsp index 6f02d2e..f97d065 100644 --- a/example/hello.blsp +++ b/example/hello.blsp @@ -1,4 +1,3 @@ -(fun str "Hello, world!") - -(fun main - (print (str))) \ No newline at end of file +(fun main (do + (def str "Hello, world!") + (print (str)))) \ No newline at end of file diff --git a/example/math.blsp b/example/math.blsp deleted file mode 100644 index 8fdf481..0000000 --- a/example/math.blsp +++ /dev/null @@ -1,3 +0,0 @@ -(fun cool_number (/ (+ 345 345) 10)) -(fun main - (print cool_number)) \ No newline at end of file diff --git a/example/throw.blsp b/example/throw.blsp new file mode 100644 index 0000000..8a3dabd --- /dev/null +++ b/example/throw.blsp @@ -0,0 +1,2 @@ +(fun main + (throw "error :(")) \ No newline at end of file