mirror of
https://github.com/azur1s/bobbylisp.git
synced 2024-10-16 02:37:40 -05:00
feat: throw
This commit is contained in:
parent
c1975a40af
commit
5d9d0f700b
|
@ -22,13 +22,14 @@ Hello, World!
|
||||||
DONE:
|
DONE:
|
||||||
- Parsing, Compiling, Running(VM)
|
- Parsing, Compiling, Running(VM)
|
||||||
- Intrinsic:
|
- Intrinsic:
|
||||||
- Function definition: `fun`
|
- Function definition: `fun` (no arguments yet)
|
||||||
- Variable definition: `def`
|
- Variable definition: `def`
|
||||||
- Do blocks: `do`
|
- Do blocks: `do`
|
||||||
- User input: `read`
|
- User input: `read`
|
||||||
- Printing: `print`
|
- Printing: `print`
|
||||||
- Condition: `if`
|
- Condition: `if`
|
||||||
- Loops: `while`
|
- Loops: `while`
|
||||||
|
- Erroring: `throw`
|
||||||
- Math:
|
- Math:
|
||||||
- `+` , `add`
|
- `+` , `add`
|
||||||
- `-` , `sub`
|
- `-` , `sub`
|
||||||
|
|
|
@ -114,6 +114,28 @@ impl Compiler {
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn compile_atom(&mut self, atom: &Sexpr) -> Result<Vec<Instr>, 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<Vec<Instr>, String> {
|
fn compile_intrinsic(&mut self, intrinsic: &String, args: &[Sexpr]) -> Result<Vec<Instr>, String> {
|
||||||
let mut result = Vec::new();
|
let mut result = Vec::new();
|
||||||
|
|
||||||
|
@ -127,6 +149,10 @@ impl Compiler {
|
||||||
result.append(&mut self.compile(args[0].clone())?);
|
result.append(&mut self.compile(args[0].clone())?);
|
||||||
result.push(Instr::Call { function: "slurp".to_string() });
|
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" | "+" => {
|
"add" | "+" => {
|
||||||
let mut lhs = self.compile_atom(&args[0])?;
|
let mut lhs = self.compile_atom(&args[0])?;
|
||||||
|
@ -189,36 +215,6 @@ impl Compiler {
|
||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile_atom(&mut self, atom: &Sexpr) -> Result<Vec<Instr>, 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<Type, String> {
|
fn quoted_sexpr(cdr: &Sexpr) -> Result<Type, String> {
|
||||||
|
|
|
@ -34,7 +34,7 @@ fn compile_src(src: String, path: Option<PathBuf>, file: PathBuf, debug: bool) {
|
||||||
let file_name = match path {
|
let file_name = match path {
|
||||||
Some(path) => path,
|
Some(path) => path,
|
||||||
None => Path::new(&file).to_path_buf(),
|
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 start = Instant::now();
|
||||||
let tokens = tokenize(&cover_paren(src));
|
let tokens = tokenize(&cover_paren(src));
|
||||||
|
@ -57,14 +57,17 @@ fn compile_src(src: String, path: Option<PathBuf>, file: PathBuf, debug: bool) {
|
||||||
|
|
||||||
let elapsed = start.elapsed();
|
let elapsed = start.elapsed();
|
||||||
println!("Compiled in {}.{}s", elapsed.as_secs(), elapsed.subsec_millis());
|
println!("Compiled in {}.{}s", elapsed.as_secs(), elapsed.subsec_millis());
|
||||||
|
exit(0);
|
||||||
},
|
},
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
eprintln!("{}", err);
|
eprintln!("{}", err);
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("{}", e);
|
eprintln!("{}", e);
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ impl Type {
|
||||||
s.push('(');
|
s.push('(');
|
||||||
for (i, t) in v.iter().enumerate() {
|
for (i, t) in v.iter().enumerate() {
|
||||||
if i != 0 { s.push(' '); }
|
if i != 0 { s.push(' '); }
|
||||||
s.push_str(&t.print().to_string());
|
s.push_str(&t.print());
|
||||||
}
|
}
|
||||||
s.push(')');
|
s.push(')');
|
||||||
s
|
s
|
||||||
|
|
|
@ -9,6 +9,7 @@ pub enum Error {
|
||||||
UnknownFunctionCall(String),
|
UnknownFunctionCall(String),
|
||||||
InvalidAriphmeticOperation,
|
InvalidAriphmeticOperation,
|
||||||
FileError(String),
|
FileError(String),
|
||||||
|
Throw(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Error {
|
impl Display for Error {
|
||||||
|
@ -20,6 +21,7 @@ impl Display for Error {
|
||||||
Error::UnknownFunctionCall(function) => write!(f, "Unknown function call: {}", function),
|
Error::UnknownFunctionCall(function) => write!(f, "Unknown function call: {}", function),
|
||||||
Error::InvalidAriphmeticOperation => write!(f, "Invalid ariphmetic operation"),
|
Error::InvalidAriphmeticOperation => write!(f, "Invalid ariphmetic operation"),
|
||||||
Error::FileError(msg) => write!(f, "Could not open file: {}", msg),
|
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))),
|
Ok(_) => Ok(self.stack.push(Type::String(result))),
|
||||||
Err(e) => Err(Error::FileError(e.to_string())),
|
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())) },
|
_ => { dbg!(function); Err(Error::UnknownFunctionCall(function.to_string())) },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
(fun str "Hello, world!")
|
(fun main (do
|
||||||
|
(def str "Hello, world!")
|
||||||
(fun main
|
(print (str))))
|
||||||
(print (str)))
|
|
|
@ -1,3 +0,0 @@
|
||||||
(fun cool_number (/ (+ 345 345) 10))
|
|
||||||
(fun main
|
|
||||||
(print cool_number))
|
|
2
example/throw.blsp
Normal file
2
example/throw.blsp
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
(fun main
|
||||||
|
(throw "error :("))
|
Loading…
Reference in a new issue