1
0

Fix tests; Rename point to move; Implement lists in the VM

This commit is contained in:
Jeff 2025-02-17 10:04:31 -05:00
parent 5de44b58ee
commit 4a169bc515
20 changed files with 680 additions and 443 deletions

View File

@ -30,7 +30,7 @@ use type_checks::{check_math_type, check_math_types};
use std::{mem::replace, sync::Arc};
use crate::{
instruction::{Jump, Point, Return, TypeCode},
instruction::{Jump, Move, Return, TypeCode},
Chunk, DustError, DustString, FunctionType, Instruction, Lexer, Local, NativeFunction, Operand,
Operation, Scope, Span, Token, TokenKind, Type,
};
@ -876,8 +876,8 @@ impl<'src> Compiler<'src> {
position: self.previous_position,
})?;
let (left, push_back_left) = self.handle_binary_argument(&left_instruction);
let left_is_mutable_local = if left_instruction.operation() == Operation::POINT {
let Point { to, .. } = Point::from(left_instruction);
let left_is_mutable_local = if left_instruction.operation() == Operation::MOVE {
let Move { operand: to, .. } = Move::from(&left_instruction);
self.locals
.get(to.index() as usize)
@ -1084,8 +1084,8 @@ impl<'src> Compiler<'src> {
found: self.previous_token.to_owned(),
position: self.previous_position,
})?;
let operand_register = if left_instruction.operation() == Operation::POINT {
let Point { to, .. } = Point::from(left_instruction);
let operand_register = if left_instruction.operation() == Operation::MOVE {
let Move { operand: to, .. } = Move::from(&left_instruction);
let local = self.get_local(to.index())?;
local.register_index
@ -1239,7 +1239,7 @@ impl<'src> Compiler<'src> {
Type::String => self.next_string_register(),
_ => todo!(),
};
let point = Instruction::point(
let point = Instruction::r#move(
destination,
Operand::Register(local_register_index, local_type.type_code()),
);
@ -1756,20 +1756,21 @@ impl<'src> Compiler<'src> {
}
fn parse_implicit_return(&mut self) -> Result<(), CompileError> {
if matches!(self.get_last_operation(), Some(Operation::POINT)) {
let Point { to, .. } = Point::from(self.instructions.last().unwrap().0);
if matches!(self.get_last_operation(), Some(Operation::MOVE)) {
let last_instruction = self.instructions.last().unwrap().0;
let Move { operand, .. } = Move::from(&last_instruction);
let (point, r#type, position) = self.instructions.pop().unwrap();
let (r#move, r#type, position) = self.instructions.pop().unwrap();
let (should_return, target_register) = if r#type == Type::None {
(false, 0)
} else {
(true, to.index())
(true, operand.index())
};
let r#return =
Instruction::r#return(should_return, target_register, r#type.type_code());
if !should_return {
self.instructions.push((point, r#type.clone(), position));
self.instructions.push((r#move, r#type.clone(), position));
}
self.emit_instruction(r#return, r#type, self.current_position);

View File

@ -10,8 +10,8 @@ pub struct Close {
pub r#type: TypeCode,
}
impl From<Instruction> for Close {
fn from(instruction: Instruction) -> Self {
impl From<&Instruction> for Close {
fn from(instruction: &Instruction) -> Self {
Close {
from: instruction.b_field(),
to: instruction.c_field(),

View File

@ -93,11 +93,11 @@ mod load_function;
mod load_list;
mod load_self;
mod modulo;
mod r#move;
mod multiply;
mod negate;
mod not;
mod operation;
mod point;
mod r#return;
mod subtract;
mod test;
@ -123,7 +123,7 @@ pub use multiply::Multiply;
pub use negate::Negate;
pub use not::Not;
pub use operation::Operation;
pub use point::Point;
pub use r#move::Move;
pub use r#return::Return;
pub use subtract::Subtract;
pub use test::Test;
@ -183,7 +183,7 @@ impl From<&Instruction> for InstructionFields {
impl Default for InstructionFields {
fn default() -> Self {
InstructionFields {
operation: Operation::POINT,
operation: Operation::MOVE,
a_field: 0,
b_field: 0,
c_field: 0,
@ -277,8 +277,8 @@ impl Instruction {
pub fn as_operand(&self) -> Operand {
match self.operation() {
Operation::POINT => {
let Point { to, .. } = Point::from(*self);
Operation::MOVE => {
let Move { operand: to, .. } = Move::from(self);
Operand::Register(to.index(), to.as_type())
}
@ -370,8 +370,11 @@ impl Instruction {
Instruction(Operation::NO_OP.0 as u64)
}
pub fn point(destination: u16, to: Operand) -> Instruction {
Instruction::from(Point { destination, to })
pub fn r#move(destination: u16, to: Operand) -> Instruction {
Instruction::from(Move {
destination,
operand: to,
})
}
pub fn close(from: u16, to: u16, r#type: TypeCode) -> Instruction {
@ -605,7 +608,7 @@ impl Instruction {
pub fn yields_value(&self) -> bool {
match self.operation() {
Operation::POINT
Operation::MOVE
| Operation::LOAD_ENCODED
| Operation::LOAD_CONSTANT
| Operation::LOAD_FUNCTION
@ -640,8 +643,8 @@ impl Instruction {
let operation = self.operation();
match operation {
Operation::POINT => Point::from(*self).to_string(),
Operation::CLOSE => Close::from(*self).to_string(),
Operation::MOVE => Move::from(self).to_string(),
Operation::CLOSE => Close::from(self).to_string(),
Operation::LOAD_ENCODED => LoadEncoded::from(*self).to_string(),
Operation::LOAD_CONSTANT => LoadConstant::from(*self).to_string(),
Operation::LOAD_FUNCTION => LoadFunction::from(*self).to_string(),

View File

@ -4,26 +4,26 @@ use crate::{Instruction, Operation};
use super::{InstructionFields, Operand, TypeCode};
pub struct Point {
pub struct Move {
pub destination: u16,
pub to: Operand,
pub operand: Operand,
}
impl From<Instruction> for Point {
fn from(instruction: Instruction) -> Self {
Point {
impl From<&Instruction> for Move {
fn from(instruction: &Instruction) -> Self {
Move {
destination: instruction.a_field(),
to: instruction.b_as_operand(),
operand: instruction.b_as_operand(),
}
}
}
impl From<Point> for Instruction {
fn from(r#move: Point) -> Self {
let operation = Operation::POINT;
impl From<Move> for Instruction {
fn from(r#move: Move) -> Self {
let operation = Operation::MOVE;
let a_field = r#move.destination;
let (b_field, b_is_constant) = r#move.to.as_index_and_constant_flag();
let b_type = r#move.to.as_type();
let (b_field, b_is_constant) = r#move.operand.as_index_and_constant_flag();
let b_type = r#move.operand.as_type();
InstructionFields {
operation,
@ -37,9 +37,12 @@ impl From<Point> for Instruction {
}
}
impl Display for Point {
impl Display for Move {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
let Point { destination, to } = self;
let Move {
destination,
operand: to,
} = self;
match to.as_type() {
TypeCode::BOOLEAN => write!(f, "R_BOOL_{destination} -> {to}"),
@ -50,7 +53,7 @@ impl Display for Point {
TypeCode::STRING => write!(f, "R_STR_{destination} -> {to}"),
unsupported => write!(
f,
"Unsupported type code: {unsupported} for Point instruction"
"Unsupported type code: {unsupported} for MOVE instruction"
),
}
}

View File

@ -12,7 +12,7 @@ impl Operation {
pub const NO_OP: Operation = Operation(0);
// Stack manipulation
pub const POINT: Operation = Operation(1);
pub const MOVE: Operation = Operation(1);
pub const CLOSE: Operation = Operation(2);
// Loaders
@ -55,7 +55,7 @@ impl Operation {
pub fn name(&self) -> &'static str {
match *self {
Self::NO_OP => "NO_OP",
Self::POINT => "POINT",
Self::MOVE => "MOVE",
Self::CLOSE => "CLOSE",
Self::LOAD_ENCODED => "LOAD_ENCODED",
Self::LOAD_CONSTANT => "LOAD_CONSTANT",

View File

@ -27,6 +27,7 @@
//!
//! println!("{}", report);
//! ```
#![feature(get_many_mut)]
pub mod chunk;
pub mod compiler;
@ -40,17 +41,17 @@ pub mod value;
pub mod vm;
pub use crate::chunk::{Chunk, Disassembler, Local, Scope};
pub use crate::compiler::{CompileError, Compiler, compile};
pub use crate::compiler::{compile, CompileError, Compiler};
pub use crate::dust_error::{AnnotatedError, DustError};
pub use crate::instruction::{Instruction, Operand, Operation};
pub use crate::lexer::{LexError, Lexer, lex};
pub use crate::lexer::{lex, LexError, Lexer};
pub use crate::native_function::{NativeFunction, NativeFunctionError};
pub use crate::token::{Token, TokenKind, TokenOwned};
pub use crate::r#type::{EnumType, FunctionType, StructType, Type, TypeConflict};
pub use crate::token::{Token, TokenKind, TokenOwned};
pub use crate::value::{
AbstractList, ConcreteValue, DustString, Function, RangeValue, Value, ValueError,
};
pub use crate::vm::{Vm, run};
pub use crate::vm::{run, Vm};
use std::fmt::Display;

View File

@ -8,7 +8,11 @@ pub fn panic(data: &mut Thread, _: usize, argument_range: Range<usize>) {
let mut message = format!("Dust panic at {position}!");
for register_index in argument_range {
let string = current_frame.get_string_from_register(register_index);
let string = current_frame
.registers
.strings
.get(register_index)
.as_value();
message.push_str(string);
message.push('\n');

View File

@ -27,7 +27,11 @@ pub fn write(data: &mut Thread, _: usize, argument_range: Range<usize>) {
let mut stdout = stdout();
for register_index in argument_range {
let string = current_frame.get_string_from_register(register_index);
let string = current_frame
.registers
.strings
.get(register_index)
.as_value();
let _ = stdout.write(string.as_bytes());
}
@ -39,7 +43,11 @@ pub fn write_line(data: &mut Thread, _: usize, argument_range: Range<usize>) {
let mut stdout = stdout().lock();
for register_index in argument_range {
let string = current_frame.get_string_from_register(register_index);
let string = current_frame
.registers
.strings
.get(register_index)
.as_value();
let _ = stdout.write(string.as_bytes());
}

View File

@ -14,17 +14,21 @@ pub fn random_int(data: &mut Thread, destination: usize, argument_range: Range<u
let register_index = argument_range_iter
.next()
.unwrap_or_else(|| panic!("No argument was passed to \"random_int\""));
let integer = current_frame.get_integer_from_register(register_index);
let integer = current_frame
.registers
.integers
.get(register_index)
.copy_value();
if min.is_none() {
min = Some(integer);
} else {
if let Some(min) = min {
break (min, integer);
} else {
min = Some(integer);
}
}
};
let random_integer = rand::thread_rng().gen_range(min.unwrap()..max);
let random_integer = rand::thread_rng().gen_range(min..max);
current_frame
.registers

View File

@ -13,6 +13,7 @@ use crate::instruction::TypeCode;
#[derive(Clone, Default, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(tag = "Type", content = "Value")]
pub enum Type {
Any,
Boolean,
Byte,
Character,
@ -168,6 +169,7 @@ impl Type {
impl Display for Type {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
Type::Any => write!(f, "any"),
Type::Boolean => write!(f, "bool"),
Type::Byte => write!(f, "byte"),
Type::Character => write!(f, "char"),
@ -231,6 +233,8 @@ impl PartialOrd for Type {
impl Ord for Type {
fn cmp(&self, other: &Self) -> Ordering {
match (self, other) {
(Type::Any, Type::Any) => Ordering::Equal,
(Type::Any, _) => Ordering::Greater,
(Type::Boolean, Type::Boolean) => Ordering::Equal,
(Type::Boolean, _) => Ordering::Greater,
(Type::Byte, Type::Byte) => Ordering::Equal,

View File

@ -5,7 +5,7 @@ use crate::{
vm::{Pointer, Thread},
};
use super::DustString;
use super::{ConcreteValue, DustString};
#[derive(Clone, Debug, PartialEq, PartialOrd)]
pub struct AbstractList {
@ -20,7 +20,7 @@ impl AbstractList {
display.push('[');
for (i, pointer) in self.item_pointers.iter().enumerate() {
for (i, pointer) in self.item_pointers.iter().copied().enumerate() {
if i > 0 {
display.push_str(", ");
}
@ -44,6 +44,71 @@ impl AbstractList {
display
}
pub fn to_concrete(&self, thread: &Thread) -> ConcreteValue {
let mut concrete_list = Vec::with_capacity(self.item_pointers.len());
match self.item_type {
TypeCode::BOOLEAN => {
for pointer in &self.item_pointers {
let boolean = thread.current_frame().get_boolean_from_pointer(*pointer);
concrete_list.push(ConcreteValue::Boolean(boolean));
}
}
TypeCode::BYTE => {
for pointer in &self.item_pointers {
let byte = thread.current_frame().get_byte_from_pointer(*pointer);
concrete_list.push(ConcreteValue::Byte(byte));
}
}
TypeCode::CHARACTER => {
for pointer in &self.item_pointers {
let character = thread.current_frame().get_character_from_pointer(*pointer);
concrete_list.push(ConcreteValue::Character(character));
}
}
TypeCode::FLOAT => {
for pointer in &self.item_pointers {
let float = thread.current_frame().get_float_from_pointer(*pointer);
concrete_list.push(ConcreteValue::Float(float));
}
}
TypeCode::INTEGER => {
for pointer in &self.item_pointers {
let integer = thread.current_frame().get_integer_from_pointer(*pointer);
concrete_list.push(ConcreteValue::Integer(integer));
}
}
TypeCode::STRING => {
for pointer in &self.item_pointers {
let string = thread
.current_frame()
.get_string_from_pointer(*pointer)
.clone();
concrete_list.push(ConcreteValue::String(string));
}
}
TypeCode::LIST => {
for pointer in &self.item_pointers {
let list = thread
.current_frame()
.get_list_from_pointer(pointer)
.to_concrete(thread);
concrete_list.push(list);
}
}
_ => todo!(),
}
ConcreteValue::List(concrete_list)
}
}
impl Default for AbstractList {

View File

@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
use smartstring::{LazyCompact, SmartString};
use tracing::trace;
use crate::{Type, Value, instruction::TypeCode};
use crate::{Type, Value};
use super::RangeValue;
@ -18,10 +18,7 @@ pub enum ConcreteValue {
Character(char),
Float(f64),
Integer(i64),
List {
items: Vec<ConcreteValue>,
item_type: TypeCode,
},
List(Vec<ConcreteValue>),
Range(RangeValue),
String(DustString),
}
@ -31,11 +28,8 @@ impl ConcreteValue {
Value::Concrete(self)
}
pub fn list<T: Into<Vec<ConcreteValue>>>(into_items: T, type_code: TypeCode) -> Self {
ConcreteValue::List {
items: into_items.into(),
item_type: type_code,
}
pub fn list<T: Into<Vec<ConcreteValue>>>(into_items: T) -> Self {
ConcreteValue::List(into_items.into())
}
pub fn string<T: Into<SmartString<LazyCompact>>>(to_string: T) -> Self {
@ -91,8 +85,8 @@ impl ConcreteValue {
}
pub fn as_list(&self) -> Option<&Vec<ConcreteValue>> {
if let ConcreteValue::List { items, .. } = self {
Some(items)
if let ConcreteValue::List(list) = self {
Some(list)
} else {
None
}
@ -117,7 +111,7 @@ impl ConcreteValue {
ConcreteValue::Character(_) => Type::Character,
ConcreteValue::Float(_) => Type::Float,
ConcreteValue::Integer(_) => Type::Integer,
ConcreteValue::List { item_type, .. } => Type::List(*item_type),
ConcreteValue::List(items) => items.first().map_or(Type::Any, |item| item.r#type()),
ConcreteValue::Range(range) => range.r#type(),
ConcreteValue::String(_) => Type::String,
}
@ -134,10 +128,7 @@ impl Clone for ConcreteValue {
ConcreteValue::Character(character) => ConcreteValue::Character(*character),
ConcreteValue::Float(float) => ConcreteValue::Float(*float),
ConcreteValue::Integer(integer) => ConcreteValue::Integer(*integer),
ConcreteValue::List { items, item_type } => ConcreteValue::List {
items: items.clone(),
item_type: *item_type,
},
ConcreteValue::List(items) => ConcreteValue::List(items.clone()),
ConcreteValue::Range(range) => ConcreteValue::Range(*range),
ConcreteValue::String(string) => ConcreteValue::String(string.clone()),
}
@ -160,7 +151,7 @@ impl Display for ConcreteValue {
Ok(())
}
ConcreteValue::Integer(integer) => write!(f, "{integer}"),
ConcreteValue::List { items, .. } => {
ConcreteValue::List(items) => {
write!(f, "[")?;
for (index, item) in items.iter().enumerate() {

View File

@ -1,8 +1,7 @@
use std::{
cell::{RefCell, RefMut},
fmt::{self, Debug, Display, Formatter},
ops::{Add, Index, IndexMut},
rc::Rc,
ops::{Index, IndexMut, RangeInclusive},
sync::Arc,
};
use smallvec::SmallVec;
@ -11,14 +10,14 @@ use crate::{AbstractList, Chunk, DustString, Function};
#[derive(Debug)]
pub struct CallFrame {
pub chunk: Rc<Chunk>,
pub chunk: Arc<Chunk>,
pub ip: usize,
pub return_register: u16,
pub registers: RegisterTable,
}
impl CallFrame {
pub fn new(chunk: Rc<Chunk>, return_register: u16) -> Self {
pub fn new(chunk: Arc<Chunk>, return_register: u16) -> Self {
let registers = RegisterTable {
booleans: RegisterList::new(chunk.boolean_register_count as usize),
bytes: RegisterList::new(chunk.byte_register_count as usize),
@ -38,129 +37,81 @@ impl CallFrame {
}
}
pub fn get_boolean_from_register(&self, register_index: usize) -> bool {
let register = self.registers.booleans.get(register_index);
match register {
Register::Value { value, .. } => *value,
Register::Pointer { pointer, .. } => self.get_boolean_from_pointer(pointer),
}
}
pub fn get_boolean_from_pointer(&self, pointer: &Pointer) -> bool {
pub fn get_boolean_from_pointer(&self, pointer: Pointer) -> bool {
match pointer {
Pointer::Register(register_index) => self.get_boolean_from_register(*register_index),
Pointer::Register(register_index) => {
*self.registers.booleans.get(register_index).as_value()
}
Pointer::Constant(_) => panic!("Attempted to get boolean from constant pointer"),
}
}
pub fn get_byte_from_register(&self, register_index: usize) -> u8 {
let register = self.registers.bytes.get(register_index);
match register {
Register::Value { value, .. } => *value,
Register::Pointer { pointer, .. } => self.get_byte_from_pointer(pointer),
}
}
pub fn get_byte_from_pointer(&self, pointer: &Pointer) -> u8 {
pub fn get_byte_from_pointer(&self, pointer: Pointer) -> u8 {
match pointer {
Pointer::Register(register_index) => self.get_byte_from_register(*register_index),
Pointer::Register(register_index) => {
*self.registers.bytes.get(register_index).as_value()
}
Pointer::Constant(_) => panic!("Attempted to get byte from constant pointer"),
}
}
pub fn get_character_from_register(&self, register_index: usize) -> char {
let register = self.registers.characters.get(register_index);
match register {
Register::Value { value, .. } => *value,
Register::Pointer { pointer, .. } => self.get_character_from_pointer(pointer),
}
}
pub fn get_character_from_pointer(&self, pointer: &Pointer) -> char {
pub fn get_character_from_pointer(&self, pointer: Pointer) -> char {
match pointer {
Pointer::Register(register_index) => self.get_character_from_register(*register_index),
Pointer::Constant(constant_index) => self.get_character_constant(*constant_index),
Pointer::Register(register_index) => {
*self.registers.characters.get(register_index).as_value()
}
Pointer::Constant(constant_index) => self.get_character_constant(constant_index),
}
}
pub fn get_character_constant(&self, constant_index: usize) -> char {
let constant = if cfg!(debug_assertions) {
self.chunk.character_constants.get(constant_index).unwrap()
if cfg!(debug_assertions) {
*self.chunk.character_constants.get(constant_index).unwrap()
} else {
unsafe { self.chunk.character_constants.get_unchecked(constant_index) }
};
*constant
}
pub fn get_float_from_register(&self, register_index: usize) -> f64 {
let register = self.registers.floats.get(register_index);
match register {
Register::Value { value, .. } => *value,
Register::Pointer { pointer, .. } => self.get_float_from_pointer(pointer),
unsafe { *self.chunk.character_constants.get_unchecked(constant_index) }
}
}
pub fn get_float_from_pointer(&self, pointer: &Pointer) -> f64 {
pub fn get_float_from_pointer(&self, pointer: Pointer) -> f64 {
match pointer {
Pointer::Register(register_index) => self.get_float_from_register(*register_index),
Pointer::Constant(constant_index) => self.get_float_constant(*constant_index),
Pointer::Register(register_index) => {
*self.registers.floats.get(register_index).as_value()
}
Pointer::Constant(constant_index) => self.get_float_constant(constant_index),
}
}
pub fn get_float_constant(&self, constant_index: usize) -> f64 {
let constant = if cfg!(debug_assertions) {
self.chunk.float_constants.get(constant_index).unwrap()
if cfg!(debug_assertions) {
*self.chunk.float_constants.get(constant_index).unwrap()
} else {
unsafe { self.chunk.float_constants.get_unchecked(constant_index) }
};
*constant
}
pub fn get_integer_from_register(&self, register_index: usize) -> i64 {
let register = self.registers.integers.get(register_index);
match register {
Register::Value { value, .. } => *value,
Register::Pointer { pointer, .. } => self.get_integer_from_pointer(pointer),
unsafe { *self.chunk.float_constants.get_unchecked(constant_index) }
}
}
pub fn get_integer_from_pointer(&self, pointer: &Pointer) -> i64 {
pub fn get_integer_from_pointer(&self, pointer: Pointer) -> i64 {
match pointer {
Pointer::Register(register_index) => self.get_integer_from_register(*register_index),
Pointer::Constant(constant_index) => self.get_integer_constant(*constant_index),
Pointer::Register(register_index) => {
*self.registers.integers.get(register_index).as_value()
}
Pointer::Constant(constant_index) => self.get_integer_constant(constant_index),
}
}
pub fn get_integer_constant(&self, constant_index: usize) -> i64 {
let constant = if cfg!(debug_assertions) {
self.chunk.integer_constants.get(constant_index).unwrap()
if cfg!(debug_assertions) {
*self.chunk.integer_constants.get(constant_index).unwrap()
} else {
unsafe { self.chunk.integer_constants.get_unchecked(constant_index) }
};
*constant
}
pub fn get_string_from_register(&self, register_index: usize) -> &DustString {
let register = self.registers.strings.get(register_index);
match register {
Register::Value { value, .. } => value,
Register::Pointer { pointer, .. } => self.get_string_from_pointer(pointer),
unsafe { *self.chunk.integer_constants.get_unchecked(constant_index) }
}
}
pub fn get_string_from_pointer(&self, pointer: &Pointer) -> &DustString {
pub fn get_string_from_pointer(&self, pointer: Pointer) -> &DustString {
match pointer {
Pointer::Register(register_index) => self.get_string_from_register(*register_index),
Pointer::Constant(constant_index) => self.get_string_constant(*constant_index),
Pointer::Register(register_index) => {
self.registers.strings.get(register_index).as_value()
}
Pointer::Constant(constant_index) => self.get_string_constant(constant_index),
}
}
@ -172,52 +123,20 @@ impl CallFrame {
}
}
pub fn get_list_from_register(&self, register_index: usize) -> &AbstractList {
let register = self.registers.lists.get(register_index);
match register {
Register::Value { value, .. } => value,
Register::Pointer { pointer, .. } => self.get_list_from_pointer(pointer),
}
}
pub fn get_list_from_register_mut(&mut self, register_index: usize) -> &mut AbstractList {
let register = self.registers.lists.get_mut(register_index);
match register {
Register::Value { value, .. } => value,
Register::Pointer { .. } => panic!("Attempted to get mutable list from pointer"),
}
}
pub fn get_list_from_pointer(&self, pointer: &Pointer) -> &AbstractList {
match pointer {
Pointer::Register(register_index) => self.get_list_from_register(*register_index),
Pointer::Register(register_index) => {
self.registers.lists.get(*register_index).as_value()
}
Pointer::Constant(_) => panic!("Attempted to get list from constant pointer"),
}
}
pub fn get_function_from_register(&self, register_index: usize) -> &Function {
let register = self.registers.functions.get(register_index);
match register {
Register::Value { value, .. } => value,
Register::Pointer { pointer, .. } => self.get_function_from_pointer(pointer),
}
}
pub fn get_function_from_register_mut(&mut self, register_index: usize) -> &mut Function {
let register = self.registers.functions.get_mut(register_index);
match register {
Register::Value { value, .. } => value,
Register::Pointer { .. } => panic!("Attempted to get mutable function from pointer"),
}
}
pub fn get_function_from_pointer(&self, pointer: &Pointer) -> &Function {
match pointer {
Pointer::Register(register_index) => self.get_function_from_register(*register_index),
Pointer::Register(register_index) => {
self.registers.functions.get(*register_index).as_value()
}
Pointer::Constant(_) => panic!("Attempted to get function from constant pointer"),
}
}
@ -276,6 +195,16 @@ where
}
}
pub fn get_many_mut(&mut self, indices: RangeInclusive<usize>) -> &mut [Register<T>] {
let registers = if cfg!(debug_assertions) {
self.registers.get_many_mut([indices]).unwrap()
} else {
unsafe { self.registers.get_many_unchecked_mut([indices]) }
};
registers[0]
}
pub fn get_mut(&mut self, index: usize) -> &mut Register<T> {
if cfg!(debug_assertions) {
let length = self.registers.len();
@ -302,6 +231,18 @@ where
}
}
pub fn close_many(&mut self, indices: RangeInclusive<usize>) {
let registers = if cfg!(debug_assertions) {
&mut self.registers.get_many_mut([indices]).unwrap()[0]
} else {
unsafe { &mut self.registers.get_many_unchecked_mut([indices])[0] }
};
for register in registers.iter_mut() {
register.close();
}
}
pub fn is_closed(&self, index: usize) -> bool {
if cfg!(debug_assertions) {
self.registers.get(index).unwrap().is_closed()
@ -325,66 +266,56 @@ impl<T> IndexMut<usize> for RegisterList<T> {
}
}
#[derive(Clone, Debug)]
pub enum Register<T> {
Value { value: T, is_closed: bool },
Pointer { pointer: Pointer, is_closed: bool },
#[derive(Clone, Copy, Debug)]
pub struct Register<T> {
value: T,
is_closed: bool,
}
impl<T> Register<T> {
pub fn value(value: T) -> Self {
Self::Value {
Self {
value,
is_closed: false,
}
}
pub fn is_closed(&self) -> bool {
match self {
Self::Value { is_closed, .. } => *is_closed,
Self::Pointer { is_closed, .. } => *is_closed,
}
self.is_closed
}
pub fn close(&mut self) {
match self {
Self::Value { is_closed, .. } => *is_closed = true,
Self::Pointer { is_closed, .. } => *is_closed = true,
}
self.is_closed = true;
}
pub fn set(&mut self, new_value: T) {
match self {
Self::Value {
value: old_value, ..
} => *old_value = new_value,
Self::Pointer { is_closed, .. } => {
*self = Self::Value {
value: new_value,
is_closed: *is_closed,
}
}
}
self.value = new_value;
}
pub fn as_value(&self) -> &T {
match self {
Self::Value { value, .. } => value,
Self::Pointer { .. } => panic!("Attempted to use pointer as value"),
}
&self.value
}
pub fn as_value_mut(&mut self) -> &mut T {
match self {
Self::Value { value, .. } => value,
Self::Pointer { .. } => panic!("Attempted to use pointer as value"),
}
&mut self.value
}
}
impl<T: Copy> Register<T> {
pub fn copy_value(&self) -> T {
self.value
}
}
impl<T: Clone> Register<T> {
pub fn clone_value(&self) -> T {
self.value.clone()
}
}
impl<T: Default> Default for Register<T> {
fn default() -> Self {
Self::Value {
Self {
value: Default::default(),
is_closed: false,
}

View File

@ -3,7 +3,7 @@
mod call_frame;
mod thread;
use std::{rc::Rc, thread::Builder};
use std::{sync::Arc, thread::Builder};
pub use call_frame::{CallFrame, Pointer, Register, RegisterTable};
pub use thread::Thread;
@ -32,6 +32,7 @@ impl Vm {
pub fn run(self) -> Option<Value> {
let span = span!(Level::INFO, "Run");
let _enter = span.enter();
let thread_name = self
.main_chunk
.name
@ -43,7 +44,7 @@ impl Vm {
Builder::new()
.name(thread_name)
.spawn(move || {
let main_chunk = Rc::new(self.main_chunk);
let main_chunk = Arc::new(self.main_chunk);
let main_thread = Thread::new(main_chunk);
let return_value = main_thread.run();
let _ = tx.send(return_value);

View File

@ -1,21 +1,23 @@
use std::{rc::Rc, thread::JoinHandle};
use std::{sync::Arc, thread::JoinHandle};
use tracing::info;
use crate::{
instruction::TypeCode, vm::CallFrame, Chunk, ConcreteValue, DustString, Operation, Span, Value,
instruction::TypeCode,
vm::{CallFrame, Pointer},
AbstractList, Chunk, DustString, Operation, Span, Value,
};
pub struct Thread {
chunk: Rc<Chunk>,
chunk: Arc<Chunk>,
call_stack: Vec<CallFrame>,
_spawned_threads: Vec<JoinHandle<()>>,
}
impl Thread {
pub fn new(chunk: Rc<Chunk>) -> Self {
pub fn new(chunk: Arc<Chunk>) -> Self {
let mut call_stack = Vec::with_capacity(chunk.prototypes.len() + 1);
let main_call = CallFrame::new(Rc::clone(&chunk), 0);
let main_call = CallFrame::new(Arc::clone(&chunk), 0);
call_stack.push(main_call);
@ -52,6 +54,168 @@ impl Thread {
info!("Run instruction {}", instruction.operation());
match instruction.operation() {
Operation::MOVE => {
let source = instruction.b_field() as usize;
let destination = instruction.a_field() as usize;
let source_type = instruction.b_type();
match source_type {
TypeCode::BOOLEAN => {
let value = current_frame.registers.booleans.get(source).copy_value();
current_frame
.registers
.booleans
.get_mut(destination)
.set(value);
}
TypeCode::BYTE => {
let value = current_frame.registers.bytes.get(source).copy_value();
current_frame
.registers
.bytes
.get_mut(destination)
.set(value);
}
TypeCode::CHARACTER => {
let value = current_frame.registers.characters.get(source).copy_value();
current_frame
.registers
.characters
.get_mut(destination)
.set(value);
}
TypeCode::FLOAT => {
let value = current_frame.registers.floats.get(source).copy_value();
current_frame
.registers
.floats
.get_mut(destination)
.set(value);
}
TypeCode::INTEGER => {
let value = current_frame.registers.integers.get(source).copy_value();
current_frame
.registers
.integers
.get_mut(destination)
.set(value);
}
TypeCode::STRING => {
let value = current_frame.registers.strings.get(source).clone_value();
current_frame
.registers
.strings
.get_mut(destination)
.set(value);
}
TypeCode::LIST => {
let value = current_frame.registers.lists.get(source).clone_value();
current_frame
.registers
.lists
.get_mut(destination)
.set(value);
}
_ => todo!(),
}
}
Operation::CLOSE => {
let from = instruction.b_field() as usize;
let to = instruction.c_field() as usize;
let r#type = instruction.b_type();
match r#type {
TypeCode::BOOLEAN => {
let registers =
current_frame.registers.booleans.get_many_mut(from..=to);
for register in registers {
register.close();
}
}
TypeCode::BYTE => {
let registers = current_frame.registers.bytes.get_many_mut(from..=to);
for register in registers {
register.close();
}
}
TypeCode::CHARACTER => {
let registers =
current_frame.registers.characters.get_many_mut(from..=to);
for register in registers {
register.close();
}
}
TypeCode::FLOAT => {
let registers = current_frame.registers.floats.get_many_mut(from..=to);
for register in registers {
register.close();
}
}
TypeCode::INTEGER => {
let registers =
current_frame.registers.integers.get_many_mut(from..=to);
for register in registers {
register.close();
}
}
TypeCode::STRING => {
let registers = current_frame.registers.strings.get_many_mut(from..=to);
for register in registers {
register.close();
}
}
TypeCode::LIST => {
let registers = current_frame.registers.lists.get_many_mut(from..=to);
for register in registers {
register.close();
}
}
_ => unreachable!("Invalid CLOSE operation"),
}
}
Operation::LOAD_ENCODED => {
let destination = instruction.a_field() as usize;
let value_type = instruction.b_type();
let jump_next = instruction.c_field() != 0;
match value_type {
TypeCode::BOOLEAN => {
let boolean = instruction.b_field() != 0;
current_frame
.registers
.booleans
.set_to_new_register(destination, boolean);
}
TypeCode::BYTE => {
let byte = instruction.b_field() as u8;
current_frame
.registers
.bytes
.set_to_new_register(destination, byte);
}
_ => unreachable!(),
}
if jump_next {
current_frame.ip += 1;
}
}
Operation::LOAD_CONSTANT => {
let destination = instruction.a_field() as usize;
let constant_index = instruction.b_field() as usize;
@ -102,6 +266,139 @@ impl Thread {
current_frame.ip += 1;
}
}
Operation::LOAD_LIST => {
let destination = instruction.a_field() as usize;
let start_register = instruction.b_field() as usize;
let item_type = instruction.b_type();
let end_register = instruction.c_field() as usize;
let jump_next = instruction.d_field();
let mut item_pointers = Vec::with_capacity(end_register - start_register + 1);
match item_type {
TypeCode::BOOLEAN => {
for register_index in start_register..=end_register {
let register_is_closed =
current_frame.registers.booleans.is_closed(register_index);
if register_is_closed {
continue;
}
item_pointers.push(Pointer::Register(register_index));
}
}
TypeCode::BYTE => {
for register_index in start_register..=end_register {
let register_is_closed =
current_frame.registers.bytes.is_closed(register_index);
if register_is_closed {
continue;
}
item_pointers.push(Pointer::Register(register_index));
}
}
TypeCode::CHARACTER => {
for register_index in start_register..=end_register {
let register_is_closed =
current_frame.registers.characters.is_closed(register_index);
if register_is_closed {
continue;
}
item_pointers.push(Pointer::Register(register_index));
}
}
TypeCode::FLOAT => {
for register_index in start_register..=end_register {
let register_is_closed =
current_frame.registers.floats.is_closed(register_index);
if register_is_closed {
continue;
}
item_pointers.push(Pointer::Register(register_index));
}
}
TypeCode::INTEGER => {
for register_index in start_register..=end_register {
let register_is_closed =
current_frame.registers.integers.is_closed(register_index);
if register_is_closed {
continue;
}
item_pointers.push(Pointer::Register(register_index));
}
}
TypeCode::STRING => {
for register_index in start_register..=end_register {
let register_is_closed =
current_frame.registers.strings.is_closed(register_index);
if register_is_closed {
continue;
}
item_pointers.push(Pointer::Register(register_index));
}
}
TypeCode::LIST => {
for register_index in start_register..=end_register {
let register_is_closed =
current_frame.registers.lists.is_closed(register_index);
if register_is_closed {
continue;
}
item_pointers.push(Pointer::Register(register_index));
}
}
_ => unreachable!("Invalid LOAD_LIST operation"),
}
let list = AbstractList {
item_type,
item_pointers,
};
current_frame.registers.lists.get_mut(destination).set(list);
if jump_next {
current_frame.ip += 1;
}
}
Operation::LOAD_FUNCTION => {
let destination = instruction.a_field() as usize;
let prototype_index = instruction.b_field() as usize;
let jump_next = instruction.c_field() != 0;
let prototype = if cfg!(debug_assertions) {
current_frame.chunk.prototypes.get(prototype_index).unwrap()
} else {
unsafe {
current_frame
.chunk
.prototypes
.get_unchecked(prototype_index)
}
};
let function = prototype.as_function();
current_frame
.registers
.functions
.set_to_new_register(destination, function);
if jump_next {
current_frame.ip += 1;
}
}
Operation::LESS => match (instruction.b_type(), instruction.c_type()) {
(TypeCode::INTEGER, TypeCode::INTEGER) => {
let left = instruction.b_field() as usize;
@ -113,12 +410,12 @@ impl Thread {
let left_value = if left_is_constant {
current_frame.get_integer_constant(left)
} else {
current_frame.get_integer_from_register(left)
current_frame.registers.integers.get(left).copy_value()
};
let right_value = if right_is_constant {
current_frame.get_integer_constant(right)
} else {
current_frame.get_integer_from_register(right)
current_frame.registers.integers.get(right).copy_value()
};
let is_less_than = left_value < right_value;
@ -134,8 +431,9 @@ impl Thread {
let right_index = instruction.c_field() as usize;
let destination_index = instruction.a_field() as usize;
let left_value = current_frame.get_byte_from_register(left_index);
let right_value = current_frame.get_byte_from_register(right_index);
let left_value = current_frame.registers.bytes.get(left_index).copy_value();
let right_value =
current_frame.registers.bytes.get(right_index).copy_value();
let sum = left_value + right_value;
current_frame
@ -153,12 +451,20 @@ impl Thread {
let left_value = if left_is_constant {
current_frame.get_character_constant(left_index)
} else {
current_frame.get_character_from_register(left_index)
current_frame
.registers
.characters
.get(left_index)
.copy_value()
};
let right_value = if right_is_constant {
current_frame.get_character_constant(right_index)
} else {
current_frame.get_character_from_register(right_index)
current_frame
.registers
.characters
.get(right_index)
.copy_value()
};
let concatenated = {
let mut concatenated = DustString::from(String::with_capacity(2));
@ -184,12 +490,16 @@ impl Thread {
let left_value = if left_is_constant {
current_frame.get_character_constant(left_index)
} else {
current_frame.get_character_from_register(left_index)
current_frame
.registers
.characters
.get(left_index)
.copy_value()
};
let right_value = if right_is_constant {
current_frame.get_string_constant(right_index)
} else {
current_frame.get_string_from_register(right_index)
current_frame.registers.strings.get(right_index).as_value()
};
let concatenated = DustString::from(format!("{left_value}{right_value}"));
@ -203,8 +513,10 @@ impl Thread {
let right_index = instruction.c_field() as usize;
let destination_index = instruction.a_field() as usize;
let left_value = current_frame.get_float_from_register(left_index);
let right_value = current_frame.get_float_from_register(right_index);
let left_value =
current_frame.registers.floats.get(left_index).copy_value();
let right_value =
current_frame.registers.floats.get(right_index).copy_value();
let sum = left_value + right_value;
current_frame
@ -222,12 +534,12 @@ impl Thread {
let left_value = if left_is_constant {
current_frame.get_integer_constant(left)
} else {
current_frame.get_integer_from_register(left)
current_frame.registers.integers.get(left).copy_value()
};
let right_value = if right_is_constant {
current_frame.get_integer_constant(right)
} else {
current_frame.get_integer_from_register(right)
current_frame.registers.integers.get(right).copy_value()
};
let sum = left_value + right_value;
@ -246,12 +558,12 @@ impl Thread {
let left_value = if left_is_constant {
current_frame.get_string_constant(left)
} else {
current_frame.get_string_from_register(left)
current_frame.registers.strings.get(left).as_value()
};
let right_value = if right_is_constant {
current_frame.get_string_constant(right)
} else {
current_frame.get_string_from_register(right)
current_frame.registers.strings.get(right).as_value()
};
let concatenated = DustString::from(format!("{left_value}{right_value}"));
@ -260,7 +572,7 @@ impl Thread {
.strings
.set_to_new_register(destination_index, concatenated);
}
_ => todo!(),
_ => unreachable!("Invalid ADD operation"),
},
Operation::JUMP => {
let offset = instruction.b_field() as usize;
@ -280,112 +592,69 @@ impl Thread {
if should_return_value {
match return_type {
TypeCode::BOOLEAN => {
let return_value =
current_frame.get_boolean_from_register(return_register);
let return_value = current_frame
.registers
.booleans
.get(return_register)
.copy_value();
return Some(Value::boolean(return_value));
}
TypeCode::BYTE => {
let return_value =
current_frame.get_byte_from_register(return_register);
let return_value = current_frame
.registers
.bytes
.get(return_register)
.copy_value();
return Some(Value::byte(return_value));
}
TypeCode::CHARACTER => {
let return_value =
current_frame.get_character_from_register(return_register);
let return_value = current_frame
.registers
.characters
.get(return_register)
.copy_value();
return Some(Value::character(return_value));
}
TypeCode::FLOAT => {
let return_value =
current_frame.get_float_from_register(return_register);
let return_value = current_frame
.registers
.floats
.get(return_register)
.copy_value();
return Some(Value::float(return_value));
}
TypeCode::INTEGER => {
let return_value =
current_frame.get_integer_from_register(return_register);
let return_value = current_frame
.registers
.integers
.get(return_register)
.copy_value();
return Some(Value::integer(return_value));
}
TypeCode::STRING => {
let return_value = current_frame
.get_string_from_register(return_register)
.clone();
.registers
.strings
.get(return_register)
.clone_value();
return Some(Value::string(return_value));
}
TypeCode::LIST => {
let abstract_list =
current_frame.get_list_from_register(return_register);
let concrete_list = current_frame
.registers
.lists
.get(return_register)
.as_value()
.clone()
.to_concrete(&self);
let mut concrete_list =
Vec::with_capacity(abstract_list.item_pointers.len());
match abstract_list.item_type {
TypeCode::BOOLEAN => {
for pointer in &abstract_list.item_pointers {
let boolean =
current_frame.get_boolean_from_pointer(&pointer);
let value = ConcreteValue::Boolean(boolean);
concrete_list.push(value);
}
}
TypeCode::BYTE => {
for pointer in &abstract_list.item_pointers {
let byte =
current_frame.get_byte_from_pointer(&pointer);
let value = ConcreteValue::Byte(byte);
concrete_list.push(value);
}
}
TypeCode::CHARACTER => {
for pointer in &abstract_list.item_pointers {
let character =
current_frame.get_character_from_pointer(&pointer);
let value = ConcreteValue::Character(character);
concrete_list.push(value);
}
}
TypeCode::FLOAT => {
for pointer in &abstract_list.item_pointers {
let float =
current_frame.get_float_from_pointer(&pointer);
let value = ConcreteValue::Float(float);
concrete_list.push(value);
}
}
TypeCode::INTEGER => {
for pointer in &abstract_list.item_pointers {
let integer =
current_frame.get_integer_from_pointer(&pointer);
let value = ConcreteValue::Integer(integer);
concrete_list.push(value);
}
}
TypeCode::STRING => {
for pointer in &abstract_list.item_pointers {
let string = current_frame
.get_string_from_pointer(pointer)
.clone();
let value = ConcreteValue::String(string);
concrete_list.push(value);
}
}
_ => todo!(),
}
return Some(Value::Concrete(ConcreteValue::list(
concrete_list,
abstract_list.item_type,
)));
return Some(Value::Concrete(concrete_list));
}
_ => unreachable!(),
}

View File

@ -1,6 +1,6 @@
use dust_lang::{
Chunk, ConcreteValue, FunctionType, Instruction, Operand, Span, Type, Value, compile,
instruction::TypeCode, run,
compile, instruction::TypeCode, run, Chunk, FunctionType, Instruction, Operand, Span, Type,
Value,
};
#[test]
@ -78,7 +78,7 @@ fn divide_floats() {
Instruction::r#return(true, 0, TypeCode::FLOAT),
],
positions: vec![Span(0, 10), Span(10, 10)],
constants: vec![ConcreteValue::Float(1.0), ConcreteValue::Float(0.25)],
float_constants: vec![1.0, 0.25],
..Chunk::default()
};
let return_value = Some(Value::float(4.0));
@ -106,11 +106,7 @@ fn divide_many_floats() {
Instruction::r#return(true, 1, TypeCode::FLOAT),
],
positions: vec![Span(0, 10), Span(0, 16), Span(16, 16)],
constants: vec![
ConcreteValue::Float(1.0),
ConcreteValue::Float(0.25),
ConcreteValue::Float(0.5),
],
float_constants: vec![1.0, 0.25, 0.5],
..Chunk::default()
};
let return_value = Some(Value::float(8.0));
@ -133,7 +129,7 @@ fn divide_integers() {
Instruction::r#return(true, 0, TypeCode::INTEGER),
],
positions: vec![Span(0, 6), Span(6, 6)],
constants: vec![ConcreteValue::Integer(10), ConcreteValue::Integer(2)],
integer_constants: vec![10, 2],
..Chunk::default()
};
let return_value = Some(Value::integer(5));
@ -161,7 +157,7 @@ fn divide_many_integers() {
Instruction::r#return(true, 1, TypeCode::INTEGER),
],
positions: vec![Span(0, 6), Span(0, 10), Span(10, 10)],
constants: vec![ConcreteValue::Integer(10), ConcreteValue::Integer(2)],
integer_constants: vec![10, 2],
..Chunk::default()
};
let return_value = Some(Value::integer(2));

View File

@ -1,6 +1,6 @@
use dust_lang::{
Chunk, ConcreteValue, FunctionType, Instruction, Operand, Span, Type, Value, compile,
instruction::TypeCode, run,
compile, instruction::TypeCode, run, Chunk, FunctionType, Instruction, Operand, Span, Type,
Value,
};
#[test]
@ -78,7 +78,7 @@ fn modulo_integers() {
Instruction::r#return(true, 0, TypeCode::INTEGER),
],
positions: vec![Span(0, 6), Span(6, 6)],
constants: vec![ConcreteValue::Integer(10), ConcreteValue::Integer(3)],
integer_constants: vec![10, 3],
..Chunk::default()
};
let return_value = Some(Value::integer(1));
@ -106,11 +106,7 @@ fn modulo_many_integers() {
Instruction::r#return(true, 1, TypeCode::INTEGER),
],
positions: vec![Span(0, 6), Span(0, 10), Span(10, 10)],
constants: vec![
ConcreteValue::Integer(10),
ConcreteValue::Integer(5),
ConcreteValue::Integer(3),
],
integer_constants: vec![10, 5, 3],
..Chunk::default()
};
let return_value = Some(Value::integer(0));

View File

@ -1,6 +1,6 @@
use dust_lang::{
Chunk, ConcreteValue, FunctionType, Instruction, Operand, Span, Type, Value, compile,
instruction::TypeCode, run,
compile, instruction::TypeCode, run, Chunk, FunctionType, Instruction, Operand, Span, Type,
Value,
};
#[test]
@ -78,7 +78,7 @@ fn multiply_floats() {
Instruction::r#return(true, 0, TypeCode::FLOAT),
],
positions: vec![Span(0, 9), Span(9, 9)],
constants: vec![ConcreteValue::Float(0.5), ConcreteValue::Float(2.0)],
float_constants: vec![0.5, 2.0],
..Chunk::default()
};
let return_value = Some(Value::float(1.0));
@ -106,7 +106,7 @@ fn multiply_many_floats() {
Instruction::r#return(true, 1, TypeCode::FLOAT),
],
positions: vec![Span(0, 9), Span(0, 15), Span(15, 15)],
constants: vec![ConcreteValue::Float(0.5), ConcreteValue::Float(2.0)],
float_constants: vec![0.5, 2.0],
..Chunk::default()
};
let return_value = Some(Value::float(0.5));
@ -129,7 +129,7 @@ fn multiply_integers() {
Instruction::r#return(true, 0, TypeCode::INTEGER),
],
positions: vec![Span(0, 6), Span(6, 6)],
constants: vec![ConcreteValue::Integer(10), ConcreteValue::Integer(5)],
integer_constants: vec![10, 5],
..Chunk::default()
};
let return_value = Some(Value::integer(50));
@ -157,11 +157,7 @@ fn multiply_many_integers() {
Instruction::r#return(true, 1, TypeCode::INTEGER),
],
positions: vec![Span(0, 6), Span(0, 10), Span(10, 10)],
constants: vec![
ConcreteValue::Integer(10),
ConcreteValue::Integer(5),
ConcreteValue::Integer(2),
],
integer_constants: vec![10, 5, 2],
..Chunk::default()
};
let return_value = Some(Value::integer(100));

View File

@ -1,6 +1,6 @@
use dust_lang::{
Chunk, ConcreteValue, FunctionType, Instruction, Operand, Span, Type, Value, compile,
instruction::TypeCode, run,
compile, instruction::TypeCode, run, Chunk, FunctionType, Instruction, Operand, Span, Type,
Value,
};
#[test]
@ -78,7 +78,7 @@ fn add_floats() {
Instruction::r#return(true, 0, TypeCode::FLOAT),
],
positions: vec![Span(0, 10), Span(10, 10)],
constants: vec![ConcreteValue::Float(0.5), ConcreteValue::Float(0.25)],
float_constants: vec![0.5, 0.25],
..Chunk::default()
};
let return_value = Some(Value::float(0.25));
@ -106,7 +106,7 @@ fn add_many_floats() {
Instruction::r#return(true, 1, TypeCode::FLOAT),
],
positions: vec![Span(0, 10), Span(0, 17), Span(17, 17)],
constants: vec![ConcreteValue::Float(0.5), ConcreteValue::Float(0.25)],
float_constants: vec![0.5, 0.25],
..Chunk::default()
};
let return_value = Some(Value::float(0.0));
@ -129,7 +129,7 @@ fn subtract_integers() {
Instruction::r#return(true, 0, TypeCode::INTEGER),
],
positions: vec![Span(0, 6), Span(6, 6)],
constants: vec![ConcreteValue::Integer(10), ConcreteValue::Integer(5)],
integer_constants: vec![10, 5],
..Chunk::default()
};
let return_value = Some(Value::integer(5));
@ -157,7 +157,7 @@ fn subtract_many_integers() {
Instruction::r#return(true, 1, TypeCode::INTEGER),
],
positions: vec![Span(0, 6), Span(0, 10), Span(10, 10)],
constants: vec![ConcreteValue::Integer(10), ConcreteValue::Integer(5)],
integer_constants: vec![10, 5],
..Chunk::default()
};
let return_value = Some(Value::integer(0));

View File

@ -147,10 +147,10 @@ fn load_boolean_list() {
positions: vec![Span(1, 5), Span(7, 12), Span(0, 13), Span(13, 13)],
..Chunk::default()
};
let return_value = Some(Value::Concrete(ConcreteValue::List {
items: vec![ConcreteValue::Boolean(true), ConcreteValue::Boolean(false)],
item_type: TypeCode::BOOLEAN,
}));
let return_value = Some(Value::Concrete(ConcreteValue::List(vec![
ConcreteValue::Boolean(true),
ConcreteValue::Boolean(false),
])));
assert_eq!(chunk, compile(source).unwrap());
assert_eq!(return_value, run(source).unwrap());
@ -170,10 +170,10 @@ fn load_byte_list() {
positions: vec![Span(1, 5), Span(7, 11), Span(0, 12), Span(12, 12)],
..Chunk::default()
};
let return_value = Some(Value::Concrete(ConcreteValue::List {
items: vec![ConcreteValue::Byte(0x2a), ConcreteValue::Byte(0x42)],
item_type: TypeCode::BYTE,
}));
let return_value = Some(Value::Concrete(ConcreteValue::List(vec![
ConcreteValue::Byte(0x2a),
ConcreteValue::Byte(0x42),
])));
assert_eq!(chunk, compile(source).unwrap());
assert_eq!(return_value, run(source).unwrap());
@ -194,10 +194,10 @@ fn load_character_list() {
character_constants: vec!['a', 'b'],
..Chunk::default()
};
let return_value = Some(Value::Concrete(ConcreteValue::List {
items: vec![ConcreteValue::Character('a'), ConcreteValue::Character('b')],
item_type: TypeCode::CHARACTER,
}));
let return_value = Some(Value::Concrete(ConcreteValue::List(vec![
ConcreteValue::Character('a'),
ConcreteValue::Character('b'),
])));
assert_eq!(chunk, compile(source).unwrap());
assert_eq!(return_value, run(source).unwrap());
@ -218,10 +218,10 @@ fn load_float_list() {
float_constants: vec![42.42, 24.24],
..Chunk::default()
};
let return_value = Some(Value::Concrete(ConcreteValue::List {
items: vec![ConcreteValue::Float(42.42), ConcreteValue::Float(24.24)],
item_type: TypeCode::FLOAT,
}));
let return_value = Some(Value::Concrete(ConcreteValue::List(vec![
ConcreteValue::Float(42.42),
ConcreteValue::Float(24.24),
])));
assert_eq!(chunk, compile(source).unwrap());
assert_eq!(return_value, run(source).unwrap());
@ -243,14 +243,11 @@ fn load_integer_list() {
integer_constants: vec![1, 2, 3],
..Chunk::default()
};
let return_value = Some(Value::Concrete(ConcreteValue::List {
items: vec![
ConcreteValue::Integer(1),
ConcreteValue::Integer(2),
ConcreteValue::Integer(3),
],
item_type: TypeCode::INTEGER,
}));
let return_value = Some(Value::Concrete(ConcreteValue::List(vec![
ConcreteValue::Integer(1),
ConcreteValue::Integer(2),
ConcreteValue::Integer(3),
])));
assert_eq!(chunk, compile(source).unwrap());
assert_eq!(return_value, run(source).unwrap());
@ -271,13 +268,10 @@ fn load_string_list() {
string_constants: vec![DustString::from("Hello"), DustString::from("World")],
..Chunk::default()
};
let return_value = Some(Value::Concrete(ConcreteValue::List {
items: vec![
ConcreteValue::String(DustString::from("Hello")),
ConcreteValue::String(DustString::from("World")),
],
item_type: TypeCode::STRING,
}));
let return_value = Some(Value::Concrete(ConcreteValue::List(vec![
ConcreteValue::String(DustString::from("Hello")),
ConcreteValue::String(DustString::from("World")),
])));
assert_eq!(chunk, compile(source).unwrap());
assert_eq!(return_value, run(source).unwrap());
@ -311,19 +305,10 @@ fn load_nested_list() {
integer_constants: vec![1, 2, 3, 4],
..Chunk::default()
};
let return_value = Some(Value::Concrete(ConcreteValue::List {
items: vec![
ConcreteValue::List {
items: vec![ConcreteValue::Integer(1), ConcreteValue::Integer(2)],
item_type: TypeCode::INTEGER,
},
ConcreteValue::List {
items: vec![ConcreteValue::Integer(3), ConcreteValue::Integer(4)],
item_type: TypeCode::INTEGER,
},
],
item_type: TypeCode::LIST,
}));
let return_value = Some(Value::Concrete(ConcreteValue::List(vec![
ConcreteValue::List(vec![ConcreteValue::Integer(1), ConcreteValue::Integer(2)]),
ConcreteValue::List(vec![ConcreteValue::Integer(3), ConcreteValue::Integer(4)]),
])));
assert_eq!(chunk, compile(source).unwrap());
assert_eq!(return_value, run(source).unwrap());
@ -377,37 +362,16 @@ fn load_deeply_nested_list() {
integer_constants: vec![1, 2, 3, 4, 5, 6, 7, 8],
..Chunk::default()
};
let return_value = Some(Value::Concrete(ConcreteValue::List {
items: vec![
ConcreteValue::List {
items: vec![
ConcreteValue::List {
items: vec![ConcreteValue::Integer(1), ConcreteValue::Integer(2)],
item_type: TypeCode::INTEGER,
},
ConcreteValue::List {
items: vec![ConcreteValue::Integer(3), ConcreteValue::Integer(4)],
item_type: TypeCode::INTEGER,
},
],
item_type: TypeCode::LIST,
},
ConcreteValue::List {
items: vec![
ConcreteValue::List {
items: vec![ConcreteValue::Integer(5), ConcreteValue::Integer(6)],
item_type: TypeCode::INTEGER,
},
ConcreteValue::List {
items: vec![ConcreteValue::Integer(7), ConcreteValue::Integer(8)],
item_type: TypeCode::INTEGER,
},
],
item_type: TypeCode::LIST,
},
],
item_type: TypeCode::LIST,
}));
let return_value = Some(Value::Concrete(ConcreteValue::List(vec![
ConcreteValue::List(vec![
ConcreteValue::List(vec![ConcreteValue::Integer(1), ConcreteValue::Integer(2)]),
ConcreteValue::List(vec![ConcreteValue::Integer(3), ConcreteValue::Integer(4)]),
]),
ConcreteValue::List(vec![
ConcreteValue::List(vec![ConcreteValue::Integer(5), ConcreteValue::Integer(6)]),
ConcreteValue::List(vec![ConcreteValue::Integer(7), ConcreteValue::Integer(8)]),
]),
])));
assert_eq!(chunk, compile(source).unwrap());
assert_eq!(return_value, run(source).unwrap());