aboutsummaryrefslogtreecommitdiffstats
path: root/src/vm.rs
diff options
context:
space:
mode:
authorGustav Sörnäs <gustav@sornas.net>2021-02-09 20:02:37 +0100
committerGustav Sörnäs <gustav@sornas.net>2021-02-09 20:02:37 +0100
commit0965a15e7d9c37acc5830f69dfadfa4f811802e3 (patch)
tree0e55f44d63457c8042b1c8624307e023e04fa75c /src/vm.rs
parent6db2f51d4aa52c4ab83b0c8160e6c8fc6ce00eb0 (diff)
parent1c9674e1a718397e48363743eb21638e2ccd6281 (diff)
downloadsylt-0965a15e7d9c37acc5830f69dfadfa4f811802e3.tar.gz
Merge remote-tracking branch 'origin/op-copy' into unsafe
Diffstat (limited to 'src/vm.rs')
-rw-r--r--src/vm.rs91
1 files changed, 69 insertions, 22 deletions
diff --git a/src/vm.rs b/src/vm.rs
index 37da8ca..3215797 100644
--- a/src/vm.rs
+++ b/src/vm.rs
@@ -62,6 +62,8 @@ pub struct VM {
frames: Vec<Frame>,
blobs: Vec<Rc<Blob>>,
+ constants: Vec<Value>,
+ strings: Vec<String>,
pub print_blocks: bool,
pub print_ops: bool,
@@ -96,7 +98,11 @@ impl VM {
stack_len: 0,
stack: unsafe { alloc(Layout::array::<Value>(10_000).unwrap()) as *mut Value }, //TODO fix max len
frames: Vec::new(),
+
blobs: Vec::new(),
+ constants: Vec::new(),
+ strings: Vec::new(),
+
print_blocks: false,
print_ops: false,
@@ -171,9 +177,24 @@ impl VM {
&mut self.frames[last]
}
+ fn constant(&self, slot: usize) -> &Value {
+ &self.constants[slot]
+ }
+
+ fn ty(&self, slot: usize) -> &Type {
+ match &self.constants[slot] {
+ Value::Ty(ty) => ty,
+ _ => self.crash_and_burn(),
+ }
+ }
+
+ fn string(&self, slot: usize) -> &String {
+ &self.strings[slot]
+ }
+
fn op(&self) -> Op {
let ip = self.frame().ip;
- self.frame().block.borrow().ops[ip].clone()
+ self.frame().block.borrow().ops[ip]
}
/// Stop the program, violently
@@ -236,7 +257,8 @@ impl VM {
Op::Constant(value) => {
let offset = self.frame().stack_offset;
- let value = match value {
+ let constant = self.constant(value).clone();
+ let value = match constant {
Value::Function(_, block) => {
let mut ups = Vec::new();
for (slot, is_up, _) in block.borrow().upvalues.iter() {
@@ -254,7 +276,7 @@ impl VM {
}
Value::Function(ups, block)
},
- _ => value.clone(),
+ value => value,
};
self.push(value);
}
@@ -279,21 +301,23 @@ impl VM {
Op::Get(field) => {
let inst = self.pop();
+ let field = self.string(field);
if let Value::BlobInstance(ty, values) = inst {
- let slot = self.blobs[ty].fields.get(&field).unwrap().0;
+ let slot = self.blobs[ty].fields.get(field).unwrap().0;
self.push(values.borrow()[slot].clone());
} else {
- error!(self, ErrorKind::RuntimeTypeError(Op::Get(field.clone()), vec![inst]));
+ error!(self, ErrorKind::RuntimeTypeError(op, vec![inst]));
}
}
Op::Set(field) => {
let (inst, value) = self.poppop();
+ let field = self.string(field);
if let Value::BlobInstance(ty, values) = inst {
- let slot = self.blobs[ty].fields.get(&field).unwrap().0;
+ let slot = self.blobs[ty].fields.get(field).unwrap().0;
values.borrow_mut()[slot] = value;
} else {
- error!(self, ErrorKind::RuntimeTypeError(Op::Get(field.clone()), vec![inst]));
+ error!(self, ErrorKind::RuntimeTypeError(op, vec![inst]));
}
}
@@ -468,6 +492,9 @@ impl VM {
pub(crate) fn init(&mut self, prog: &Prog) {
let block = Rc::clone(&prog.blocks[0]);
self.blobs = prog.blobs.clone();
+ self.constants = prog.constants.clone();
+ self.strings = prog.strings.clone();
+
self.extern_functions = prog.functions.clone();
self.stack_len = 0;
self.frames.clear();
@@ -509,8 +536,8 @@ impl VM {
Op::Yield => {}
- Op::Constant(ref value) => {
- match value.clone() {
+ Op::Constant(value) => {
+ match self.constant(value).clone() {
Value::Function(_, block) => {
self.push(Value::Function(Vec::new(), block.clone()));
@@ -533,14 +560,14 @@ impl VM {
} else {
if ty != suggestion {
error!(self,
- ErrorKind::TypeError(op.clone(),
+ ErrorKind::TypeError(op,
vec![ty.clone(), suggestion.clone()]),
"Failed to infer type.".to_string());
}
}
};
},
- _ => {
+ value => {
self.push(value.clone());
}
}
@@ -548,26 +575,27 @@ impl VM {
Op::Get(field) => {
let inst = self.pop();
+ let field = self.string(field);
if let Value::BlobInstance(ty, _) = inst {
- let value = Value::from(&self.blobs[ty].fields.get(&field).unwrap().1);
+ let value = Value::from(&self.blobs[ty].fields.get(field).unwrap().1);
self.push(value);
} else {
self.push(Value::Nil);
- error!(self, ErrorKind::RuntimeTypeError(Op::Get(field.clone()), vec![inst]));
+ error!(self, ErrorKind::RuntimeTypeError(op, vec![inst]));
}
}
Op::Set(field) => {
- let value = self.pop();
- let inst = self.pop();
+ let (inst, value) = self.poppop();
+ let field = self.string(field);
if let Value::BlobInstance(ty, _) = inst {
- let ty = &self.blobs[ty].fields.get(&field).unwrap().1;
+ let ty = &self.blobs[ty].fields.get(field).unwrap().1;
if ty != &Type::from(&value) {
- error!(self, ErrorKind::RuntimeTypeError(Op::Set(field.clone()), vec![inst]));
+ error!(self, ErrorKind::RuntimeTypeError(op, vec![inst]));
}
} else {
- error!(self, ErrorKind::RuntimeTypeError(Op::Set(field.clone()), vec![inst]));
+ error!(self, ErrorKind::RuntimeTypeError(op, vec![inst]));
}
}
@@ -604,7 +632,23 @@ impl VM {
self.pop();
}
- Op::Define(_) => {}
+ Op::Define(ty) => {
+ let ty = self.ty(ty);
+ let top_type = self.stack.last().unwrap().into();
+ match (ty, top_type) {
+ (Type::Unknown, top_type)
+ if top_type != Type::Unknown => {}
+ (a, b) if a != &b => {
+ error!(self,
+ ErrorKind::TypeError(
+ op,
+ vec![a.clone(), b.clone()]),
+ format!("Tried to assign a type {:?} to type {:?}.", a, b)
+ );
+ }
+ _ => {}
+ }
+ }
Op::Call(num_args) => {
let new_base = self.stack_len - 1 - num_args;
@@ -639,7 +683,7 @@ impl VM {
let stack_args: Vec<_> = stack_args.iter().map(|x| x.into()).collect();
if args != &stack_args {
error!(self,
- ErrorKind::TypeError(op.clone(), vec![]),
+ ErrorKind::TypeError(op, vec![]),
format!("Expected args of type {:?} but got {:?}.",
args, stack_args));
}
@@ -664,7 +708,7 @@ impl VM {
}
_ => {
error!(self,
- ErrorKind::TypeError(op.clone(), vec![Type::from(self.get(new_base))]),
+ ErrorKind::TypeError(op, vec![Type::from(self.get(new_base))]),
format!("Tried to call non-function {:?}", self.get(new_base)));
}
}
@@ -673,7 +717,7 @@ impl VM {
Op::JmpFalse(_) => {
match self.pop() {
Value::Bool(_) => {},
- a => { error!(self, ErrorKind::TypeError(op.clone(), vec![a.into()])) },
+ a => { error!(self, ErrorKind::TypeError(op, vec![a.into()])) },
}
}
_ => {
@@ -734,6 +778,9 @@ impl VM {
let mut errors = Vec::new();
self.blobs = prog.blobs.clone();
+ self.constants = prog.constants.clone();
+ self.strings = prog.strings.clone();
+
self.extern_functions = prog.functions.clone();
for block in prog.blocks.iter() {
errors.append(&mut self.typecheck_block(Rc::clone(block)));