main
parent
7073e57123
commit
934cebc598
@ -0,0 +1,6 @@
|
|||||||
|
condense_wildcard_suffixes = true
|
||||||
|
format_strings = true
|
||||||
|
reorder_impl_items = true
|
||||||
|
group_imports = "StdExternalCrate"
|
||||||
|
use_field_init_shorthand = true
|
||||||
|
wrap_comments = true
|
@ -1,25 +1,13 @@
|
|||||||
use chunk::{Chunk, OpCode};
|
use chunk::{Chunk, OpCode};
|
||||||
use vm::VM;
|
|
||||||
|
|
||||||
pub mod chunk;
|
mod chunk;
|
||||||
pub mod vec;
|
mod value;
|
||||||
pub mod vm;
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut chunk = Chunk::default();
|
let mut chunk = Chunk::default();
|
||||||
|
|
||||||
chunk.write_constant(1.2, 123);
|
chunk.push_constant(1.2, 123);
|
||||||
|
chunk.push(OpCode::Return, 123);
|
||||||
|
|
||||||
chunk.write(OpCode::Return as u8, 123);
|
chunk.disassemble("test chunk");
|
||||||
|
|
||||||
// for i in 0..=u8::MAX {
|
|
||||||
// chunk.write_constant(i.into(), 123);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// chunk.write_constant(0.0, 123);
|
|
||||||
|
|
||||||
// chunk.disassemble("test chunk");
|
|
||||||
|
|
||||||
let vm = VM::new(chunk);
|
|
||||||
vm.interpret();
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
pub type Value = f64;
|
@ -1,118 +0,0 @@
|
|||||||
// https://doc.rust-lang.org/nomicon/vec/vec.html
|
|
||||||
|
|
||||||
use std::alloc::{self, Layout};
|
|
||||||
use std::marker::PhantomData;
|
|
||||||
use std::mem;
|
|
||||||
use std::ops::{Deref, DerefMut};
|
|
||||||
use std::ptr::{self, NonNull};
|
|
||||||
|
|
||||||
pub struct Vec<T> {
|
|
||||||
ptr: NonNull<T>,
|
|
||||||
cap: usize,
|
|
||||||
len: usize,
|
|
||||||
_marker: PhantomData<T>,
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe impl<T: Send> Send for Vec<T> {}
|
|
||||||
unsafe impl<T: Sync> Sync for Vec<T> {}
|
|
||||||
|
|
||||||
impl<T> Vec<T> {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
assert!(mem::size_of::<T>() != 0, "We're not ready to handle ZSTs");
|
|
||||||
Vec {
|
|
||||||
ptr: NonNull::dangling(),
|
|
||||||
len: 0,
|
|
||||||
cap: 0,
|
|
||||||
_marker: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push(&mut self, elem: T) {
|
|
||||||
if self.len == self.cap {
|
|
||||||
self.grow();
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
ptr::write(self.ptr.as_ptr().add(self.len), elem);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can't fail, we'll OOM first.
|
|
||||||
self.len += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pop(&mut self) -> Option<T> {
|
|
||||||
if self.len == 0 {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
self.len -= 1;
|
|
||||||
unsafe { Some(ptr::read(self.ptr.as_ptr().add(self.len))) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn grow(&mut self) {
|
|
||||||
let (new_cap, new_layout) = if self.cap == 0 {
|
|
||||||
(1, Layout::array::<T>(1).unwrap())
|
|
||||||
} else {
|
|
||||||
// This can't overflow since self.cap <= isize::MAX.
|
|
||||||
let new_cap = 2 * self.cap;
|
|
||||||
|
|
||||||
// `Layout::array` checks that the number of bytes is <= usize::MAX,
|
|
||||||
// but this is redundant since old_layout.size() <= isize::MAX,
|
|
||||||
// so the `unwrap` should never fail.
|
|
||||||
let new_layout = Layout::array::<T>(new_cap).unwrap();
|
|
||||||
(new_cap, new_layout)
|
|
||||||
};
|
|
||||||
|
|
||||||
// Ensure that the new allocation doesn't exceed `isize::MAX` bytes.
|
|
||||||
assert!(
|
|
||||||
new_layout.size() <= isize::MAX as usize,
|
|
||||||
"Allocation too large"
|
|
||||||
);
|
|
||||||
|
|
||||||
let new_ptr = if self.cap == 0 {
|
|
||||||
unsafe { alloc::alloc(new_layout) }
|
|
||||||
} else {
|
|
||||||
let old_layout = Layout::array::<T>(self.cap).unwrap();
|
|
||||||
let old_ptr = self.ptr.as_ptr() as *mut u8;
|
|
||||||
unsafe { alloc::realloc(old_ptr, old_layout, new_layout.size()) }
|
|
||||||
};
|
|
||||||
|
|
||||||
// If allocation fails, `new_ptr` will be null, in which case we abort.
|
|
||||||
self.ptr = match NonNull::new(new_ptr as *mut T) {
|
|
||||||
Some(p) => p,
|
|
||||||
None => alloc::handle_alloc_error(new_layout),
|
|
||||||
};
|
|
||||||
self.cap = new_cap;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Drop for Vec<T> {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
if self.cap != 0 {
|
|
||||||
while self.pop().is_some() {}
|
|
||||||
let layout = Layout::array::<T>(self.cap).unwrap();
|
|
||||||
unsafe {
|
|
||||||
alloc::dealloc(self.ptr.as_ptr() as *mut u8, layout);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Deref for Vec<T> {
|
|
||||||
type Target = [T];
|
|
||||||
fn deref(&self) -> &[T] {
|
|
||||||
unsafe { std::slice::from_raw_parts(self.ptr.as_ptr(), self.len) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> DerefMut for Vec<T> {
|
|
||||||
fn deref_mut(&mut self) -> &mut [T] {
|
|
||||||
unsafe { std::slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Default for Vec<T> {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::new()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
use std::ptr;
|
|
||||||
|
|
||||||
use anyhow::Result;
|
|
||||||
use thiserror::Error;
|
|
||||||
|
|
||||||
use crate::chunk::Chunk;
|
|
||||||
|
|
||||||
pub struct VM {
|
|
||||||
chunk: Chunk,
|
|
||||||
ip: *const u8,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
|
||||||
pub enum DataStoreError {
|
|
||||||
#[error("")]
|
|
||||||
CompileError,
|
|
||||||
#[error("")]
|
|
||||||
RuntimeError,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl VM {
|
|
||||||
pub fn new(chunk: Chunk) -> Self {
|
|
||||||
VM { chunk, ip: &chunk.code.ptr }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn interpret(&self) -> Result<()> {
|
|
||||||
self.run()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run(&self) -> Result<()> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in new issue