λ Support functions! #5

Open
acw wants to merge 59 commits from awick/functions into develop
Showing only changes of commit d54680a8fe - Show all commits

View File

@@ -330,7 +330,7 @@ pub fn solve_constraints(
loc, from_type, to_type, loc, from_type, to_type,
)); ));
} }
tracing::trace!(form = %from_type, to = %to_type, "changed something because we can determine if we can do the cast"); tracing::trace!(form = %from_type, to = %to_type, "we can determine if we can do the cast");
changed_something = true; changed_something = true;
} }
@@ -352,7 +352,7 @@ pub fn solve_constraints(
TypeOrVar::Function(args2, ret2), TypeOrVar::Function(args2, ret2),
)); ));
} }
tracing::trace!("changed something because we transferred CanCastTo to equivalence checks for function types"); tracing::trace!("we transferred CanCastTo to equivalence checks for function types");
changed_something = true; changed_something = true;
} }
@@ -361,7 +361,7 @@ pub fn solve_constraints(
ft @ TypeOrVar::Function(_, _), ft @ TypeOrVar::Function(_, _),
pt @ TypeOrVar::Primitive(_), pt @ TypeOrVar::Primitive(_),
) => { ) => {
tracing::trace!(function_type = %ft, primitive_type = %pt, "changed something because we can't cast a function type to a primitive type"); tracing::trace!(function_type = %ft, primitive_type = %pt, "we can't cast a function type to a primitive type");
errors.push(TypeInferenceError::CannotCastFromFunctionType(loc, pt)); errors.push(TypeInferenceError::CannotCastFromFunctionType(loc, pt));
changed_something = true; changed_something = true;
} }
@@ -371,14 +371,14 @@ pub fn solve_constraints(
pt @ TypeOrVar::Primitive(_), pt @ TypeOrVar::Primitive(_),
ft @ TypeOrVar::Function(_, _), ft @ TypeOrVar::Function(_, _),
) => { ) => {
tracing::trace!(function_type = %ft, primitive_type = %pt, "changed something because we can't cast a primitive type to a function type"); tracing::trace!(function_type = %ft, primitive_type = %pt, "we can't cast a primitive type to a function type");
errors.push(TypeInferenceError::CannotCastToFunctionType(loc, pt)); errors.push(TypeInferenceError::CannotCastToFunctionType(loc, pt));
changed_something = true; changed_something = true;
} }
// if we're testing if an actual primitive type is numeric, that's pretty easy // if we're testing if an actual primitive type is numeric, that's pretty easy
Constraint::ConstantNumericType(loc, TypeOrVar::Primitive(pt)) => { Constraint::ConstantNumericType(loc, TypeOrVar::Primitive(pt)) => {
tracing::trace!(primitive_type = %pt, "changed something because its easy to tell if a constant number can be a primitive type"); tracing::trace!(primitive_type = %pt, "its easy to tell if a constant number can be a primitive type");
if pt.max_value().is_none() { if pt.max_value().is_none() {
errors.push(TypeInferenceError::NotANumber(loc, pt)) errors.push(TypeInferenceError::NotANumber(loc, pt))
} }
@@ -387,7 +387,7 @@ pub fn solve_constraints(
// if we're testing if a function type is numeric, then throw a useful warning // if we're testing if a function type is numeric, then throw a useful warning
Constraint::ConstantNumericType(loc, t @ TypeOrVar::Function(_, _)) => { Constraint::ConstantNumericType(loc, t @ TypeOrVar::Function(_, _)) => {
tracing::trace!(function_type = %t, "changed something because functions can't be constant numbers"); tracing::trace!(function_type = %t, "functions can't be constant numbers");
errors.push(TypeInferenceError::CannotMakeNumberAFunction(loc, t, None)); errors.push(TypeInferenceError::CannotMakeNumberAFunction(loc, t, None));
changed_something = true; changed_something = true;
} }
@@ -404,12 +404,12 @@ pub fn solve_constraints(
Some(_) => {} Some(_) => {}
} }
changed_something = true; changed_something = true;
tracing::trace!(primitive_type = %ctype, value = val, "changed something because we can test for a value fitting in a primitive type"); tracing::trace!(primitive_type = %ctype, value = val, "we can test for a value fitting in a primitive type");
} }
// if we're testing if a function type can fit into a numeric type, that's a problem // if we're testing if a function type can fit into a numeric type, that's a problem
Constraint::FitsInNumType(loc, t @ TypeOrVar::Function(_, _), val) => { Constraint::FitsInNumType(loc, t @ TypeOrVar::Function(_, _), val) => {
tracing::trace!(function_type = %t, "changed something because values don't fit in function types"); tracing::trace!(function_type = %t, "values don't fit in function types");
errors.push(TypeInferenceError::CannotMakeNumberAFunction( errors.push(TypeInferenceError::CannotMakeNumberAFunction(
loc, loc,
t, t,
@@ -421,13 +421,13 @@ pub fn solve_constraints(
// if we want to know if a type is something, and it is something, then we're done // if we want to know if a type is something, and it is something, then we're done
Constraint::IsSomething(_, t @ TypeOrVar::Function(_, _)) Constraint::IsSomething(_, t @ TypeOrVar::Function(_, _))
| Constraint::IsSomething(_, t @ TypeOrVar::Primitive(_)) => { | Constraint::IsSomething(_, t @ TypeOrVar::Primitive(_)) => {
tracing::trace!(tested_type = %t, "changed something because type is definitely something"); tracing::trace!(tested_type = %t, "type is definitely something");
changed_something = true; changed_something = true;
} }
// if we want to know if something is signed, we can check its primitive type // if we want to know if something is signed, we can check its primitive type
Constraint::IsSigned(loc, TypeOrVar::Primitive(pt)) => { Constraint::IsSigned(loc, TypeOrVar::Primitive(pt)) => {
tracing::trace!(primitive_type = %pt, "changed something because we can check if a primitive is signed"); tracing::trace!(primitive_type = %pt, "we can check if a primitive is signed");
if !pt.valid_operators().contains(&("-", 1)) { if !pt.valid_operators().contains(&("-", 1)) {
errors.push(TypeInferenceError::IsNotSigned(loc, pt)); errors.push(TypeInferenceError::IsNotSigned(loc, pt));
} }
@@ -436,14 +436,14 @@ pub fn solve_constraints(
// again with the functions and the numbers // again with the functions and the numbers
Constraint::IsSigned(loc, t @ TypeOrVar::Function(_, _)) => { Constraint::IsSigned(loc, t @ TypeOrVar::Function(_, _)) => {
tracing::trace!(function_type = %t, "changed something because functions are not signed"); tracing::trace!(function_type = %t, "functions are not signed");
errors.push(TypeInferenceError::CannotCastFromFunctionType(loc, t)); errors.push(TypeInferenceError::CannotCastFromFunctionType(loc, t));
changed_something = true; changed_something = true;
} }
// if we're testing if an actual primitive type is numeric, that's pretty easy // if we're testing if an actual primitive type is numeric, that's pretty easy
Constraint::NumericType(loc, TypeOrVar::Primitive(pt)) => { Constraint::NumericType(loc, TypeOrVar::Primitive(pt)) => {
tracing::trace!(primitive_type = %pt, "changed something because its easy to tell if a primitive type is numeric"); tracing::trace!(primitive_type = %pt, "its easy to tell if a primitive type is numeric");
if pt.max_value().is_none() { if pt.max_value().is_none() {
errors.push(TypeInferenceError::NotANumber(loc, pt)) errors.push(TypeInferenceError::NotANumber(loc, pt))
} }
@@ -452,20 +452,20 @@ pub fn solve_constraints(
// if we're testing if a function type is numeric, then throw a useful warning // if we're testing if a function type is numeric, then throw a useful warning
Constraint::NumericType(loc, t @ TypeOrVar::Function(_, _)) => { Constraint::NumericType(loc, t @ TypeOrVar::Function(_, _)) => {
tracing::trace!(function_type = %t, "changed something because function types aren't numeric"); tracing::trace!(function_type = %t, "function types aren't numeric");
errors.push(TypeInferenceError::CannotMakeNumberAFunction(loc, t, None)); errors.push(TypeInferenceError::CannotMakeNumberAFunction(loc, t, None));
changed_something = true; changed_something = true;
} }
// all of our primitive types are printable // all of our primitive types are printable
Constraint::Printable(_, TypeOrVar::Primitive(pt)) => { Constraint::Printable(_, TypeOrVar::Primitive(pt)) => {
tracing::trace!(primitive_type = %pt, "changed something because primitive types are printable"); tracing::trace!(primitive_type = %pt, "primitive types are printable");
changed_something = true; changed_something = true;
} }
// function types are definitely not printable // function types are definitely not printable
Constraint::Printable(loc, ft @ TypeOrVar::Function(_, _)) => { Constraint::Printable(loc, ft @ TypeOrVar::Function(_, _)) => {
tracing::trace!(function_type = %ft, "changed something because function types are not printable"); tracing::trace!(function_type = %ft, "function types are not printable");
errors.push(TypeInferenceError::FunctionsAreNotPrintable(loc)); errors.push(TypeInferenceError::FunctionsAreNotPrintable(loc));
changed_something = true; changed_something = true;
} }
@@ -486,7 +486,7 @@ pub fn solve_constraints(
new_constraints.push(Constraint::Equivalent(loc.clone(), left, ret)); new_constraints.push(Constraint::Equivalent(loc.clone(), left, ret));
changed_something = true; changed_something = true;
all_constraints_solved = false; all_constraints_solved = false;
tracing::trace!(primitive = %prim, "changed something because we expanded out a binary primitive operation"); tracing::trace!(primitive = %prim, "we expanded out a binary primitive operation");
} }
Primitive::Minus if args.len() == 1 => { Primitive::Minus if args.len() == 1 => {
@@ -496,7 +496,7 @@ pub fn solve_constraints(
new_constraints.push(Constraint::Equivalent(loc, value, ret)); new_constraints.push(Constraint::Equivalent(loc, value, ret));
changed_something = true; changed_something = true;
all_constraints_solved = false; all_constraints_solved = false;
tracing::trace!(primitive = %prim, "changed something because we expanded out a unary primitive operation"); tracing::trace!(primitive = %prim, "we expanded out a unary primitive operation");
} }
Primitive::Plus | Primitive::Times | Primitive::Divide => { Primitive::Plus | Primitive::Times | Primitive::Divide => {
@@ -508,7 +508,7 @@ pub fn solve_constraints(
args.len(), args.len(),
)); ));
changed_something = true; changed_something = true;
tracing::trace!(primitive = %prim, provided_arity = args.len(), "changed something because binary primitive operation arity is wrong"); tracing::trace!(primitive = %prim, provided_arity = args.len(), "binary primitive operation arity is wrong");
} }
Primitive::Minus => { Primitive::Minus => {
@@ -520,7 +520,7 @@ pub fn solve_constraints(
args.len(), args.len(),
)); ));
changed_something = true; changed_something = true;
tracing::trace!(primitive = %prim, provided_arity = args.len(), "changed something because unary primitive operation arity is wrong"); tracing::trace!(primitive = %prim, provided_arity = args.len(), "unary primitive operation arity is wrong");
} }
}, },
@@ -538,7 +538,7 @@ pub fn solve_constraints(
)); ));
} }
changed_something = true; changed_something = true;
tracing::trace!(primitive_type1 = %pt1, primitive_type2 = %pt2, "changed something because we checked for primitive type equivalence"); tracing::trace!(primitive_type1 = %pt1, primitive_type2 = %pt2, "we checked for primitive type equivalence");
} }
Constraint::Equivalent( Constraint::Equivalent(
@@ -551,7 +551,7 @@ pub fn solve_constraints(
ft @ TypeOrVar::Function(_, _), ft @ TypeOrVar::Function(_, _),
pt @ TypeOrVar::Primitive(_), pt @ TypeOrVar::Primitive(_),
) => { ) => {
tracing::trace!(primitive_type = %pt, function_type = %ft, "changed something because function and primitive types cannot be equivalent"); tracing::trace!(primitive_type = %pt, function_type = %ft, "function and primitive types cannot be equivalent");
errors.push(TypeInferenceError::NotEquivalent(loc, pt, ft)); errors.push(TypeInferenceError::NotEquivalent(loc, pt, ft));
changed_something = true; changed_something = true;
} }
@@ -561,7 +561,7 @@ pub fn solve_constraints(
TypeOrVar::Variable(_, name1), TypeOrVar::Variable(_, name1),
TypeOrVar::Variable(_, name2), TypeOrVar::Variable(_, name2),
) if name1 == name2 => { ) if name1 == name2 => {
tracing::trace!(name = %name1, "changed something because variable is equivalent to itself"); tracing::trace!(name = %name1, "variable is equivalent to itself");
changed_something = true; changed_something = true;
} }
@@ -583,7 +583,7 @@ pub fn solve_constraints(
} }
changed_something = true; changed_something = true;
tracing::trace!("changed something because we checked/rewrote if function types are equivalent"); tracing::trace!("we checked/rewrote if function types are equivalent");
} }
Constraint::Equivalent(_, TypeOrVar::Variable(_, ref name), ref rhs) => { Constraint::Equivalent(_, TypeOrVar::Variable(_, ref name), ref rhs) => {
@@ -591,13 +591,13 @@ pub fn solve_constraints(
changed_something |= replace_variable(&mut new_constraints, name, rhs); changed_something |= replace_variable(&mut new_constraints, name, rhs);
all_constraints_solved &= rhs.is_resolved(); all_constraints_solved &= rhs.is_resolved();
if changed_something { if changed_something {
tracing::trace!(%name, new_type = %rhs, "changed something because we were able to rewrite name somewhere"); tracing::trace!(%name, new_type = %rhs, "we were able to rewrite name somewhere");
} }
new_constraints.push(constraint); new_constraints.push(constraint);
} }
Constraint::Equivalent(loc, lhs, rhs @ TypeOrVar::Variable(_, _)) => { Constraint::Equivalent(loc, lhs, rhs @ TypeOrVar::Variable(_, _)) => {
tracing::trace!(new_left = %rhs, new_right = %lhs, "changed something because we flipped the order on an equivalence"); tracing::trace!(new_left = %rhs, new_right = %lhs, "we flipped the order on an equivalence");
new_constraints.push(Constraint::Equivalent(loc, rhs, lhs)); new_constraints.push(Constraint::Equivalent(loc, rhs, lhs));
changed_something = true; changed_something = true;
all_constraints_solved = false; all_constraints_solved = false;