1
0

Extend and pass tests

This commit is contained in:
Jeff 2025-02-08 00:17:15 -05:00
parent d3addbe183
commit e387579a81
8 changed files with 172 additions and 72 deletions

View File

@ -38,3 +38,7 @@ harness = false
[[bench]]
name = "threads"
harness = false
[[test]]
name = "add"
path = "tests/math/add.rs"

View File

@ -269,7 +269,7 @@ impl<'src> Compiler<'src> {
.iter()
.rev()
.find_map(|(instruction, r#type, _)| {
if r#type == &Type::Boolean && instruction.yields_value() {
if instruction.b_type() == TypeCode::BOOLEAN && instruction.yields_value() {
Some(instruction.a_field() + 1)
} else {
None
@ -301,7 +301,10 @@ impl<'src> Compiler<'src> {
.iter()
.rev()
.find_map(|(instruction, r#type, _)| {
if r#type == &Type::Character && instruction.yields_value() {
if instruction.b_type() == TypeCode::CHARACTER
&& r#type == &Type::Character
&& instruction.yields_value()
{
Some(instruction.a_field() + 1)
} else {
None
@ -314,8 +317,8 @@ impl<'src> Compiler<'src> {
self.instructions
.iter()
.rev()
.find_map(|(instruction, r#type, _)| {
if r#type == &Type::Float && instruction.yields_value() {
.find_map(|(instruction, _, _)| {
if instruction.b_type() == TypeCode::FLOAT && instruction.yields_value() {
Some(instruction.a_field() + 1)
} else {
None
@ -329,7 +332,7 @@ impl<'src> Compiler<'src> {
.iter()
.rev()
.find_map(|(instruction, r#type, _)| {
if r#type == &Type::Integer && instruction.yields_value() {
if r#type == &Type::Integer {
Some(instruction.a_field() + 1)
} else {
None
@ -343,7 +346,10 @@ impl<'src> Compiler<'src> {
.iter()
.rev()
.find_map(|(instruction, r#type, _)| {
if r#type == &Type::String && instruction.yields_value() {
if instruction.b_type() == TypeCode::STRING
&& r#type == &Type::String
&& instruction.yields_value()
{
Some(instruction.a_field() + 1)
} else {
None
@ -358,7 +364,11 @@ impl<'src> Compiler<'src> {
.rev()
.find_map(|(instruction, r#type, _)| {
if let Type::List(_) = r#type {
Some(instruction.a_field() + 1)
if instruction.yields_value() {
Some(instruction.a_field() + 1)
} else {
None
}
} else {
None
}
@ -370,10 +380,8 @@ impl<'src> Compiler<'src> {
self.instructions
.iter()
.rev()
.find_map(|(instruction, r#type, _)| {
if matches!(r#type, Type::Function(_) | Type::SelfFunction)
&& instruction.yields_value()
{
.find_map(|(instruction, _, _)| {
if instruction.b_type() == TypeCode::FUNCTION && instruction.yields_value() {
Some(instruction.a_field() + 1)
} else {
None
@ -858,6 +866,10 @@ impl<'src> Compiler<'src> {
self.advance()?;
self.parse_sub_expression(&rule.precedence)?;
if is_assignment {
self.allow(Token::Semicolon)?;
}
let (right_instruction, right_type, right_position) = self.instructions.pop().unwrap();
let (right, push_back_right) = self.handle_binary_argument(&right_instruction);
@ -1164,25 +1176,7 @@ impl<'src> Compiler<'src> {
let (math_instruction, _, _) = self.instructions.last_mut().unwrap();
math_instruction.set_a_field(local_register_index);
} else {
let register = match local_type {
Type::Boolean => self.next_boolean_register(),
Type::Byte => self.next_byte_register(),
Type::Character => self.next_character_register(),
Type::Float => self.next_float_register(),
Type::Integer => self.next_integer_register(),
Type::String => self.next_string_register(),
_ => todo!(),
};
let point = Instruction::point(
local_register_index,
Operand::Register(register, local_type.type_code()),
);
self.emit_instruction(point, local_type, start_position);
}
return Ok(());
}
let destination = match local_type {
@ -1262,25 +1256,12 @@ impl<'src> Compiler<'src> {
if item_type == Type::None {
item_type = self.get_last_instruction_type();
} else {
// TODO: Check if the item type the same as the previous item type
}
if start_register.is_none() {
let first_index = match item_type {
Type::Boolean => self.next_boolean_register() - 1,
Type::Byte => self.next_byte_register() - 1,
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,
Type::List(_) => self.next_list_register() - 1,
Type::None => {
return Err(CompileError::ExpectedExpression {
found: self.previous_token.to_owned(),
position: self.previous_position,
});
}
_ => todo!(),
};
let first_index = self.instructions.last().unwrap().0.a_field();
start_register = Some(first_index);
}
@ -1369,12 +1350,12 @@ impl<'src> Compiler<'src> {
}
}
Type::List(_) => {
let used_list_registers = self.next_list_register() - next_list_register - 1;
let used_list_registers = self.next_list_register() - next_list_register;
if used_list_registers > 1 {
let close = Instruction::close(
next_list_register,
next_list_register + used_list_registers - 1,
self.next_list_register() - 2,
TypeCode::LIST,
);
@ -1387,13 +1368,13 @@ impl<'src> Compiler<'src> {
let end = self.previous_position.1;
let end_register = match item_type {
Type::Boolean => self.next_boolean_register() - 1,
Type::Byte => self.next_byte_register() - 1,
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,
Type::List(_) => self.next_list_register() - 1,
Type::Boolean => self.next_boolean_register().saturating_sub(1),
Type::Byte => self.next_byte_register().saturating_sub(1),
Type::Character => self.next_character_register().saturating_sub(1),
Type::Float => self.next_float_register().saturating_sub(1),
Type::Integer => self.next_integer_register().saturating_sub(1),
Type::String => self.next_string_register().saturating_sub(1),
Type::List(_) => self.next_list_register().saturating_sub(1),
_ => todo!(),
};
let destination = self.next_list_register();
@ -1636,11 +1617,6 @@ impl<'src> Compiler<'src> {
Ok(())
}
fn parse_semicolon(&mut self) -> Result<(), CompileError> {
self.advance()?;
self.parse(Precedence::None)
}
fn parse_expression(&mut self) -> Result<(), CompileError> {
self.parse(Precedence::None)?;
@ -1732,8 +1708,18 @@ impl<'src> Compiler<'src> {
if matches!(self.get_last_operation(), Some(Operation::POINT)) {
let Point { to, .. } = Point::from(self.instructions.last().unwrap().0);
let (_, r#type, _) = self.instructions.pop().unwrap();
let r#return = Instruction::r#return(true, to.index(), to.as_type());
let (point, r#type, position) = self.instructions.pop().unwrap();
let (should_return, target_register) = if r#type == Type::None {
(false, 0)
} else {
(true, to.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.emit_instruction(r#return, r#type, self.current_position);
} else if matches!(self.get_last_operation(), Some(Operation::RETURN))
@ -1821,6 +1807,7 @@ impl<'src> Compiler<'src> {
self.expect(Token::Equal)?;
self.parse_expression()?;
self.allow(Token::Semicolon)?;
let register_index = match self.get_last_instruction_type() {
Type::Boolean => self.next_boolean_register() - 1,

View File

@ -237,7 +237,7 @@ impl From<&Token<'_>> for ParseRule<'_> {
precedence: Precedence::None,
},
Token::Semicolon => ParseRule {
prefix: Some(Compiler::parse_semicolon),
prefix: None,
infix: None,
precedence: Precedence::None,
},

View File

@ -42,12 +42,12 @@ impl Display for Point {
let Point { destination, to } = self;
match to.as_type() {
TypeCode::BOOLEAN => write!(f, "R_BOOL_{destination} -> R_BOOL_{to}"),
TypeCode::BYTE => write!(f, "R_BYTE_{destination} -> R_BYTE_{to}"),
TypeCode::CHARACTER => write!(f, "R_CHAR_{destination} -> R_CHAR_{to}"),
TypeCode::FLOAT => write!(f, "R_FLOAT_{destination} -> R_FLOAT_{to}"),
TypeCode::INTEGER => write!(f, "R_INT_{destination} -> R_INT_{to}"),
TypeCode::STRING => write!(f, "R_STR_{destination} -> R_STR_{to}"),
TypeCode::BOOLEAN => write!(f, "R_BOOL_{destination} -> {to}"),
TypeCode::BYTE => write!(f, "R_BYTE_{destination} -> {to}"),
TypeCode::CHARACTER => write!(f, "R_CHAR_{destination} -> {to}"),
TypeCode::FLOAT => write!(f, "R_FLOAT_{destination} -> {to}"),
TypeCode::INTEGER => write!(f, "R_INT_{destination} -> {to}"),
TypeCode::STRING => write!(f, "R_STR_{destination} -> {to}"),
unsupported => write!(
f,
"Unsupported type code: {unsupported} for Point instruction"

View File

@ -62,7 +62,7 @@ impl Display for Return {
TypeCode::STRING => write!(f, "R_STR_{return_register}"),
TypeCode::LIST => write!(f, "R_LIST_{return_register}"),
TypeCode::FUNCTION => write!(f, "R_FN_{return_register}"),
unsupported => unreachable!("Unsupported return type: {:?}", unsupported),
unsupported => unreachable!("Unsupported return type: {}", unsupported),
}
} else {
write!(f, "RETURN")

View File

@ -68,7 +68,112 @@ pub const RUNNER_LOGIC_TABLE: [RunnerLogic; 23] = [
r#return,
];
pub fn point(_: InstructionFields, thread: &mut Thread) {}
pub fn point(instruction: InstructionFields, thread: &mut Thread) {
let destination = instruction.a_field as usize;
let to = instruction.b_field as usize;
let to_is_constant = instruction.b_is_constant;
let r#type = instruction.b_type;
match r#type {
TypeCode::BOOLEAN => {
let boolean = if to_is_constant {
if cfg!(debug_assertions) {
thread.get_constant(to).as_boolean().unwrap()
} else {
unsafe { thread.get_constant(to).as_boolean().unwrap_unchecked() }
}
} else {
thread.get_boolean_register(to)
};
let register = Register::Value(*boolean);
thread.set_boolean_register(destination, register);
}
TypeCode::BYTE => {
let byte = if to_is_constant {
if cfg!(debug_assertions) {
thread.get_constant(to).as_byte().unwrap()
} else {
unsafe { thread.get_constant(to).as_byte().unwrap_unchecked() }
}
} else {
thread.get_byte_register(to)
};
let register = Register::Value(*byte);
thread.set_byte_register(destination, register);
}
TypeCode::CHARACTER => {
let character = if to_is_constant {
if cfg!(debug_assertions) {
thread.get_constant(to).as_character().unwrap()
} else {
unsafe { thread.get_constant(to).as_character().unwrap_unchecked() }
}
} else {
thread.get_character_register(to)
};
let register = Register::Value(*character);
thread.set_character_register(destination, register);
}
TypeCode::FLOAT => {
let float = if to_is_constant {
if cfg!(debug_assertions) {
thread.get_constant(to).as_float().unwrap()
} else {
unsafe { thread.get_constant(to).as_float().unwrap_unchecked() }
}
} else {
thread.get_float_register(to)
};
let register = Register::Value(*float);
thread.set_float_register(destination, register);
}
TypeCode::INTEGER => {
let integer = if to_is_constant {
if cfg!(debug_assertions) {
thread.get_constant(to).as_integer().unwrap()
} else {
unsafe { thread.get_constant(to).as_integer().unwrap_unchecked() }
}
} else {
thread.get_integer_register(to)
};
let register = Register::Value(*integer);
thread.set_integer_register(destination, register);
}
TypeCode::STRING => {
let string = if to_is_constant {
if cfg!(debug_assertions) {
thread.get_constant(to).as_string().unwrap().clone()
} else {
unsafe {
thread
.get_constant(to)
.as_string()
.unwrap_unchecked()
.clone()
}
}
} else {
thread.get_string_register(to).clone()
};
let register = Register::Value(string);
thread.set_string_register(destination, register);
}
TypeCode::LIST => {
let list = thread.get_list_register(to).clone();
let register = Register::Value(list);
thread.set_list_register(destination, register);
}
_ => unimplemented!(),
}
}
pub fn close(instruction: InstructionFields, thread: &mut Thread) {
let from = instruction.b_field as usize;
@ -599,7 +704,9 @@ pub fn r#return(instruction: InstructionFields, thread: &mut Thread) {
let mut concrete_list = Vec::with_capacity(abstract_list.item_pointers.len());
for pointer in &abstract_list.item_pointers {
concrete_list.push(thread.get_value_from_pointer(pointer));
let value = thread.get_value_from_pointer(pointer);
concrete_list.push(value);
}
thread.return_value =

View File

@ -122,7 +122,9 @@ impl Thread {
let mut concrete_list = Vec::with_capacity(abstract_list.item_pointers.len());
for pointer in &abstract_list.item_pointers {
concrete_list.push(self.get_value_from_pointer(pointer));
let value = self.get_value_from_pointer(pointer);
concrete_list.push(value);
}
ConcreteValue::List(concrete_list)