1
0

Reimplement more instruction and compiler logic

This commit is contained in:
Jeff 2025-02-08 17:36:30 -05:00
parent 07001a03e7
commit 3af1b64820
11 changed files with 217 additions and 443 deletions

View File

@ -1020,44 +1020,52 @@ impl<'src> Compiler<'src> {
} }
fn parse_logical_binary(&mut self) -> Result<(), CompileError> { fn parse_logical_binary(&mut self) -> Result<(), CompileError> {
let (last_instruction, last_type, last_position) = let operator = self.current_token;
let operator_position = self.current_position;
let rule = ParseRule::from(&operator);
let (left_instruction, left_type, left_position) =
self.instructions self.instructions
.pop() .pop()
.ok_or_else(|| CompileError::ExpectedExpression { .ok_or_else(|| CompileError::ExpectedExpression {
found: self.previous_token.to_owned(), found: self.previous_token.to_owned(),
position: self.previous_position, position: self.previous_position,
})?; })?;
let operand_register = if last_instruction.operation() == Operation::POINT { let operand_register = if left_instruction.operation() == Operation::POINT {
let Point { to, .. } = Point::from(last_instruction); let Point { to, .. } = Point::from(left_instruction);
let local = self.get_local(to.index())?; let local = self.get_local(to.index())?;
local.register_index local.register_index
} else if last_instruction.yields_value() { } else if left_instruction.yields_value() {
let register = last_instruction.a_field(); let register = left_instruction.a_field();
self.instructions self.instructions
.push((last_instruction, last_type, last_position)); .push((left_instruction, left_type, left_position));
register register
} else { } else {
let register = match last_type { return Err(CompileError::ExpectedExpression {
Type::Boolean => self.next_boolean_register() - 1, found: self.previous_token.to_owned(),
Type::Byte => self.next_byte_register() - 1, position: self.previous_position,
Type::Character => self.next_character_register() - 1, });
Type::Float => self.next_float_register() - 1,
Type::Integer => self.next_integer_register() - 1,
Type::String => self.next_string_register() - 1,
_ => todo!(),
};
self.instructions
.push((last_instruction, last_type, last_position));
register
}; };
let operator = self.current_token;
let operator_position = self.current_position; // TODO: Check if the left type is boolean
let rule = ParseRule::from(&operator);
self.advance()?;
self.parse_sub_expression(&rule.precedence)?;
let (mut right_instruction, right_type, right_position) = self
.instructions
.pop()
.ok_or_else(|| CompileError::ExpectedExpression {
found: self.previous_token.to_owned(),
position: self.previous_position,
})?;
// TODO: Check if the right type is boolean
right_instruction.set_a_field(operand_register);
let test_boolean = match operator { let test_boolean = match operator {
Token::DoubleAmpersand => true, Token::DoubleAmpersand => true,
Token::DoublePipe => false, Token::DoublePipe => false,
@ -1074,8 +1082,8 @@ impl<'src> Compiler<'src> {
self.emit_instruction(test, Type::None, operator_position); self.emit_instruction(test, Type::None, operator_position);
self.emit_instruction(jump, Type::None, operator_position); self.emit_instruction(jump, Type::None, operator_position);
self.advance()?; self.instructions
self.parse_sub_expression(&rule.precedence)?; .push((right_instruction, right_type, right_position));
let instructions_length = self.instructions.len(); let instructions_length = self.instructions.len();
@ -1571,7 +1579,7 @@ impl<'src> Compiler<'src> {
fn parse_call_native(&mut self, function: NativeFunction) -> Result<(), CompileError> { fn parse_call_native(&mut self, function: NativeFunction) -> Result<(), CompileError> {
let start = self.previous_position.0; let start = self.previous_position.0;
let mut argument_count = 0; let mut first_argument_index = None;
self.expect(Token::LeftParenthesis)?; self.expect(Token::LeftParenthesis)?;
@ -1579,7 +1587,9 @@ impl<'src> Compiler<'src> {
self.parse_expression()?; self.parse_expression()?;
self.allow(Token::Comma)?; self.allow(Token::Comma)?;
argument_count += 1; if first_argument_index.is_none() {
first_argument_index = Some(self.instructions.last().unwrap().0.a_field());
}
} }
let end = self.previous_position.1; let end = self.previous_position.1;
@ -1594,11 +1604,8 @@ impl<'src> Compiler<'src> {
_ => todo!(), _ => todo!(),
}; };
let return_type = *function.r#type().return_type; let return_type = *function.r#type().return_type;
let call_native = Instruction::from(CallNative { let call_native =
destination, Instruction::call_native(destination, function, first_argument_index.unwrap_or(0));
function,
argument_count,
});
self.emit_instruction(call_native, return_type, Span(start, end)); self.emit_instruction(call_native, return_type, Span(start, end));

View File

@ -1,24 +1,25 @@
use std::fmt::Display; use std::fmt::Display;
use crate::{Instruction, NativeFunction, Operation}; use crate::{Instruction, NativeFunction, Operation, Type};
use super::InstructionFields; use super::InstructionFields;
pub struct CallNative { pub struct CallNative {
pub destination: u16, pub destination: u16,
pub function: NativeFunction, pub function: NativeFunction,
pub argument_count: u16, pub first_argument_index: u16,
} }
impl From<Instruction> for CallNative { impl From<Instruction> for CallNative {
fn from(instruction: Instruction) -> Self { fn from(instruction: Instruction) -> Self {
let destination = instruction.a_field(); let destination = instruction.a_field();
let function = NativeFunction::from(instruction.b_field()); let function = NativeFunction::from(instruction.b_field());
let first_argument_index = instruction.c_field();
CallNative { CallNative {
destination, destination,
function, function,
argument_count: instruction.c_field(), first_argument_index,
} }
} }
} }
@ -28,7 +29,7 @@ impl From<CallNative> for Instruction {
let operation = Operation::CALL_NATIVE; let operation = Operation::CALL_NATIVE;
let a_field = call_native.destination; let a_field = call_native.destination;
let b_field = call_native.function as u16; let b_field = call_native.function as u16;
let c_field = call_native.argument_count; let c_field = call_native.first_argument_index;
InstructionFields { InstructionFields {
operation, operation,
@ -46,21 +47,57 @@ impl Display for CallNative {
let CallNative { let CallNative {
destination, destination,
function, function,
argument_count, first_argument_index,
} = self; } = self;
let arguments_start = destination.saturating_sub(*argument_count); let argument_count = function.r#type().value_parameters.len() as u16;
let arguments_end = arguments_start + argument_count;
if function.returns_value() { if function.returns_value() {
write!(f, "R{destination} = ")?; write!(f, "R{destination} = ")?;
} }
write!(f, "{function}")?;
match argument_count { match argument_count {
0 => { 0 => {
write!(f, "{function}()") write!(f, "()")
}
_ => {
let arguments_end = first_argument_index + argument_count - 1;
let arguments_index_range = *first_argument_index..=arguments_end;
let function_type = function.r#type();
let argument_types = function_type.value_parameters.iter();
write!(f, "(")?;
for (index, r#type) in arguments_index_range.zip(argument_types) {
match r#type {
Type::Boolean => {
write!(f, "R_BOOL_{index}")
}
Type::Byte => {
write!(f, "R_BYTE_{index}")
}
Type::Float => {
write!(f, "R_FLOAT_{index}")
}
Type::Integer => {
write!(f, "R_INT_{index}")
}
Type::String => {
write!(f, "R_STR_{index}")
}
unsupported => {
todo!("Support for {unsupported:?} arguments")
}
}?;
if index != arguments_end {
write!(f, ", ")?;
}
}
write!(f, ")")
} }
1 => write!(f, "{function}(R{arguments_start})"),
_ => write!(f, "{function}(R{arguments_start}..R{arguments_end})"),
} }
} }
} }

View File

@ -556,12 +556,12 @@ impl Instruction {
pub fn call_native( pub fn call_native(
destination: u16, destination: u16,
function: NativeFunction, function: NativeFunction,
argument_count: u16, first_argument_index: u16,
) -> Instruction { ) -> Instruction {
Instruction::from(CallNative { Instruction::from(CallNative {
destination, destination,
function, function,
argument_count, first_argument_index,
}) })
} }

View File

@ -44,6 +44,6 @@ impl Display for Test {
} = self; } = self;
let bang = if *test_value { "" } else { "!" }; let bang = if *test_value { "" } else { "!" };
write!(f, "if {bang}R{operand_register} {{ JUMP +1 }}") write!(f, "if {bang}R_BOOL_{operand_register} {{ JUMP +1 }}")
} }
} }

View File

@ -143,13 +143,13 @@ define_native_function! {
// (ToByte, 5_u8, "to_byte", true), // (ToByte, 5_u8, "to_byte", true),
// (ToFloat, 6_u8, "to_float", true), // (ToFloat, 6_u8, "to_float", true),
// (ToInteger, 7_u8, "to_integer", true), // (ToInteger, 7_u8, "to_integer", true),
( // (
ToString, // ToString,
8, // 8,
"to_string", // "to_string",
FunctionType::new([], [Type::Any], Type::String), // FunctionType::new([], [Type::Any], Type::String),
string::to_string // string::to_string
), // ),
// // List and string // // List and string
// (All, 9_u8, "all", true), // (All, 9_u8, "all", true),
@ -216,7 +216,7 @@ define_native_function! {
Write, Write,
55, 55,
"write", "write",
FunctionType::new([], [Type::Any], Type::None), FunctionType::new([], [Type::String], Type::None),
io::write io::write
), ),
// (WriteFile, 56_u8, "write_file", false), // (WriteFile, 56_u8, "write_file", false),
@ -224,7 +224,7 @@ define_native_function! {
WriteLine, WriteLine,
57, 57,
"write_line", "write_line",
FunctionType::new([], [Type::Any], Type::None), FunctionType::new([], [Type::String], Type::None),
io::write_line io::write_line
), ),
@ -242,7 +242,7 @@ define_native_function! {
Spawn, Spawn,
60, 60,
"spawn", "spawn",
FunctionType::new([], [ Type::function([], [], Type::Any)], Type::None), FunctionType::new([], [ Type::function([], [], Type::None)], Type::None),
thread::spawn thread::spawn
) )
} }

View File

@ -13,7 +13,6 @@ use crate::instruction::TypeCode;
#[derive(Clone, Default, Debug, Eq, PartialEq, Serialize, Deserialize)] #[derive(Clone, Default, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(tag = "Type", content = "Value")] #[serde(tag = "Type", content = "Value")]
pub enum Type { pub enum Type {
Any,
Boolean, Boolean,
Byte, Byte,
Character, Character,
@ -77,9 +76,7 @@ impl Type {
/// Checks that the type is compatible with another type. /// Checks that the type is compatible with another type.
pub fn check(&self, other: &Type) -> Result<(), TypeConflict> { pub fn check(&self, other: &Type) -> Result<(), TypeConflict> {
match (self.concrete_type(), other.concrete_type()) { match (self.concrete_type(), other.concrete_type()) {
(Type::Any, _) (Type::Boolean, Type::Boolean)
| (_, Type::Any)
| (Type::Boolean, Type::Boolean)
| (Type::Byte, Type::Byte) | (Type::Byte, Type::Byte)
| (Type::Character, Type::Character) | (Type::Character, Type::Character)
| (Type::Float, Type::Float) | (Type::Float, Type::Float)
@ -171,7 +168,6 @@ impl Type {
impl Display for Type { impl Display for Type {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self { match self {
Type::Any => write!(f, "any"),
Type::Boolean => write!(f, "bool"), Type::Boolean => write!(f, "bool"),
Type::Byte => write!(f, "byte"), Type::Byte => write!(f, "byte"),
Type::Character => write!(f, "char"), Type::Character => write!(f, "char"),
@ -235,8 +231,6 @@ impl PartialOrd for Type {
impl Ord for Type { impl Ord for Type {
fn cmp(&self, other: &Self) -> Ordering { fn cmp(&self, other: &Self) -> Ordering {
match (self, other) { match (self, other) {
(Type::Any, Type::Any) => Ordering::Equal,
(Type::Any, _) => Ordering::Greater,
(Type::Boolean, Type::Boolean) => Ordering::Equal, (Type::Boolean, Type::Boolean) => Ordering::Equal,
(Type::Boolean, _) => Ordering::Greater, (Type::Boolean, _) => Ordering::Greater,
(Type::Byte, Type::Byte) => Ordering::Equal, (Type::Byte, Type::Byte) => Ordering::Equal,

View File

@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
use smartstring::{LazyCompact, SmartString}; use smartstring::{LazyCompact, SmartString};
use tracing::trace; use tracing::trace;
use crate::{Type, Value, ValueError}; use crate::{Type, Value, ValueError, instruction::TypeCode};
use super::RangeValue; use super::RangeValue;
@ -18,7 +18,10 @@ pub enum ConcreteValue {
Character(char), Character(char),
Float(f64), Float(f64),
Integer(i64), Integer(i64),
List(Vec<ConcreteValue>), List {
items: Vec<ConcreteValue>,
item_type: TypeCode,
},
Range(RangeValue), Range(RangeValue),
String(DustString), String(DustString),
} }
@ -28,8 +31,11 @@ impl ConcreteValue {
Value::Concrete(self) Value::Concrete(self)
} }
pub fn list<T: Into<Vec<ConcreteValue>>>(into_list: T) -> Self { pub fn list<T: Into<Vec<ConcreteValue>>>(into_items: T, type_code: TypeCode) -> Self {
ConcreteValue::List(into_list.into()) ConcreteValue::List {
items: into_items.into(),
item_type: type_code,
}
} }
pub fn string<T: Into<SmartString<LazyCompact>>>(to_string: T) -> Self { pub fn string<T: Into<SmartString<LazyCompact>>>(to_string: T) -> Self {
@ -85,8 +91,8 @@ impl ConcreteValue {
} }
pub fn as_list(&self) -> Option<&Vec<ConcreteValue>> { pub fn as_list(&self) -> Option<&Vec<ConcreteValue>> {
if let ConcreteValue::List(list) = self { if let ConcreteValue::List { items, .. } = self {
Some(list) Some(items)
} else { } else {
None None
} }
@ -111,239 +117,11 @@ impl ConcreteValue {
ConcreteValue::Character(_) => Type::Character, ConcreteValue::Character(_) => Type::Character,
ConcreteValue::Float(_) => Type::Float, ConcreteValue::Float(_) => Type::Float,
ConcreteValue::Integer(_) => Type::Integer, ConcreteValue::Integer(_) => Type::Integer,
ConcreteValue::List(list) => { ConcreteValue::List { item_type, .. } => Type::List(*item_type),
let item_type = list
.first()
.map_or(Type::Any, |item| item.r#type())
.type_code();
Type::List(item_type)
}
ConcreteValue::Range(range) => range.r#type(), ConcreteValue::Range(range) => range.r#type(),
ConcreteValue::String(_) => Type::String, ConcreteValue::String(_) => Type::String,
} }
} }
pub fn add(&self, other: &Self) -> ConcreteValue {
use ConcreteValue::*;
match (self, other) {
(Byte(left), Byte(right)) => {
let sum = left.saturating_add(*right);
Byte(sum)
}
(Character(left), Character(right)) => {
let mut concatenated = DustString::new();
concatenated.push(*left);
concatenated.push(*right);
String(concatenated)
}
(Character(left), String(right)) => {
let mut concatenated = DustString::new();
concatenated.push(*left);
concatenated.push_str(right);
String(concatenated)
}
(Float(left), Float(right)) => {
let sum = left + right;
Float(sum)
}
(Integer(left), Integer(right)) => {
let sum = left.saturating_add(*right);
Integer(sum)
}
(String(left), Character(right)) => {
let concatenated = format!("{}{}", left, right);
String(DustString::from(concatenated))
}
(String(left), String(right)) => {
let concatenated = format!("{}{}", left, right);
String(DustString::from(concatenated))
}
_ => panic!(
"{}",
ValueError::CannotAdd(
Value::Concrete(self.clone()),
Value::Concrete(other.clone())
)
),
}
}
pub fn subtract(&self, other: &Self) -> ConcreteValue {
use ConcreteValue::*;
match (self, other) {
(Byte(left), Byte(right)) => ConcreteValue::Byte(left.saturating_sub(*right)),
(Float(left), Float(right)) => ConcreteValue::Float(left - right),
(Integer(left), Integer(right)) => ConcreteValue::Integer(left.saturating_sub(*right)),
_ => panic!(
"{}",
ValueError::CannotSubtract(
Value::Concrete(self.clone()),
Value::Concrete(other.clone())
)
),
}
}
pub fn multiply(&self, other: &Self) -> Result<ConcreteValue, ValueError> {
use ConcreteValue::*;
let product = match (self, other) {
(Byte(left), Byte(right)) => ConcreteValue::Byte(left.saturating_mul(*right)),
(Float(left), Float(right)) => ConcreteValue::Float(left * right),
(Integer(left), Integer(right)) => ConcreteValue::Integer(left.saturating_mul(*right)),
_ => {
return Err(ValueError::CannotMultiply(
self.clone().to_value(),
other.clone().to_value(),
));
}
};
Ok(product)
}
pub fn divide(&self, other: &Self) -> Result<ConcreteValue, ValueError> {
use ConcreteValue::*;
let quotient = match (self, other) {
(Byte(left), Byte(right)) => ConcreteValue::Byte(left.saturating_div(*right)),
(Float(left), Float(right)) => ConcreteValue::Float(left / right),
(Integer(left), Integer(right)) => ConcreteValue::Integer(left.saturating_div(*right)),
_ => {
return Err(ValueError::CannotMultiply(
self.clone().to_value(),
other.clone().to_value(),
));
}
};
Ok(quotient)
}
pub fn modulo(&self, other: &Self) -> Result<ConcreteValue, ValueError> {
use ConcreteValue::*;
let product = match (self, other) {
(Byte(left), Byte(right)) => ConcreteValue::Byte(left.wrapping_rem(*right)),
(Float(left), Float(right)) => ConcreteValue::Float(left % right),
(Integer(left), Integer(right)) => {
ConcreteValue::Integer(left.wrapping_rem_euclid(*right))
}
_ => {
return Err(ValueError::CannotMultiply(
self.clone().to_value(),
other.clone().to_value(),
));
}
};
Ok(product)
}
pub fn negate(&self) -> ConcreteValue {
use ConcreteValue::*;
match self {
Boolean(value) => ConcreteValue::Boolean(!value),
Byte(value) => ConcreteValue::Byte(value.wrapping_neg()),
Float(value) => ConcreteValue::Float(-value),
Integer(value) => ConcreteValue::Integer(value.wrapping_neg()),
_ => panic!("{}", ValueError::CannotNegate(self.clone().to_value())),
}
}
pub fn not(&self) -> Result<ConcreteValue, ValueError> {
use ConcreteValue::*;
let not = match self {
Boolean(value) => ConcreteValue::Boolean(!value),
_ => return Err(ValueError::CannotNot(self.clone().to_value())),
};
Ok(not)
}
pub fn equals(&self, other: &ConcreteValue) -> bool {
use ConcreteValue::*;
match (self, other) {
(Boolean(left), Boolean(right)) => left == right,
(Byte(left), Byte(right)) => left == right,
(Character(left), Character(right)) => left == right,
(Float(left), Float(right)) => left == right,
(Integer(left), Integer(right)) => left == right,
(List(left), List(right)) => left == right,
(Range(left), Range(right)) => left == right,
(String(left), String(right)) => left == right,
_ => {
panic!(
"{}",
ValueError::CannotCompare(
Value::Concrete(self.clone()),
Value::Concrete(other.clone())
)
)
}
}
}
pub fn less_than(&self, other: &ConcreteValue) -> Result<ConcreteValue, ValueError> {
use ConcreteValue::*;
let less_than = match (self, other) {
(Boolean(left), Boolean(right)) => ConcreteValue::Boolean(left < right),
(Byte(left), Byte(right)) => ConcreteValue::Boolean(left < right),
(Character(left), Character(right)) => ConcreteValue::Boolean(left < right),
(Float(left), Float(right)) => ConcreteValue::Boolean(left < right),
(Integer(left), Integer(right)) => ConcreteValue::Boolean(left < right),
(List(left), List(right)) => ConcreteValue::Boolean(left < right),
(Range(left), Range(right)) => ConcreteValue::Boolean(left < right),
(String(left), String(right)) => ConcreteValue::Boolean(left < right),
_ => {
return Err(ValueError::CannotCompare(
self.clone().to_value(),
other.clone().to_value(),
));
}
};
Ok(less_than)
}
pub fn less_than_or_equals(&self, other: &ConcreteValue) -> Result<ConcreteValue, ValueError> {
use ConcreteValue::*;
let less_than_or_equal = match (self, other) {
(Boolean(left), Boolean(right)) => ConcreteValue::Boolean(left <= right),
(Byte(left), Byte(right)) => ConcreteValue::Boolean(left <= right),
(Character(left), Character(right)) => ConcreteValue::Boolean(left <= right),
(Float(left), Float(right)) => ConcreteValue::Boolean(left <= right),
(Integer(left), Integer(right)) => ConcreteValue::Boolean(left <= right),
(List(left), List(right)) => ConcreteValue::Boolean(left <= right),
(Range(left), Range(right)) => ConcreteValue::Boolean(left <= right),
(String(left), String(right)) => ConcreteValue::Boolean(left <= right),
_ => {
return Err(ValueError::CannotCompare(
self.clone().to_value(),
other.clone().to_value(),
));
}
};
Ok(less_than_or_equal)
}
} }
impl Clone for ConcreteValue { impl Clone for ConcreteValue {
@ -356,7 +134,10 @@ impl Clone for ConcreteValue {
ConcreteValue::Character(character) => ConcreteValue::Character(*character), ConcreteValue::Character(character) => ConcreteValue::Character(*character),
ConcreteValue::Float(float) => ConcreteValue::Float(*float), ConcreteValue::Float(float) => ConcreteValue::Float(*float),
ConcreteValue::Integer(integer) => ConcreteValue::Integer(*integer), ConcreteValue::Integer(integer) => ConcreteValue::Integer(*integer),
ConcreteValue::List(list) => ConcreteValue::List(list.clone()), ConcreteValue::List { items, item_type } => ConcreteValue::List {
items: items.clone(),
item_type: *item_type,
},
ConcreteValue::Range(range) => ConcreteValue::Range(*range), ConcreteValue::Range(range) => ConcreteValue::Range(*range),
ConcreteValue::String(string) => ConcreteValue::String(string.clone()), ConcreteValue::String(string) => ConcreteValue::String(string.clone()),
} }
@ -379,10 +160,10 @@ impl Display for ConcreteValue {
Ok(()) Ok(())
} }
ConcreteValue::Integer(integer) => write!(f, "{integer}"), ConcreteValue::Integer(integer) => write!(f, "{integer}"),
ConcreteValue::List(list) => { ConcreteValue::List { items, .. } => {
write!(f, "[")?; write!(f, "[")?;
for (index, item) in list.iter().enumerate() { for (index, item) in items.iter().enumerate() {
if index > 0 { if index > 0 {
write!(f, ", ")?; write!(f, ", ")?;
} }

View File

@ -130,101 +130,6 @@ impl Value {
} }
} }
pub fn add(&self, other: &Value) -> Value {
let sum = match (self, other) {
(Value::Concrete(left), Value::Concrete(right)) => left.add(right),
_ => panic!("{}", ValueError::CannotAdd(self.clone(), other.clone())),
};
Value::Concrete(sum)
}
pub fn subtract(&self, other: &Value) -> Value {
let difference = match (self, other) {
(Value::Concrete(left), Value::Concrete(right)) => left.subtract(right),
_ => panic!(
"{}",
ValueError::CannotSubtract(self.clone(), other.clone())
),
};
Value::Concrete(difference)
}
pub fn multiply(&self, other: &Value) -> Result<Value, ValueError> {
match (self, other) {
(Value::Concrete(left), Value::Concrete(right)) => {
left.multiply(right).map(Value::Concrete)
}
_ => Err(ValueError::CannotMultiply(
self.to_owned(),
other.to_owned(),
)),
}
}
pub fn divide(&self, other: &Value) -> Result<Value, ValueError> {
match (self, other) {
(Value::Concrete(left), Value::Concrete(right)) => {
left.divide(right).map(Value::Concrete)
}
_ => Err(ValueError::CannotDivide(self.to_owned(), other.to_owned())),
}
}
pub fn modulo(&self, other: &Value) -> Result<Value, ValueError> {
match (self, other) {
(Value::Concrete(left), Value::Concrete(right)) => {
left.modulo(right).map(Value::Concrete)
}
_ => Err(ValueError::CannotModulo(self.to_owned(), other.to_owned())),
}
}
pub fn negate(&self) -> Value {
let concrete = match self {
Value::Concrete(concrete_value) => concrete_value.negate(),
_ => panic!("{}", ValueError::CannotNegate(self.clone())),
};
Value::Concrete(concrete)
}
pub fn not(&self) -> Result<Value, ValueError> {
match self {
Value::Concrete(concrete_value) => concrete_value.not().map(Value::Concrete),
_ => Err(ValueError::CannotNot(self.to_owned())),
}
}
pub fn equals(&self, other: &Value) -> bool {
match (self, other) {
(Value::Concrete(left), Value::Concrete(right)) => left.equals(right),
_ => panic!(
"{}",
ValueError::CannotCompare(self.to_owned(), other.to_owned())
),
}
}
pub fn less(&self, other: &Value) -> Result<Value, ValueError> {
match (self, other) {
(Value::Concrete(left), Value::Concrete(right)) => {
left.less_than(right).map(Value::Concrete)
}
_ => Err(ValueError::CannotCompare(self.to_owned(), other.to_owned())),
}
}
pub fn less_than_or_equals(&self, other: &Value) -> Result<Value, ValueError> {
match (self, other) {
(Value::Concrete(left), Value::Concrete(right)) => {
left.less_than_or_equals(right).map(Value::Concrete)
}
_ => Err(ValueError::CannotCompare(self.to_owned(), other.to_owned())),
}
}
pub fn display(&self, data: &Thread) -> DustString { pub fn display(&self, data: &Thread) -> DustString {
match self { match self {
Value::AbstractList(list) => list.display(data), Value::AbstractList(list) => list.display(data),

View File

@ -759,7 +759,7 @@ pub fn multiply(instruction: InstructionFields, thread: &mut Thread) {
let result = left_value.saturating_mul(*right_value); let result = left_value.saturating_mul(*right_value);
let register = Register::Value(result); let register = Register::Value(result);
thread.set_integer_register(destination as usize, register); thread.set_integer_register(destination, register);
} }
_ => unimplemented!(), _ => unimplemented!(),
} }
@ -850,9 +850,18 @@ pub fn divide(instruction: InstructionFields, thread: &mut Thread) {
_ => unreachable!(), _ => unreachable!(),
} }
} }
pub fn modulo(instruction: InstructionFields, thread: &mut Thread) {} pub fn modulo(instruction: InstructionFields, thread: &mut Thread) {}
pub fn test(instruction: InstructionFields, thread: &mut Thread) {} pub fn test(instruction: InstructionFields, thread: &mut Thread) {
let operand_register = instruction.b_field as usize;
let test_value = instruction.c_field != 0;
let operand_boolean = thread.get_boolean_register(operand_register);
if *operand_boolean == test_value {
thread.current_frame_mut().ip += 1;
}
}
pub fn test_set(instruction: InstructionFields, thread: &mut Thread) {} pub fn test_set(instruction: InstructionFields, thread: &mut Thread) {}
@ -976,16 +985,18 @@ pub fn r#return(instruction: InstructionFields, thread: &mut Thread) {
} }
TypeCode::LIST => { TypeCode::LIST => {
let abstract_list = thread.get_list_register(return_register).clone(); let abstract_list = thread.get_list_register(return_register).clone();
let mut concrete_list = Vec::with_capacity(abstract_list.item_pointers.len()); let mut items = Vec::with_capacity(abstract_list.item_pointers.len());
for pointer in &abstract_list.item_pointers { for pointer in &abstract_list.item_pointers {
let value = thread.get_value_from_pointer(pointer); let value = thread.get_value_from_pointer(pointer);
concrete_list.push(value); items.push(value);
} }
thread.return_value = thread.return_value = Some(Some(Value::Concrete(ConcreteValue::List {
Some(Some(Value::Concrete(ConcreteValue::List(concrete_list)))); items,
item_type: abstract_list.item_type,
})));
} }
_ => unimplemented!(), _ => unimplemented!(),
} }

View File

@ -119,15 +119,18 @@ impl Thread {
} }
Pointer::RegisterList(register_index) => { Pointer::RegisterList(register_index) => {
let abstract_list = self.get_list_register(*register_index).clone(); let abstract_list = self.get_list_register(*register_index).clone();
let mut concrete_list = Vec::with_capacity(abstract_list.item_pointers.len()); let mut items = Vec::with_capacity(abstract_list.item_pointers.len());
for pointer in &abstract_list.item_pointers { for pointer in &abstract_list.item_pointers {
let value = self.get_value_from_pointer(pointer); let value = self.get_value_from_pointer(pointer);
concrete_list.push(value); items.push(value);
} }
ConcreteValue::List(concrete_list) ConcreteValue::List {
items,
item_type: abstract_list.item_type,
}
} }
Pointer::RegisterFunction(_) => unimplemented!(), Pointer::RegisterFunction(_) => unimplemented!(),
Pointer::ConstantCharacter(constant_index) => { Pointer::ConstantCharacter(constant_index) => {

View File

@ -147,10 +147,10 @@ fn load_boolean_list() {
positions: vec![Span(1, 5), Span(7, 12), Span(0, 13), Span(13, 13)], positions: vec![Span(1, 5), Span(7, 12), Span(0, 13), Span(13, 13)],
..Chunk::default() ..Chunk::default()
}; };
let return_value = Some(Value::Concrete(ConcreteValue::List(vec![ let return_value = Some(Value::Concrete(ConcreteValue::List {
ConcreteValue::Boolean(true), items: vec![ConcreteValue::Boolean(true), ConcreteValue::Boolean(false)],
ConcreteValue::Boolean(false), item_type: TypeCode::BOOLEAN,
]))); }));
assert_eq!(chunk, compile(source).unwrap()); assert_eq!(chunk, compile(source).unwrap());
assert_eq!(return_value, run(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)], positions: vec![Span(1, 5), Span(7, 11), Span(0, 12), Span(12, 12)],
..Chunk::default() ..Chunk::default()
}; };
let return_value = Some(Value::Concrete(ConcreteValue::List(vec![ let return_value = Some(Value::Concrete(ConcreteValue::List {
ConcreteValue::Byte(0x2a), items: vec![ConcreteValue::Byte(0x2a), ConcreteValue::Byte(0x42)],
ConcreteValue::Byte(0x42), item_type: TypeCode::BYTE,
]))); }));
assert_eq!(chunk, compile(source).unwrap()); assert_eq!(chunk, compile(source).unwrap());
assert_eq!(return_value, run(source).unwrap()); assert_eq!(return_value, run(source).unwrap());
@ -194,10 +194,10 @@ fn load_character_list() {
constants: vec![ConcreteValue::Character('a'), ConcreteValue::Character('b')], constants: vec![ConcreteValue::Character('a'), ConcreteValue::Character('b')],
..Chunk::default() ..Chunk::default()
}; };
let return_value = Some(Value::Concrete(ConcreteValue::List(vec![ let return_value = Some(Value::Concrete(ConcreteValue::List {
ConcreteValue::Character('a'), items: vec![ConcreteValue::Character('a'), ConcreteValue::Character('b')],
ConcreteValue::Character('b'), item_type: TypeCode::CHARACTER,
]))); }));
assert_eq!(chunk, compile(source).unwrap()); assert_eq!(chunk, compile(source).unwrap());
assert_eq!(return_value, run(source).unwrap()); assert_eq!(return_value, run(source).unwrap());
@ -218,10 +218,10 @@ fn load_float_list() {
constants: vec![ConcreteValue::Float(42.42), ConcreteValue::Float(24.24)], constants: vec![ConcreteValue::Float(42.42), ConcreteValue::Float(24.24)],
..Chunk::default() ..Chunk::default()
}; };
let return_value = Some(Value::Concrete(ConcreteValue::List(vec![ let return_value = Some(Value::Concrete(ConcreteValue::List {
ConcreteValue::Float(42.42), items: vec![ConcreteValue::Float(42.42), ConcreteValue::Float(24.24)],
ConcreteValue::Float(24.24), item_type: TypeCode::FLOAT,
]))); }));
assert_eq!(chunk, compile(source).unwrap()); assert_eq!(chunk, compile(source).unwrap());
assert_eq!(return_value, run(source).unwrap()); assert_eq!(return_value, run(source).unwrap());
@ -247,11 +247,14 @@ fn load_integer_list() {
], ],
..Chunk::default() ..Chunk::default()
}; };
let return_value = Some(Value::Concrete(ConcreteValue::List(vec![ let return_value = Some(Value::Concrete(ConcreteValue::List {
ConcreteValue::Integer(1), items: vec![
ConcreteValue::Integer(2), ConcreteValue::Integer(1),
ConcreteValue::Integer(3), ConcreteValue::Integer(2),
]))); ConcreteValue::Integer(3),
],
item_type: TypeCode::INTEGER,
}));
assert_eq!(chunk, compile(source).unwrap()); assert_eq!(chunk, compile(source).unwrap());
assert_eq!(return_value, run(source).unwrap()); assert_eq!(return_value, run(source).unwrap());
@ -275,10 +278,13 @@ fn load_string_list() {
], ],
..Chunk::default() ..Chunk::default()
}; };
let return_value = Some(Value::Concrete(ConcreteValue::List(vec![ let return_value = Some(Value::Concrete(ConcreteValue::List {
ConcreteValue::String(DustString::from("Hello")), items: vec![
ConcreteValue::String(DustString::from("World")), ConcreteValue::String(DustString::from("Hello")),
]))); ConcreteValue::String(DustString::from("World")),
],
item_type: TypeCode::STRING,
}));
assert_eq!(chunk, compile(source).unwrap()); assert_eq!(chunk, compile(source).unwrap());
assert_eq!(return_value, run(source).unwrap()); assert_eq!(return_value, run(source).unwrap());
@ -317,10 +323,19 @@ fn load_nested_list() {
], ],
..Chunk::default() ..Chunk::default()
}; };
let return_value = Some(Value::Concrete(ConcreteValue::List(vec![ let return_value = Some(Value::Concrete(ConcreteValue::List {
ConcreteValue::List(vec![ConcreteValue::Integer(1), ConcreteValue::Integer(2)]), items: vec![
ConcreteValue::List(vec![ConcreteValue::Integer(3), ConcreteValue::Integer(4)]), 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,
}));
assert_eq!(chunk, compile(source).unwrap()); assert_eq!(chunk, compile(source).unwrap());
assert_eq!(return_value, run(source).unwrap()); assert_eq!(return_value, run(source).unwrap());
@ -383,16 +398,37 @@ fn load_deeply_nested_list() {
], ],
..Chunk::default() ..Chunk::default()
}; };
let return_value = Some(Value::Concrete(ConcreteValue::List(vec![ let return_value = Some(Value::Concrete(ConcreteValue::List {
ConcreteValue::List(vec![ items: vec![
ConcreteValue::List(vec![ConcreteValue::Integer(1), ConcreteValue::Integer(2)]), ConcreteValue::List {
ConcreteValue::List(vec![ConcreteValue::Integer(3), ConcreteValue::Integer(4)]), items: vec![
]), ConcreteValue::List {
ConcreteValue::List(vec![ items: vec![ConcreteValue::Integer(1), ConcreteValue::Integer(2)],
ConcreteValue::List(vec![ConcreteValue::Integer(5), ConcreteValue::Integer(6)]), item_type: TypeCode::INTEGER,
ConcreteValue::List(vec![ConcreteValue::Integer(7), ConcreteValue::Integer(8)]), },
]), 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,
}));
assert_eq!(chunk, compile(source).unwrap()); assert_eq!(chunk, compile(source).unwrap());
assert_eq!(return_value, run(source).unwrap()); assert_eq!(return_value, run(source).unwrap());