aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEdvard Thörnros <edvard.thornros@gmail.com>2021-01-28 20:16:08 +0100
committerEdvard Thörnros <edvard.thornros@gmail.com>2021-01-28 20:16:08 +0100
commit92075e6bc23d63d62e2d0caf83acbf81ad0ccd99 (patch)
tree1c123b8919c155688fda1100c01cf84a0049c010 /src
parentcf42ef9b25361255ad23ae084164303657473608 (diff)
downloadsylt-92075e6bc23d63d62e2d0caf83acbf81ad0ccd99.tar.gz
Pass blobs all the way
Diffstat (limited to 'src')
-rw-r--r--src/compiler.rs52
-rw-r--r--src/lib.rs3
-rw-r--r--src/vm.rs13
3 files changed, 47 insertions, 21 deletions
diff --git a/src/compiler.rs b/src/compiler.rs
index 9fb7e8c..2302e76 100644
--- a/src/compiler.rs
+++ b/src/compiler.rs
@@ -49,6 +49,13 @@ nextable_enum!(Prec {
Factor,
});
+
+#[derive(Debug, Clone)]
+pub struct Prog {
+ pub blocks: Vec<Rc<RefCell<Block>>>,
+ pub blobs: Vec<Rc<Blob>>,
+}
+
#[derive(Debug, Clone)]
pub enum Type {
Void,
@@ -167,11 +174,10 @@ impl Frame {
}
#[derive(Debug, Clone)]
-struct Blob {
+pub struct Blob {
name: String,
- name_to_field: HashMap<String, usize>,
- field: Vec<Type>,
+ name_to_field: HashMap<String, Type>,
}
impl Blob {
@@ -179,19 +185,17 @@ impl Blob {
Self {
name: String::from(name),
name_to_field: HashMap::new(),
- field: Vec::new(),
}
}
- pub fn add_field(&mut self, name: &str, ty: Type) -> Result<usize, ()> {
- let slot = self.field.len();
+ pub fn add_field(&mut self, name: &str, ty: Type) -> Result<(), ()> {
let entry = self.name_to_field.entry(String::from(name));
if matches!(entry, Entry::Occupied(_)) {
- return Err(());
+ Err(())
+ } else {
+ entry.or_insert(ty);
+ Ok(())
}
- entry.or_insert(slot);
- self.field.push(ty);
- Ok(slot)
}
}
@@ -508,6 +512,12 @@ impl Compiler {
return Self::find_and_capture_variable(name, self.frames.iter_mut().rev());
}
+ fn find_blob(&self, name: &str) -> Option<usize> {
+ self.blobs.iter().enumerate()
+ .find(|(_, x)| x.name == name)
+ .map(|(i, _)| i)
+ }
+
fn call(&mut self, block: &mut Block) {
expect!(self, Token::LeftParen, "Expected '(' at start of function call.");
@@ -634,6 +644,11 @@ impl Compiler {
if self.peek() == Token::LeftParen {
self.call(block);
}
+ } else if let Some(blob) = self.find_blob(&name) {
+ // block.add(Op::Blob(blob));
+ if self.peek() == Token::LeftParen {
+ self.call(block);
+ }
} else {
error!(self, format!("Using undefined variable {}.", name));
}
@@ -857,9 +872,9 @@ impl Compiler {
}
}
- expect!(self, Token::RightBrace, "Expected '}' 'blob' body. AKA '}'.");
+ expect!(self, Token::RightBrace, "Expected '}' after 'blob' body. AKA '}'.");
- println!("Blob: {:?}", blob);
+ self.blobs.push(blob);
}
fn statement(&mut self, block: &mut Block) {
@@ -895,7 +910,7 @@ impl Compiler {
self.assign(&name, block);
}
- (Token::Blob, Token::Identifier(name), ..) => {
+ (Token::Blob, Token::Identifier(_), ..) => {
self.blob_statement(block);
}
@@ -932,7 +947,8 @@ impl Compiler {
}
- pub fn compile(&mut self, name: &str, file: &Path) -> Result<Vec<Rc<RefCell<Block>>>, Vec<Error>> {
+ pub fn compile(&mut self, name: &str, file: &Path) -> Result<Prog, Vec<Error>> {
+ println!("=== START COMPILATION ===");
self.stack_mut().push(Variable {
name: String::from("/main/"),
typ: Type::Void,
@@ -956,14 +972,18 @@ impl Compiler {
self.blocks.insert(0, Rc::new(RefCell::new(block)));
+ println!("=== END COMPILATION ===");
if self.errors.is_empty() {
- Ok(self.blocks.clone())
+ Ok(Prog {
+ blocks: self.blocks.clone(),
+ blobs: Vec::new(),
+ })
} else {
Err(self.errors.clone())
}
}
}
-pub fn compile(name: &str, file: &Path, tokens: TokenStream) -> Result<Vec<Rc<RefCell<Block>>>, Vec<Error>> {
+pub fn compile(name: &str, file: &Path, tokens: TokenStream) -> Result<Prog, Vec<Error>> {
Compiler::new(file, tokens).compile(name, file)
}
diff --git a/src/lib.rs b/src/lib.rs
index e83d11f..8cf9b36 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,5 +1,4 @@
use std::path::Path;
-use std::rc::Rc;
pub mod compiler;
pub mod tokenizer;
@@ -23,7 +22,7 @@ pub fn run(tokens: TokenStream, path: &Path, print: bool) -> Result<(), Vec<Erro
Ok(blocks) => {
let mut vm = vm::VM::new().print_blocks(print).print_ops(print);
vm.typecheck(&blocks)?;
- if let Err(e) = vm.run(Rc::clone(&blocks[0])) {
+ if let Err(e) = vm.run(&blocks) {
Err(vec![e])
} else {
Ok(())
diff --git a/src/vm.rs b/src/vm.rs
index 5f7e0e3..cb30704 100644
--- a/src/vm.rs
+++ b/src/vm.rs
@@ -8,6 +8,7 @@ use std::cell::RefCell;
use crate::compiler::Type;
use crate::error::{Error, ErrorKind};
+use crate::compiler::{Prog, Blob};
macro_rules! error {
( $thing:expr, $kind:expr) => {
@@ -276,6 +277,9 @@ pub struct VM {
stack: Vec<Value>,
frames: Vec<Frame>,
+
+ blobs: Vec<Rc<Blob>>,
+
print_blocks: bool,
print_ops: bool,
}
@@ -291,6 +295,7 @@ impl VM {
upvalues: HashMap::new(),
stack: Vec::new(),
frames: Vec::new(),
+ blobs: Vec::new(),
print_blocks: false,
print_ops: false,
}
@@ -620,7 +625,9 @@ impl VM {
self.frame().block.borrow().ops[self.frame().ip]);
}
- pub fn run(&mut self, block: Rc<RefCell<Block>>) -> Result<(), Error>{
+ pub fn run(&mut self, prog: &Prog) -> Result<(), Error>{
+ let block = Rc::clone(&prog.blocks[0]);
+ self.blobs = prog.blobs.clone();
self.stack.clear();
self.frames.clear();
@@ -834,10 +841,10 @@ impl VM {
errors
}
- pub fn typecheck(&mut self, blocks: &Vec<Rc<RefCell<Block>>>) -> Result<(), Vec<Error>> {
+ pub fn typecheck(&mut self, prog: &Prog) -> Result<(), Vec<Error>> {
let mut errors = Vec::new();
- for block in blocks.iter() {
+ for block in prog.blocks.iter() {
errors.append(&mut self.typecheck_block(Rc::clone(block)));
}