Skip to content

Commit

Permalink
Merge pull request #199 from mrodz/197-bug-unpacking-array-fails
Browse files Browse the repository at this point in the history
197 bug unpacking array fails
  • Loading branch information
mrodz authored Jun 2, 2024
2 parents 1aba9d7 + b5e47ec commit 30bf06a
Show file tree
Hide file tree
Showing 11 changed files with 501 additions and 191 deletions.
295 changes: 128 additions & 167 deletions Cargo.lock

Large diffs are not rendered by default.

14 changes: 11 additions & 3 deletions bytecode/src/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -942,7 +942,11 @@ pub mod implementations {
bail!("`unwrap` requires a primitive at the top of the local operating stack");
};

if let Primitive::Optional(optional) = primitive {
if let Primitive::Optional(optional) = primitive
.move_out_of_heap_primitive_borrow()
.context("could not move out of heap primitive")?
.as_ref()
{
if let Some(new_primitive) = optional {
*primitive = *new_primitive.clone();
} else {
Expand All @@ -959,7 +963,7 @@ pub mod implementations {

#[inline(always)]
pub(crate) fn jmp_not_nil(ctx: &mut Ctx, args: &[String]) -> Result<()> {
let Some(primitive) = ctx.get_last_op_item_mut() else {
let Some(primitive) = ctx.get_last_op_item() else {
bail!("`jmp_not_nil` requires a primitive at the top of the local operating stack");
};

Expand All @@ -971,7 +975,11 @@ pub mod implementations {
.parse::<isize>()
.context("jmp_not_nil needs lines_to_jump: isize")?;

if let Primitive::Optional(None) = primitive {
if let Primitive::Optional(None) = primitive
.move_out_of_heap_primitive_borrow()
.context("could not move out of heap primitive")?
.as_ref()
{
ctx.pop();
return Ok(());
}
Expand Down
8 changes: 6 additions & 2 deletions compiler/src/ast/assignment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,12 @@ impl Assignment {

impl Dependencies for Assignment {
fn supplies(&self) -> Vec<Dependency> {
if self.idents.len() == 1 && !self.flags().contains(AssignmentFlag::modify()) {
return vec![Dependency::new(Cow::Borrowed(&self.idents[0]))];
if !self.flags().contains(AssignmentFlag::modify()) {
return self
.idents
.iter()
.map(|ident| Dependency::new(Cow::Borrowed(ident)))
.collect();
}

// We are not introducing a new variable, just pointing to a callback variable.
Expand Down
13 changes: 10 additions & 3 deletions compiler/src/ast/class/member_function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,20 @@ use crate::{
BytecodePathStr, VecErr,
};

use super::ClassType;

#[derive(Debug)]
pub(crate) struct MemberFunction {
ident: Ident,
parameters: Rc<FunctionParameters>,
body: Block,
path_str: Arc<PathBuf>,
class_name: Arc<String>,
class_type: ClassType,
}

impl MemberFunction {
pub fn symbolic_id(&self) -> String {
format!("{}::{}", self.class_name, self.ident().name())
format!("{}::{}", self.class_type.name(), self.ident().name())
}
}

Expand Down Expand Up @@ -118,6 +120,11 @@ impl Dependencies for MemberFunction {

fn supplies(&self) -> Vec<crate::ast::Dependency> {
self.parameters.supplies()
// params.push(Dependency::new(Cow::Owned(Ident::new(
// "self".to_owned(),
// Some(Cow::Owned(TypeLayout::Class(self.class_type.clone()))),
// false,
// ))));
}
}

Expand Down Expand Up @@ -162,7 +169,7 @@ impl Parser {
parameters,
path_str: input.user_data().bytecode_path(),
body,
class_name: class_type.arced_name(),
class_type,
})
}
}
48 changes: 36 additions & 12 deletions compiler/src/ast/math_expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,11 +154,12 @@ pub(crate) enum CallableContents {
pub(crate) trait UnwrapSpanDisplayable: Debug + Display {}
impl<T> UnwrapSpanDisplayable for T where T: Debug + Display {}

#[derive(Debug)]
#[derive(Debug, Clone)]
pub enum ReferenceToSelf {
Class(ClassType),
Function,
Invalid,
InvalidClosureCapture,
}

#[derive(Debug)]
Expand Down Expand Up @@ -261,10 +262,10 @@ impl Expr {
Ok(return_type.clone().into_owned())
}
Expr::ReferenceToSelf(is_valid) => {
if let ReferenceToSelf::Class(class_type) = &*is_valid.borrow() {
Ok(TypeLayout::ClassSelf(Some(class_type.clone())))
} else {
bail!("this reference to `self` is not valid here")
match &*is_valid.borrow() {
ReferenceToSelf::Class(class_type) => Ok(TypeLayout::ClassSelf(Some(class_type.clone()))),
ReferenceToSelf::InvalidClosureCapture => bail!("This reference to `self` refers to the closure, and not the class. Copy the fields you need into separate variables that *can* be captured if this is desired behavior"),
_ => bail!("This reference to `self` is not valid here"),
}
}
Expr::ReferenceToConstructor(class_type) => {
Expand Down Expand Up @@ -444,8 +445,27 @@ impl Dependencies for Expr {
lhs_deps.append(&mut index.net_dependencies());
lhs_deps
}
E::DotLookup { lhs, .. } => lhs.net_dependencies(),
E::ReferenceToSelf { .. } => vec![],
E::DotLookup { lhs, .. } => {
let x = lhs.net_dependencies();
x
}
E::ReferenceToSelf(..) => vec![],
#[cfg(not)]
E::ReferenceToSelf(reference_to_self) => {
let reference_to_self = match reference_to_self.borrow().clone() {
ReferenceToSelf::Class(class) => TypeLayout::Class(class.clone()),
_ => {
log::warn!("Invalid reference to self");
return vec![];
}
};
let self_dependency = Dependency::new(Cow::Owned(Ident::new(
"self".to_owned(),
Some(Cow::Owned(reference_to_self)),
false,
)));
vec![self_dependency]
}
E::ReferenceToConstructor(..) => vec![],
E::Nil => vec![],
E::UnaryUnwrap { value, .. } => value.net_dependencies(),
Expand Down Expand Up @@ -672,7 +692,11 @@ fn parse_expr(
match raw_string {
"self" => {
let self_reference = if let Some(c) = user_data.get_type_of_executing_class() {
ReferenceToSelf::Class(c.to_owned())
if user_data.is_function_a_class_method() {
ReferenceToSelf::Class(c.to_owned())
} else {
ReferenceToSelf::InvalidClosureCapture
}
} else {
ReferenceToSelf::Invalid
};
Expand Down Expand Up @@ -877,7 +901,7 @@ fn parse_expr(
_ => ()
}

let lhs_ty = lhs.for_type(&TypecheckFlags::use_class(user_data.get_type_of_executing_class())).details(l_span.as_ref().unwrap().as_span(), &user_data.get_source_file_name(), "bad expression 1").to_err_vec()?;
let lhs_ty = lhs.for_type(&TypecheckFlags::use_class(user_data.get_type_of_executing_class())).details(l_span.as_ref().unwrap().as_span(), &user_data.get_source_file_name(), "bad expression (E1)").to_err_vec()?;

let Some(function_type) = lhs_ty.is_callable() else {
return Err(vec![new_err(l_span.unwrap().as_span(), &user_data.get_source_file_name(), format!("`{lhs_ty}` is not callable"))]);
Expand All @@ -894,7 +918,7 @@ fn parse_expr(

let lhs_span = lhs_span.unwrap().as_span();

let lhs_ty = lhs_expr.for_type(&TypecheckFlags::use_class(user_data.get_type_of_executing_class())).details(lhs_span, &user_data.get_source_file_name(), "bad expression 2").to_err_vec()?;
let lhs_ty = lhs_expr.for_type(&TypecheckFlags::use_class(user_data.get_type_of_executing_class())).details(lhs_span, &user_data.get_source_file_name(), "bad expression (E2)").to_err_vec()?;

let index: Node = Node::new_with_user_data(op.clone(), Rc::clone(&user_data));
let index: Index = Parser::list_index(index, lhs_ty)?;
Expand All @@ -905,7 +929,7 @@ fn parse_expr(
let (lhs, l_span) = lhs?;
let l_span = l_span.unwrap().as_span();

let lhs_ty = lhs.for_type(&TypecheckFlags::use_class(user_data.get_type_of_executing_class())).details(l_span, &user_data.get_source_file_name(), "bad expression 3").to_err_vec()?;
let lhs_ty = lhs.for_type(&TypecheckFlags::use_class(user_data.get_type_of_executing_class())).details(l_span, &user_data.get_source_file_name(), "bad expression (E3)").to_err_vec()?;
let lhs_ty = lhs_ty.assume_type_of_self(&user_data);

let index: Node = Node::new_with_user_data(op.clone(), Rc::clone(&user_data));
Expand Down Expand Up @@ -970,7 +994,7 @@ fn parse_expr(
.details(
span.unwrap().as_span(),
&user_data.get_source_file_name(),
"bad expression 4",
"bad expression (E4)",
)
.to_err_vec()
})
Expand Down
6 changes: 4 additions & 2 deletions compiler/src/ast/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ impl Value {

impl Dependencies for Value {
fn dependencies(&self) -> Vec<Dependency> {
match self {
let x = match self {
Self::Function(function) => function.net_dependencies(),
Self::Ident(name) => name.net_dependencies(),
Self::Number(number) => number.net_dependencies(),
Expand All @@ -204,7 +204,9 @@ impl Dependencies for Value {
Self::Boolean(boolean) => boolean.net_dependencies(),
Self::List(list) => list.net_dependencies(),
Self::Map(map) => map.net_dependencies(),
}
};

x
}
}

Expand Down
19 changes: 17 additions & 2 deletions compiler/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -379,9 +379,24 @@ impl AssocFileData {
let mut iter = self.scopes.iter();

let this_frame = iter.next().unwrap();
let parent_scope = iter.next().unwrap();

this_frame.is_class() || parent_scope.is_class()
if this_frame.is_class() {
log::debug!("Called `is_function_a_class_method` on a class type");
return true;
}

let mut found_function = false;

for scope in self.scopes.iter() {
if found_function {
return scope.is_class();
}
if scope.is_function() {
found_function = true;
}
}

false
}

pub fn get_dependency_flags_from_name(&self, dependency: &str) -> Option<(Ref<Ident>, bool)> {
Expand Down
Loading

0 comments on commit 30bf06a

Please sign in to comment.