Fix and pass all tests
This commit is contained in:
parent
ac11ad5674
commit
d3addbe183
@ -44,7 +44,7 @@ use crate::{
|
|||||||
/// let source = "40 + 2 == 42";
|
/// let source = "40 + 2 == 42";
|
||||||
/// let chunk = compile(source).unwrap();
|
/// let chunk = compile(source).unwrap();
|
||||||
///
|
///
|
||||||
/// assert_eq!(chunk.instructions().len(), 3);
|
/// assert_eq!(chunk.instructions.len(), 6);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn compile(source: &str) -> Result<Chunk, DustError> {
|
pub fn compile(source: &str) -> Result<Chunk, DustError> {
|
||||||
let lexer = Lexer::new(source);
|
let lexer = Lexer::new(source);
|
||||||
@ -796,7 +796,13 @@ impl<'src> Compiler<'src> {
|
|||||||
fn handle_binary_argument(&mut self, instruction: &Instruction) -> (Operand, bool) {
|
fn handle_binary_argument(&mut self, instruction: &Instruction) -> (Operand, bool) {
|
||||||
let operand = instruction.as_operand();
|
let operand = instruction.as_operand();
|
||||||
let push_back = match instruction.operation() {
|
let push_back = match instruction.operation() {
|
||||||
Operation::LOAD_ENCODED | Operation::LOAD_SELF => true,
|
Operation::LOAD_ENCODED
|
||||||
|
| Operation::LOAD_SELF
|
||||||
|
| Operation::ADD
|
||||||
|
| Operation::SUBTRACT
|
||||||
|
| Operation::MULTIPLY
|
||||||
|
| Operation::DIVIDE
|
||||||
|
| Operation::MODULO => true,
|
||||||
_ => !instruction.yields_value(),
|
_ => !instruction.yields_value(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -8,8 +8,8 @@ pub struct Add {
|
|||||||
pub right: Operand,
|
pub right: Operand,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Instruction> for Add {
|
impl From<&Instruction> for Add {
|
||||||
fn from(instruction: Instruction) -> Self {
|
fn from(instruction: &Instruction) -> Self {
|
||||||
let destination = instruction.a_field();
|
let destination = instruction.a_field();
|
||||||
let (left, right) = instruction.b_and_c_as_operands();
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
|
||||||
|
@ -20,40 +20,30 @@
|
|||||||
//! you may also need to modify its flags. It is usually best to remove instructions and insert new
|
//! you may also need to modify its flags. It is usually best to remove instructions and insert new
|
||||||
//! ones in their place instead of mutating them.
|
//! ones in their place instead of mutating them.
|
||||||
//!
|
//!
|
||||||
//! # Examples
|
//! # Creating Instructions
|
||||||
//!
|
|
||||||
//! ## Creating Instructions
|
|
||||||
//!
|
//!
|
||||||
//! For each operation, there are two ways to create an instruction:
|
//! For each operation, there are two ways to create an instruction:
|
||||||
//!
|
//!
|
||||||
//! - Use the associated function on `Instruction`
|
//! - Use the associated function on `Instruction`
|
||||||
//! - Use the corresponding struct and call `Instruction::from`
|
//! - Use the corresponding struct and call `Instruction::from`
|
||||||
//!
|
//!
|
||||||
//! Both produce the same result, but the first is more concise. The structs are more useful when
|
//! Both produce the same result, but the first is usuall more concise. The structs are more useful
|
||||||
//! reading instructions, as shown below.
|
//! when reading instructions, as shown below.
|
||||||
//!
|
|
||||||
//! ```
|
|
||||||
//! # use dust_lang::instruction::{Instruction, Move};
|
|
||||||
//! let move_1 = Instruction::r#move(42, 4);
|
|
||||||
//! let move_2 = Instruction::from(Move { from: 42, to: 4 });
|
|
||||||
//!
|
|
||||||
//! assert_eq!(move_1, move_2);
|
|
||||||
//! ```
|
|
||||||
//!
|
//!
|
||||||
//! Use the [`Operand`][] type when creating instructions. In addition to being easy to read and
|
//! Use the [`Operand`][] type when creating instructions. In addition to being easy to read and
|
||||||
//! write, this ensures that the instruction has the correct flags to represent the operands.
|
//! write, this ensures that the instruction has the correct flags to represent the operands.
|
||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
//! # use dust_lang::instruction::{Instruction, Add, Operand};
|
//! # use dust_lang::instruction::{Instruction, Add, Operand, TypeCode};
|
||||||
//! let add_1 = Instruction::add(
|
//! let add_1 = Instruction::add(
|
||||||
//! 0,
|
//! 0,
|
||||||
//! Operand::Register(1),
|
//! Operand::Register(1, TypeCode::INTEGER),
|
||||||
//! Operand::Constant(2)
|
//! Operand::Constant(2, TypeCode::INTEGER)
|
||||||
//! );
|
//! );
|
||||||
//! let add_2 = Instruction::from(Add {
|
//! let add_2 = Instruction::from(Add {
|
||||||
//! destination: 0,
|
//! destination: 0,
|
||||||
//! left: Operand::Register(1),
|
//! left: Operand::Register(1, TypeCode::INTEGER),
|
||||||
//! right: Operand::Constant(2),
|
//! right: Operand::Constant(2, TypeCode::INTEGER),
|
||||||
//! });
|
//! });
|
||||||
//!
|
//!
|
||||||
//! assert_eq!(add_1, add_2);
|
//! assert_eq!(add_1, add_2);
|
||||||
@ -67,24 +57,25 @@
|
|||||||
//! D fields as `u16`, `bool` or `Operand` values.
|
//! D fields as `u16`, `bool` or `Operand` values.
|
||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
//! # use dust_lang::instruction::{Instruction, Add, Operand, Operation};
|
//! # use dust_lang::instruction::{Instruction, Add, Operand, Operation, TypeCode};
|
||||||
//! # let mystery_instruction = Instruction::add(
|
//! # let mystery_instruction = Instruction::add(
|
||||||
//! # 1,
|
//! # 1,
|
||||||
//! # Operand::Register(1),
|
//! # Operand::Register(1, TypeCode::INTEGER),
|
||||||
//! # Operand::Constant(2)
|
//! # Operand::Constant(2, TypeCode::INTEGER)
|
||||||
//! # );
|
//! # );
|
||||||
//! // Let's read an instruction and see if it performs addition-assignment,
|
//! // Let's read an instruction and see if it performs addition-assignment,
|
||||||
//! // like in one of the following examples:
|
//! // like in one of the following examples:
|
||||||
//! // - `a += 2`
|
//! // - `a += 2`
|
||||||
//! // - `a = a + 2`
|
//! // - `a = a + 2`
|
||||||
|
//! // - `a = 2 + a`
|
||||||
//!
|
//!
|
||||||
//! let operation = mystery_instruction.operation();
|
//! let operation = mystery_instruction.operation();
|
||||||
//! let is_add_assign = match operation {
|
//! let is_add_assign = match operation {
|
||||||
//! Operation::Add => {
|
//! Operation::ADD => {
|
||||||
//! let Add { destination, left, right } = Add::from(&mystery_instruction);
|
//! let Add { destination, left, right } = Add::from(&mystery_instruction);
|
||||||
//!
|
//!
|
||||||
//! left == Operand::Register(destination)
|
//! left == Operand::Register(destination, TypeCode::INTEGER)
|
||||||
//! || right == Operand::Register(destination)
|
//! || right == Operand::Register(destination, TypeCode::INTEGER)
|
||||||
//!
|
//!
|
||||||
//! }
|
//! }
|
||||||
//! _ => false,
|
//! _ => false,
|
||||||
@ -329,7 +320,26 @@ impl Instruction {
|
|||||||
|
|
||||||
Operand::Register(destination, TypeCode::FUNCTION)
|
Operand::Register(destination, TypeCode::FUNCTION)
|
||||||
}
|
}
|
||||||
_ => todo!(),
|
Operation::ADD => {
|
||||||
|
let Add {
|
||||||
|
destination, left, ..
|
||||||
|
} = Add::from(self);
|
||||||
|
|
||||||
|
let register_type = match left.as_type() {
|
||||||
|
TypeCode::BOOLEAN => TypeCode::BOOLEAN,
|
||||||
|
TypeCode::BYTE => TypeCode::BYTE,
|
||||||
|
TypeCode::CHARACTER => TypeCode::STRING,
|
||||||
|
TypeCode::INTEGER => TypeCode::INTEGER,
|
||||||
|
TypeCode::FLOAT => TypeCode::FLOAT,
|
||||||
|
TypeCode::STRING => TypeCode::STRING,
|
||||||
|
TypeCode::LIST => TypeCode::LIST,
|
||||||
|
TypeCode::FUNCTION => TypeCode::FUNCTION,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
Operand::Register(destination, register_type)
|
||||||
|
}
|
||||||
|
unsupported => todo!("Support {unsupported}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -609,7 +619,7 @@ impl Instruction {
|
|||||||
Operation::LOAD_FUNCTION => LoadFunction::from(*self).to_string(),
|
Operation::LOAD_FUNCTION => LoadFunction::from(*self).to_string(),
|
||||||
Operation::LOAD_LIST => LoadList::from(*self).to_string(),
|
Operation::LOAD_LIST => LoadList::from(*self).to_string(),
|
||||||
Operation::LOAD_SELF => LoadSelf::from(*self).to_string(),
|
Operation::LOAD_SELF => LoadSelf::from(*self).to_string(),
|
||||||
Operation::ADD => Add::from(*self).to_string(),
|
Operation::ADD => Add::from(self).to_string(),
|
||||||
Operation::SUBTRACT => Subtract::from(*self).to_string(),
|
Operation::SUBTRACT => Subtract::from(*self).to_string(),
|
||||||
Operation::MULTIPLY => Multiply::from(*self).to_string(),
|
Operation::MULTIPLY => Multiply::from(*self).to_string(),
|
||||||
Operation::DIVIDE => Divide::from(*self).to_string(),
|
Operation::DIVIDE => Divide::from(*self).to_string(),
|
||||||
|
@ -14,10 +14,10 @@
|
|||||||
//! ## Examples
|
//! ## Examples
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```rust
|
||||||
//! # use dust_lang::{run, ConcreteValue};
|
//! # use dust_lang::{run, Value};
|
||||||
//! let result = run("21 * 2").unwrap();
|
//! let result = run("21 * 2").unwrap();
|
||||||
//!
|
//!
|
||||||
//! assert_eq!(result, Some(ConcreteValue::Integer(42)));
|
//! assert_eq!(result, Some(Value::integer(42)));
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```rust
|
||||||
|
@ -430,7 +430,43 @@ pub fn add(instruction: InstructionFields, thread: &mut Thread) {
|
|||||||
|
|
||||||
pub fn subtract(instruction: InstructionFields, thread: &mut Thread) {}
|
pub fn subtract(instruction: InstructionFields, thread: &mut Thread) {}
|
||||||
|
|
||||||
pub fn multiply(instruction: InstructionFields, thread: &mut Thread) {}
|
pub fn multiply(instruction: InstructionFields, thread: &mut Thread) {
|
||||||
|
let destination = instruction.a_field as usize;
|
||||||
|
let left = instruction.b_field as usize;
|
||||||
|
let left_type = instruction.b_type;
|
||||||
|
let left_is_constant = instruction.b_is_constant;
|
||||||
|
let right = instruction.c_field as usize;
|
||||||
|
let right_type = instruction.c_type;
|
||||||
|
let right_is_constant = instruction.c_is_constant;
|
||||||
|
|
||||||
|
match (left_type, right_type) {
|
||||||
|
(TypeCode::INTEGER, TypeCode::INTEGER) => {
|
||||||
|
let left_value = if left_is_constant {
|
||||||
|
if cfg!(debug_assertions) {
|
||||||
|
thread.get_constant(left).as_integer().unwrap()
|
||||||
|
} else {
|
||||||
|
unsafe { thread.get_constant(left).as_integer().unwrap_unchecked() }
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
thread.get_integer_register(left)
|
||||||
|
};
|
||||||
|
let right_value = if right_is_constant {
|
||||||
|
if cfg!(debug_assertions) {
|
||||||
|
thread.get_constant(right).as_integer().unwrap()
|
||||||
|
} else {
|
||||||
|
unsafe { thread.get_constant(right).as_integer().unwrap_unchecked() }
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
thread.get_integer_register(right)
|
||||||
|
};
|
||||||
|
let result = left_value * right_value;
|
||||||
|
let register = Register::Value(result);
|
||||||
|
|
||||||
|
thread.set_integer_register(destination as usize, register);
|
||||||
|
}
|
||||||
|
_ => unimplemented!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn divide(instruction: InstructionFields, thread: &mut Thread) {}
|
pub fn divide(instruction: InstructionFields, thread: &mut Thread) {}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user