Fix intrinsic binops
This commit is contained in:
parent
307137d0d9
commit
5149ef8727
@ -5,6 +5,7 @@ use std::collections::HashMap;
|
|||||||
use std::convert::Infallible;
|
use std::convert::Infallible;
|
||||||
use std::error::Error as STDError;
|
use std::error::Error as STDError;
|
||||||
|
|
||||||
|
use crate::codegen::intrinsics::form_intrinsic_binops;
|
||||||
use crate::error_raporting::ReidError;
|
use crate::error_raporting::ReidError;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -53,12 +54,7 @@ impl<TErr: STDError> State<TErr> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn or_else<U, T: Into<Metadata> + Clone + Copy>(
|
fn or_else<U, T: Into<Metadata> + Clone + Copy>(&mut self, result: Result<U, TErr>, default: U, meta: T) -> U {
|
||||||
&mut self,
|
|
||||||
result: Result<U, TErr>,
|
|
||||||
default: U,
|
|
||||||
meta: T,
|
|
||||||
) -> U {
|
|
||||||
match result {
|
match result {
|
||||||
Ok(t) => t,
|
Ok(t) => t,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
@ -71,11 +67,7 @@ impl<TErr: STDError> State<TErr> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ok<T: Into<Metadata> + Clone + Copy, U>(
|
fn ok<T: Into<Metadata> + Clone + Copy, U>(&mut self, result: Result<U, TErr>, meta: T) -> Option<U> {
|
||||||
&mut self,
|
|
||||||
result: Result<U, TErr>,
|
|
||||||
meta: T,
|
|
||||||
) -> Option<U> {
|
|
||||||
match result {
|
match result {
|
||||||
Ok(v) => Some(v),
|
Ok(v) => Some(v),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
@ -200,10 +192,10 @@ impl PartialEq for ScopeBinopKey {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let operators_eq = self.params.0.narrow_into(&other.params.0).is_ok()
|
let operators_eq =
|
||||||
&& self.params.1.narrow_into(&other.params.1).is_ok();
|
self.params.0.narrow_into(&other.params.0).is_ok() && self.params.1.narrow_into(&other.params.1).is_ok();
|
||||||
let swapped_ops_eq = self.params.0.narrow_into(&other.params.1).is_ok()
|
let swapped_ops_eq =
|
||||||
&& self.params.1.narrow_into(&other.params.0).is_ok();
|
self.params.0.narrow_into(&other.params.1).is_ok() && self.params.1.narrow_into(&other.params.0).is_ok();
|
||||||
|
|
||||||
if self.operator.is_commutative() {
|
if self.operator.is_commutative() {
|
||||||
operators_eq || swapped_ops_eq
|
operators_eq || swapped_ops_eq
|
||||||
@ -253,11 +245,7 @@ pub struct PassState<'st, 'sc, Data: Clone + Default, TError: STDError + Clone>
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'st, 'sc, Data: Clone + Default, TError: STDError + Clone> PassState<'st, 'sc, Data, TError> {
|
impl<'st, 'sc, Data: Clone + Default, TError: STDError + Clone> PassState<'st, 'sc, Data, TError> {
|
||||||
fn from(
|
fn from(state: &'st mut State<TError>, scope: &'sc mut Scope<Data>, module_id: Option<SourceModuleId>) -> Self {
|
||||||
state: &'st mut State<TError>,
|
|
||||||
scope: &'sc mut Scope<Data>,
|
|
||||||
module_id: Option<SourceModuleId>,
|
|
||||||
) -> Self {
|
|
||||||
PassState {
|
PassState {
|
||||||
state,
|
state,
|
||||||
scope,
|
scope,
|
||||||
@ -275,19 +263,11 @@ impl<'st, 'sc, Data: Clone + Default, TError: STDError + Clone> PassState<'st, '
|
|||||||
self.state.or_else(result, default, meta)
|
self.state.or_else(result, default, meta)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ok<TMeta: Into<Metadata> + Clone + Copy, U>(
|
pub fn ok<TMeta: Into<Metadata> + Clone + Copy, U>(&mut self, result: Result<U, TError>, meta: TMeta) -> Option<U> {
|
||||||
&mut self,
|
|
||||||
result: Result<U, TError>,
|
|
||||||
meta: TMeta,
|
|
||||||
) -> Option<U> {
|
|
||||||
self.state.ok(result, meta)
|
self.state.ok(result, meta)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn note_errors<TMeta: Into<Metadata> + Clone>(
|
pub fn note_errors<TMeta: Into<Metadata> + Clone>(&mut self, errors: &Vec<TError>, meta: TMeta) {
|
||||||
&mut self,
|
|
||||||
errors: &Vec<TError>,
|
|
||||||
meta: TMeta,
|
|
||||||
) {
|
|
||||||
for error in errors {
|
for error in errors {
|
||||||
self.ok::<_, Infallible>(Err(error.clone()), meta.clone().into());
|
self.ok::<_, Infallible>(Err(error.clone()), meta.clone().into());
|
||||||
}
|
}
|
||||||
@ -311,18 +291,10 @@ pub trait Pass {
|
|||||||
type Data: Clone + Default;
|
type Data: Clone + Default;
|
||||||
type TError: STDError + Clone;
|
type TError: STDError + Clone;
|
||||||
|
|
||||||
fn context(
|
fn context(&mut self, _context: &mut Context, mut _state: PassState<Self::Data, Self::TError>) -> PassResult {
|
||||||
&mut self,
|
|
||||||
_context: &mut Context,
|
|
||||||
mut _state: PassState<Self::Data, Self::TError>,
|
|
||||||
) -> PassResult {
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn module(
|
fn module(&mut self, _module: &mut Module, mut _state: PassState<Self::Data, Self::TError>) -> PassResult {
|
||||||
&mut self,
|
|
||||||
_module: &mut Module,
|
|
||||||
mut _state: PassState<Self::Data, Self::TError>,
|
|
||||||
) -> PassResult {
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn function(
|
fn function(
|
||||||
@ -332,25 +304,13 @@ pub trait Pass {
|
|||||||
) -> PassResult {
|
) -> PassResult {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn block(
|
fn block(&mut self, _block: &mut Block, mut _state: PassState<Self::Data, Self::TError>) -> PassResult {
|
||||||
&mut self,
|
|
||||||
_block: &mut Block,
|
|
||||||
mut _state: PassState<Self::Data, Self::TError>,
|
|
||||||
) -> PassResult {
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn stmt(
|
fn stmt(&mut self, _stmt: &mut Statement, mut _state: PassState<Self::Data, Self::TError>) -> PassResult {
|
||||||
&mut self,
|
|
||||||
_stmt: &mut Statement,
|
|
||||||
mut _state: PassState<Self::Data, Self::TError>,
|
|
||||||
) -> PassResult {
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn expr(
|
fn expr(&mut self, _expr: &mut Expression, mut _state: PassState<Self::Data, Self::TError>) -> PassResult {
|
||||||
&mut self,
|
|
||||||
_expr: &mut Expression,
|
|
||||||
mut _state: PassState<Self::Data, Self::TError>,
|
|
||||||
) -> PassResult {
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -360,6 +320,24 @@ impl Context {
|
|||||||
let mut state = State::new();
|
let mut state = State::new();
|
||||||
let mut scope = Scope::default();
|
let mut scope = Scope::default();
|
||||||
pass.context(self, PassState::from(&mut state, &mut scope, None))?;
|
pass.context(self, PassState::from(&mut state, &mut scope, None))?;
|
||||||
|
|
||||||
|
for intrinsic in form_intrinsic_binops() {
|
||||||
|
scope
|
||||||
|
.binops
|
||||||
|
.set(
|
||||||
|
ScopeBinopKey {
|
||||||
|
params: (intrinsic.lhs.1.clone(), intrinsic.rhs.1.clone()),
|
||||||
|
operator: intrinsic.op,
|
||||||
|
},
|
||||||
|
ScopeBinopDef {
|
||||||
|
hands: (intrinsic.lhs.1.clone(), intrinsic.rhs.1.clone()),
|
||||||
|
operator: intrinsic.op,
|
||||||
|
return_ty: intrinsic.return_type.clone(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
|
||||||
for (_, module) in &mut self.modules {
|
for (_, module) in &mut self.modules {
|
||||||
module.pass(pass, &mut state, &mut scope.inner())?;
|
module.pass(pass, &mut state, &mut scope.inner())?;
|
||||||
}
|
}
|
||||||
@ -368,12 +346,7 @@ impl Context {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Module {
|
impl Module {
|
||||||
fn pass<T: Pass>(
|
fn pass<T: Pass>(&mut self, pass: &mut T, state: &mut State<T::TError>, scope: &mut Scope<T::Data>) -> PassResult {
|
||||||
&mut self,
|
|
||||||
pass: &mut T,
|
|
||||||
state: &mut State<T::TError>,
|
|
||||||
scope: &mut Scope<T::Data>,
|
|
||||||
) -> PassResult {
|
|
||||||
for typedef in &self.typedefs {
|
for typedef in &self.typedefs {
|
||||||
scope
|
scope
|
||||||
.types
|
.types
|
||||||
|
@ -418,13 +418,13 @@ impl Expression {
|
|||||||
let rhs_type = state.or_else(rhs_res, TypeKind::Vague(Vague::Unknown), rhs.1);
|
let rhs_type = state.or_else(rhs_res, TypeKind::Vague(Vague::Unknown), rhs.1);
|
||||||
let expected_return_ty = ret_ty.resolve_ref(typerefs);
|
let expected_return_ty = ret_ty.resolve_ref(typerefs);
|
||||||
|
|
||||||
let binops = typerefs.binop_types.filter(&pass::ScopeBinopKey {
|
let binops = state.scope.binops.filter(&pass::ScopeBinopKey {
|
||||||
params: (lhs_type.clone(), rhs_type.clone()),
|
params: (lhs_type.clone(), rhs_type.clone()),
|
||||||
operator: *op,
|
operator: *op,
|
||||||
});
|
});
|
||||||
if let Some(binop) = binops
|
if let Some(binop) = binops
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|f| f.1.return_ty == expected_return_ty)
|
.filter(|f| f.1.return_ty.narrow_into(&expected_return_ty).is_ok())
|
||||||
.map(|v| (v.1.clone()))
|
.map(|v| (v.1.clone()))
|
||||||
.next()
|
.next()
|
||||||
{
|
{
|
||||||
|
@ -119,6 +119,7 @@ impl BinopDefinition {
|
|||||||
.fn_kind
|
.fn_kind
|
||||||
.infer_types(state, &scope_hints, Some(self.return_type.clone()))?;
|
.infer_types(state, &scope_hints, Some(self.return_type.clone()))?;
|
||||||
if let Some(mut ret_ty) = ret_ty {
|
if let Some(mut ret_ty) = ret_ty {
|
||||||
|
dbg!(&ret_ty, &self.return_type);
|
||||||
ret_ty.narrow(&scope_hints.from_type(&self.return_type).unwrap());
|
ret_ty.narrow(&scope_hints.from_type(&self.return_type).unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -296,7 +297,27 @@ impl Expression {
|
|||||||
let mut lhs_ref = lhs.infer_types(state, type_refs)?;
|
let mut lhs_ref = lhs.infer_types(state, type_refs)?;
|
||||||
let mut rhs_ref = rhs.infer_types(state, type_refs)?;
|
let mut rhs_ref = rhs.infer_types(state, type_refs)?;
|
||||||
|
|
||||||
let binops = type_refs.available_binops(op, &mut lhs_ref, &mut rhs_ref);
|
let binops = if let (Some(lhs_ty), Some(rhs_ty)) = (lhs_ref.resolve_deep(), rhs_ref.resolve_deep()) {
|
||||||
|
let mut applying_binops = Vec::new();
|
||||||
|
for (_, binop) in state.scope.binops.iter() {
|
||||||
|
if binop.operator != *op {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if let Some(_) = binop.narrow(&lhs_ty, &rhs_ty) {
|
||||||
|
applying_binops.push(binop.clone());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if binop.operator.is_commutative() {
|
||||||
|
if let Some(_) = binop.narrow(&lhs_ty, &rhs_ty) {
|
||||||
|
applying_binops.push(binop.clone());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
applying_binops
|
||||||
|
} else {
|
||||||
|
Vec::new()
|
||||||
|
};
|
||||||
|
|
||||||
if binops.len() > 0 {
|
if binops.len() > 0 {
|
||||||
let binop = unsafe { binops.get_unchecked(0) };
|
let binop = unsafe { binops.get_unchecked(0) };
|
||||||
@ -307,9 +328,15 @@ impl Expression {
|
|||||||
widened_rhs = widened_rhs.widen_into(&binop.hands.1);
|
widened_rhs = widened_rhs.widen_into(&binop.hands.1);
|
||||||
}
|
}
|
||||||
let binop_res = type_refs.from_binop(*op, &lhs_ref, &rhs_ref);
|
let binop_res = type_refs.from_binop(*op, &lhs_ref, &rhs_ref);
|
||||||
|
dbg!(&type_refs.types.type_refs);
|
||||||
|
dbg!(&type_refs.types.hints);
|
||||||
lhs_ref.narrow(&type_refs.from_type(&widened_lhs).unwrap());
|
lhs_ref.narrow(&type_refs.from_type(&widened_lhs).unwrap());
|
||||||
rhs_ref.narrow(&type_refs.from_type(&widened_rhs).unwrap());
|
rhs_ref.narrow(&type_refs.from_type(&widened_rhs).unwrap());
|
||||||
|
dbg!(&lhs_ref, &rhs_ref);
|
||||||
*return_ty = binop_res.as_type();
|
*return_ty = binop_res.as_type();
|
||||||
|
dbg!(&type_refs.types.hints, &type_refs.types.type_refs);
|
||||||
|
dbg!(&return_ty);
|
||||||
|
dbg!(&type_refs.from_type(&return_ty));
|
||||||
Ok(binop_res)
|
Ok(binop_res)
|
||||||
} else {
|
} else {
|
||||||
Err(ErrorKind::InvalidBinop(
|
Err(ErrorKind::InvalidBinop(
|
||||||
|
@ -283,14 +283,14 @@ impl<'outer> ScopeTypeRefs<'outer> {
|
|||||||
match &lhs {
|
match &lhs {
|
||||||
TypeKind::Vague(VagueType::TypeRef(idx)) => {
|
TypeKind::Vague(VagueType::TypeRef(idx)) => {
|
||||||
let mut lhs_ref = TypeRef(Rc::new(RefCell::new(*idx)), self);
|
let mut lhs_ref = TypeRef(Rc::new(RefCell::new(*idx)), self);
|
||||||
let narrowed = self.narrow_to_type(&mut lhs_ref, &lhs_narrow).unwrap_or(lhs_ref);
|
self.narrow_to_type(&mut lhs_ref, &lhs_narrow).unwrap_or(lhs_ref);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
match &rhs {
|
match &rhs {
|
||||||
TypeKind::Vague(VagueType::TypeRef(idx)) => {
|
TypeKind::Vague(VagueType::TypeRef(idx)) => {
|
||||||
let mut rhs_ref = TypeRef(Rc::new(RefCell::new(*idx)), self);
|
let mut rhs_ref = TypeRef(Rc::new(RefCell::new(*idx)), self);
|
||||||
let narrowed = self.narrow_to_type(&mut rhs_ref, &rhs_narrow).unwrap_or(rhs_ref);
|
self.narrow_to_type(&mut rhs_ref, &rhs_narrow).unwrap_or(rhs_ref);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@ -312,9 +312,20 @@ impl<'outer> ScopeTypeRefs<'outer> {
|
|||||||
.clone()
|
.clone()
|
||||||
.widen(self.types);
|
.widen(self.types);
|
||||||
self.narrow_to_type(&hint1, &ty)?;
|
self.narrow_to_type(&hint1, &ty)?;
|
||||||
|
let hint1_typeref = self.types.retrieve_typeref(*hint1.0.borrow()).unwrap();
|
||||||
for idx in self.types.type_refs.borrow_mut().iter_mut() {
|
for idx in self.types.type_refs.borrow_mut().iter_mut() {
|
||||||
if *idx == hint2.0 && idx != &hint1.0 {
|
match hint1_typeref {
|
||||||
*idx.borrow_mut() = *hint1.0.borrow();
|
TypeRefKind::Direct(_) => {
|
||||||
|
if *idx == hint2.0 && idx != &hint1.0 {
|
||||||
|
*idx.borrow_mut() = *hint1.0.borrow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TypeRefKind::BinOp(_, _, _) => {
|
||||||
|
// TODO may not be good ?
|
||||||
|
// if *idx == hint2.0 && idx != &hint1.0 {
|
||||||
|
// *idx.borrow_mut() = *hint1.0.borrow();
|
||||||
|
// }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(TypeRef(hint1.0.clone(), self))
|
Some(TypeRef(hint1.0.clone(), self))
|
||||||
|
Loading…
Reference in New Issue
Block a user