Extend and pass tests
This commit is contained in:
parent
d3addbe183
commit
e387579a81
@ -38,3 +38,7 @@ harness = false
|
|||||||
[[bench]]
|
[[bench]]
|
||||||
name = "threads"
|
name = "threads"
|
||||||
harness = false
|
harness = false
|
||||||
|
|
||||||
|
[[test]]
|
||||||
|
name = "add"
|
||||||
|
path = "tests/math/add.rs"
|
||||||
|
@ -269,7 +269,7 @@ impl<'src> Compiler<'src> {
|
|||||||
.iter()
|
.iter()
|
||||||
.rev()
|
.rev()
|
||||||
.find_map(|(instruction, r#type, _)| {
|
.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)
|
Some(instruction.a_field() + 1)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -301,7 +301,10 @@ impl<'src> Compiler<'src> {
|
|||||||
.iter()
|
.iter()
|
||||||
.rev()
|
.rev()
|
||||||
.find_map(|(instruction, r#type, _)| {
|
.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)
|
Some(instruction.a_field() + 1)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -314,8 +317,8 @@ impl<'src> Compiler<'src> {
|
|||||||
self.instructions
|
self.instructions
|
||||||
.iter()
|
.iter()
|
||||||
.rev()
|
.rev()
|
||||||
.find_map(|(instruction, r#type, _)| {
|
.find_map(|(instruction, _, _)| {
|
||||||
if r#type == &Type::Float && instruction.yields_value() {
|
if instruction.b_type() == TypeCode::FLOAT && instruction.yields_value() {
|
||||||
Some(instruction.a_field() + 1)
|
Some(instruction.a_field() + 1)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -329,7 +332,7 @@ impl<'src> Compiler<'src> {
|
|||||||
.iter()
|
.iter()
|
||||||
.rev()
|
.rev()
|
||||||
.find_map(|(instruction, r#type, _)| {
|
.find_map(|(instruction, r#type, _)| {
|
||||||
if r#type == &Type::Integer && instruction.yields_value() {
|
if r#type == &Type::Integer {
|
||||||
Some(instruction.a_field() + 1)
|
Some(instruction.a_field() + 1)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -343,7 +346,10 @@ impl<'src> Compiler<'src> {
|
|||||||
.iter()
|
.iter()
|
||||||
.rev()
|
.rev()
|
||||||
.find_map(|(instruction, r#type, _)| {
|
.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)
|
Some(instruction.a_field() + 1)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -358,7 +364,11 @@ impl<'src> Compiler<'src> {
|
|||||||
.rev()
|
.rev()
|
||||||
.find_map(|(instruction, r#type, _)| {
|
.find_map(|(instruction, r#type, _)| {
|
||||||
if let Type::List(_) = 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 {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -370,10 +380,8 @@ impl<'src> Compiler<'src> {
|
|||||||
self.instructions
|
self.instructions
|
||||||
.iter()
|
.iter()
|
||||||
.rev()
|
.rev()
|
||||||
.find_map(|(instruction, r#type, _)| {
|
.find_map(|(instruction, _, _)| {
|
||||||
if matches!(r#type, Type::Function(_) | Type::SelfFunction)
|
if instruction.b_type() == TypeCode::FUNCTION && instruction.yields_value() {
|
||||||
&& instruction.yields_value()
|
|
||||||
{
|
|
||||||
Some(instruction.a_field() + 1)
|
Some(instruction.a_field() + 1)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -858,6 +866,10 @@ impl<'src> Compiler<'src> {
|
|||||||
self.advance()?;
|
self.advance()?;
|
||||||
self.parse_sub_expression(&rule.precedence)?;
|
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_instruction, right_type, right_position) = self.instructions.pop().unwrap();
|
||||||
let (right, push_back_right) = self.handle_binary_argument(&right_instruction);
|
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();
|
let (math_instruction, _, _) = self.instructions.last_mut().unwrap();
|
||||||
|
|
||||||
math_instruction.set_a_field(local_register_index);
|
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 {
|
let destination = match local_type {
|
||||||
@ -1262,25 +1256,12 @@ impl<'src> Compiler<'src> {
|
|||||||
|
|
||||||
if item_type == Type::None {
|
if item_type == Type::None {
|
||||||
item_type = self.get_last_instruction_type();
|
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() {
|
if start_register.is_none() {
|
||||||
let first_index = match item_type {
|
let first_index = self.instructions.last().unwrap().0.a_field();
|
||||||
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!(),
|
|
||||||
};
|
|
||||||
|
|
||||||
start_register = Some(first_index);
|
start_register = Some(first_index);
|
||||||
}
|
}
|
||||||
@ -1369,12 +1350,12 @@ impl<'src> Compiler<'src> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Type::List(_) => {
|
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 {
|
if used_list_registers > 1 {
|
||||||
let close = Instruction::close(
|
let close = Instruction::close(
|
||||||
next_list_register,
|
next_list_register,
|
||||||
next_list_register + used_list_registers - 1,
|
self.next_list_register() - 2,
|
||||||
TypeCode::LIST,
|
TypeCode::LIST,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -1387,13 +1368,13 @@ impl<'src> Compiler<'src> {
|
|||||||
|
|
||||||
let end = self.previous_position.1;
|
let end = self.previous_position.1;
|
||||||
let end_register = match item_type {
|
let end_register = match item_type {
|
||||||
Type::Boolean => self.next_boolean_register() - 1,
|
Type::Boolean => self.next_boolean_register().saturating_sub(1),
|
||||||
Type::Byte => self.next_byte_register() - 1,
|
Type::Byte => self.next_byte_register().saturating_sub(1),
|
||||||
Type::Character => self.next_character_register() - 1,
|
Type::Character => self.next_character_register().saturating_sub(1),
|
||||||
Type::Float => self.next_float_register() - 1,
|
Type::Float => self.next_float_register().saturating_sub(1),
|
||||||
Type::Integer => self.next_integer_register() - 1,
|
Type::Integer => self.next_integer_register().saturating_sub(1),
|
||||||
Type::String => self.next_string_register() - 1,
|
Type::String => self.next_string_register().saturating_sub(1),
|
||||||
Type::List(_) => self.next_list_register() - 1,
|
Type::List(_) => self.next_list_register().saturating_sub(1),
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
};
|
};
|
||||||
let destination = self.next_list_register();
|
let destination = self.next_list_register();
|
||||||
@ -1636,11 +1617,6 @@ impl<'src> Compiler<'src> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_semicolon(&mut self) -> Result<(), CompileError> {
|
|
||||||
self.advance()?;
|
|
||||||
self.parse(Precedence::None)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_expression(&mut self) -> Result<(), CompileError> {
|
fn parse_expression(&mut self) -> Result<(), CompileError> {
|
||||||
self.parse(Precedence::None)?;
|
self.parse(Precedence::None)?;
|
||||||
|
|
||||||
@ -1732,8 +1708,18 @@ impl<'src> Compiler<'src> {
|
|||||||
if matches!(self.get_last_operation(), Some(Operation::POINT)) {
|
if matches!(self.get_last_operation(), Some(Operation::POINT)) {
|
||||||
let Point { to, .. } = Point::from(self.instructions.last().unwrap().0);
|
let Point { to, .. } = Point::from(self.instructions.last().unwrap().0);
|
||||||
|
|
||||||
let (_, r#type, _) = self.instructions.pop().unwrap();
|
let (point, r#type, position) = self.instructions.pop().unwrap();
|
||||||
let r#return = Instruction::r#return(true, to.index(), to.as_type());
|
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);
|
self.emit_instruction(r#return, r#type, self.current_position);
|
||||||
} else if matches!(self.get_last_operation(), Some(Operation::RETURN))
|
} else if matches!(self.get_last_operation(), Some(Operation::RETURN))
|
||||||
@ -1821,6 +1807,7 @@ impl<'src> Compiler<'src> {
|
|||||||
|
|
||||||
self.expect(Token::Equal)?;
|
self.expect(Token::Equal)?;
|
||||||
self.parse_expression()?;
|
self.parse_expression()?;
|
||||||
|
self.allow(Token::Semicolon)?;
|
||||||
|
|
||||||
let register_index = match self.get_last_instruction_type() {
|
let register_index = match self.get_last_instruction_type() {
|
||||||
Type::Boolean => self.next_boolean_register() - 1,
|
Type::Boolean => self.next_boolean_register() - 1,
|
||||||
|
@ -237,7 +237,7 @@ impl From<&Token<'_>> for ParseRule<'_> {
|
|||||||
precedence: Precedence::None,
|
precedence: Precedence::None,
|
||||||
},
|
},
|
||||||
Token::Semicolon => ParseRule {
|
Token::Semicolon => ParseRule {
|
||||||
prefix: Some(Compiler::parse_semicolon),
|
prefix: None,
|
||||||
infix: None,
|
infix: None,
|
||||||
precedence: Precedence::None,
|
precedence: Precedence::None,
|
||||||
},
|
},
|
||||||
|
@ -42,12 +42,12 @@ impl Display for Point {
|
|||||||
let Point { destination, to } = self;
|
let Point { destination, to } = self;
|
||||||
|
|
||||||
match to.as_type() {
|
match to.as_type() {
|
||||||
TypeCode::BOOLEAN => write!(f, "R_BOOL_{destination} -> R_BOOL_{to}"),
|
TypeCode::BOOLEAN => write!(f, "R_BOOL_{destination} -> {to}"),
|
||||||
TypeCode::BYTE => write!(f, "R_BYTE_{destination} -> R_BYTE_{to}"),
|
TypeCode::BYTE => write!(f, "R_BYTE_{destination} -> {to}"),
|
||||||
TypeCode::CHARACTER => write!(f, "R_CHAR_{destination} -> R_CHAR_{to}"),
|
TypeCode::CHARACTER => write!(f, "R_CHAR_{destination} -> {to}"),
|
||||||
TypeCode::FLOAT => write!(f, "R_FLOAT_{destination} -> R_FLOAT_{to}"),
|
TypeCode::FLOAT => write!(f, "R_FLOAT_{destination} -> {to}"),
|
||||||
TypeCode::INTEGER => write!(f, "R_INT_{destination} -> R_INT_{to}"),
|
TypeCode::INTEGER => write!(f, "R_INT_{destination} -> {to}"),
|
||||||
TypeCode::STRING => write!(f, "R_STR_{destination} -> R_STR_{to}"),
|
TypeCode::STRING => write!(f, "R_STR_{destination} -> {to}"),
|
||||||
unsupported => write!(
|
unsupported => write!(
|
||||||
f,
|
f,
|
||||||
"Unsupported type code: {unsupported} for Point instruction"
|
"Unsupported type code: {unsupported} for Point instruction"
|
||||||
|
@ -62,7 +62,7 @@ impl Display for Return {
|
|||||||
TypeCode::STRING => write!(f, "R_STR_{return_register}"),
|
TypeCode::STRING => write!(f, "R_STR_{return_register}"),
|
||||||
TypeCode::LIST => write!(f, "R_LIST_{return_register}"),
|
TypeCode::LIST => write!(f, "R_LIST_{return_register}"),
|
||||||
TypeCode::FUNCTION => write!(f, "R_FN_{return_register}"),
|
TypeCode::FUNCTION => write!(f, "R_FN_{return_register}"),
|
||||||
unsupported => unreachable!("Unsupported return type: {:?}", unsupported),
|
unsupported => unreachable!("Unsupported return type: {}", unsupported),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
write!(f, "RETURN")
|
write!(f, "RETURN")
|
||||||
|
@ -68,7 +68,112 @@ pub const RUNNER_LOGIC_TABLE: [RunnerLogic; 23] = [
|
|||||||
r#return,
|
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) {
|
pub fn close(instruction: InstructionFields, thread: &mut Thread) {
|
||||||
let from = instruction.b_field as usize;
|
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());
|
let mut concrete_list = Vec::with_capacity(abstract_list.item_pointers.len());
|
||||||
|
|
||||||
for pointer in &abstract_list.item_pointers {
|
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 =
|
thread.return_value =
|
||||||
|
@ -122,7 +122,9 @@ impl Thread {
|
|||||||
let mut concrete_list = Vec::with_capacity(abstract_list.item_pointers.len());
|
let mut concrete_list = Vec::with_capacity(abstract_list.item_pointers.len());
|
||||||
|
|
||||||
for pointer in &abstract_list.item_pointers {
|
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)
|
ConcreteValue::List(concrete_list)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user