1
0

Continue addind type evaluation

This commit is contained in:
Jeff 2024-11-06 00:57:54 -05:00
parent 314913dbf5
commit a16f7795de
4 changed files with 63 additions and 24 deletions

View File

@ -18,7 +18,7 @@ use std::{
use colored::Colorize; use colored::Colorize;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{Instruction, Span, Type, Value}; use crate::{Instruction, Operation, Span, Type, Value};
/// In-memory representation of a Dust program or function. /// In-memory representation of a Dust program or function.
/// ///
@ -174,13 +174,43 @@ impl Chunk {
return local_type; return local_type;
} }
self.instructions.iter().find_map(|(instruction, _)| { self.instructions
if instruction.yields_value() && instruction.a() == register_index { .iter()
instruction.yielded_type(self) .enumerate()
} else { .find_map(|(index, (instruction, _))| {
None if let Operation::LoadList = instruction.operation() {
} if instruction.a() == register_index {
}) let mut length = (instruction.c() - instruction.b() + 1) as usize;
let mut item_type = Type::Any;
let distance_to_end = self.len() - index;
for (instruction, _) in self
.instructions()
.iter()
.rev()
.skip(distance_to_end)
.take(length)
{
if let Operation::Close = instruction.operation() {
length -= (instruction.c() - instruction.b()) as usize;
} else if let Type::Any = item_type {
item_type = instruction.yielded_type(self).unwrap_or(Type::Any);
}
}
return Some(Type::List {
item_type: Box::new(item_type),
length,
});
}
}
if instruction.yields_value() && instruction.a() == register_index {
instruction.yielded_type(self)
} else {
None
}
})
} }
pub fn return_type(&self) -> Option<Type> { pub fn return_type(&self) -> Option<Type> {

View File

@ -406,6 +406,8 @@ impl Instruction {
chunk.get_register_type(self.b()) chunk.get_register_type(self.b())
} }
} }
LoadConstant => chunk.get_constant_type(self.b()),
LoadList => chunk.get_register_type(self.a()),
GetLocal => chunk.get_local_type(self.b()), GetLocal => chunk.get_local_type(self.b()),
CallNative => { CallNative => {
let native_function = NativeFunction::from(self.b()); let native_function = NativeFunction::from(self.b());

View File

@ -123,12 +123,19 @@ impl Vm {
let to_register = instruction.a(); let to_register = instruction.a();
let first_register = instruction.b(); let first_register = instruction.b();
let last_register = instruction.c(); let last_register = instruction.c();
let is_empty = to_register == first_register && first_register == last_register; let is_empty = to_register == first_register && first_register == last_register;
let item_type = if is_empty { let item_type = if is_empty {
Type::Any Type::Any
} else { } else {
self.get_register(first_register, position)?.r#type() let register_range = (first_register as usize)..=(last_register as usize);
self.stack[register_range]
.iter()
.find_map(|register| match register {
Register::Value(value) => Some(value.r#type()),
_ => None,
})
.unwrap_or(Type::Any)
}; };
let value = Value::list(first_register, last_register, item_type); let value = Value::list(first_register, last_register, item_type);

View File

@ -64,21 +64,21 @@ fn add_assign_expects_mutable_variable() {
); );
} }
#[test] // #[test]
fn add_expects_integer_float_or_string() { // fn add_expects_integer_float_or_string() {
let source = "true + false"; // let source = "true + false";
assert_eq!( // assert_eq!(
parse(source), // parse(source),
Err(DustError::Parse { // Err(DustError::Parse {
error: ParseError::ExpectedIntegerFloatOrString { // error: ParseError::ExpectedIntegerFloatOrString {
found: Token::True, // found: Token::True,
position: Span(0, 3) // position: Span(0, 3)
}, // },
source // source
}) // })
); // );
} // }
#[test] #[test]
fn divide() { fn divide() {