Add operator to scopebinop, add some typechecking for binops
This commit is contained in:
parent
aec7d55e9b
commit
9f7022b4c0
@ -400,8 +400,9 @@ impl mir::Module {
|
|||||||
|
|
||||||
binops.insert(
|
binops.insert(
|
||||||
ScopeBinopKey {
|
ScopeBinopKey {
|
||||||
operators: (binop.lhs.1.clone(), binop.rhs.1.clone()),
|
params: (binop.lhs.1.clone(), binop.rhs.1.clone()),
|
||||||
commutative: mir::pass::CommutativeKind::True,
|
commutative: mir::pass::CommutativeKind::True,
|
||||||
|
operator: binop.op,
|
||||||
},
|
},
|
||||||
StackBinopDefinition {
|
StackBinopDefinition {
|
||||||
parameters: (binop.lhs.clone(), binop.rhs.clone()),
|
parameters: (binop.lhs.clone(), binop.rhs.clone()),
|
||||||
|
@ -110,13 +110,13 @@ impl TypeKind {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn binop_type<'o>(
|
pub fn binop_type(
|
||||||
lhs: &TypeKind,
|
lhs: &TypeKind,
|
||||||
rhs: &TypeKind,
|
rhs: &TypeKind,
|
||||||
binop: &ScopeBinopDef,
|
binop: &ScopeBinopDef,
|
||||||
) -> Option<(TypeKind, TypeKind, TypeKind)> {
|
) -> Option<(TypeKind, TypeKind, TypeKind)> {
|
||||||
let lhs_ty = lhs.collapse_into(&binop.operators.0);
|
let lhs_ty = lhs.collapse_into(&binop.hands.0);
|
||||||
let rhs_ty = rhs.collapse_into(&binop.operators.1);
|
let rhs_ty = rhs.collapse_into(&binop.hands.1);
|
||||||
if let (Ok(lhs_ty), Ok(rhs_ty)) = (lhs_ty, rhs_ty) {
|
if let (Ok(lhs_ty), Ok(rhs_ty)) = (lhs_ty, rhs_ty) {
|
||||||
Some((lhs_ty, rhs_ty, binop.return_ty.clone()))
|
Some((lhs_ty, rhs_ty, binop.return_ty.clone()))
|
||||||
} else {
|
} else {
|
||||||
@ -126,7 +126,7 @@ impl TypeKind {
|
|||||||
|
|
||||||
/// Reverse of binop_type, where the given hint is the known required output
|
/// Reverse of binop_type, where the given hint is the known required output
|
||||||
/// type of the binop, and the output is the hint for the lhs/rhs type.
|
/// type of the binop, and the output is the hint for the lhs/rhs type.
|
||||||
pub fn binop_hint(&self, op: &BinaryOperator) -> Option<TypeKind> {
|
pub fn simple_binop_hint(&self, op: &BinaryOperator) -> Option<TypeKind> {
|
||||||
match op {
|
match op {
|
||||||
BinaryOperator::Add
|
BinaryOperator::Add
|
||||||
| BinaryOperator::Minus
|
| BinaryOperator::Minus
|
||||||
@ -138,6 +138,22 @@ impl TypeKind {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn binop_hint(
|
||||||
|
&self,
|
||||||
|
lhs: &TypeKind,
|
||||||
|
rhs: &TypeKind,
|
||||||
|
binop: &ScopeBinopDef,
|
||||||
|
) -> Option<(TypeKind, TypeKind)> {
|
||||||
|
self.collapse_into(&binop.return_ty).ok()?;
|
||||||
|
let lhs_ty = lhs.collapse_into(&binop.hands.0);
|
||||||
|
let rhs_ty = rhs.collapse_into(&binop.hands.1);
|
||||||
|
if let (Ok(lhs_ty), Ok(rhs_ty)) = (lhs_ty, rhs_ty) {
|
||||||
|
Some((lhs_ty, rhs_ty))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn signed(&self) -> bool {
|
pub fn signed(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
TypeKind::Bool => false,
|
TypeKind::Bool => false,
|
||||||
|
@ -214,7 +214,7 @@ impl VagueLiteral {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub enum BinaryOperator {
|
pub enum BinaryOperator {
|
||||||
Add,
|
Add,
|
||||||
Minus,
|
Minus,
|
||||||
@ -226,7 +226,7 @@ pub enum BinaryOperator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Specifically the operators that LLVM likes to take in as "icmp" parameters
|
/// Specifically the operators that LLVM likes to take in as "icmp" parameters
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub enum CmpOperator {
|
pub enum CmpOperator {
|
||||||
LT,
|
LT,
|
||||||
LE,
|
LE,
|
||||||
|
@ -170,7 +170,8 @@ pub struct ScopeVariable {
|
|||||||
|
|
||||||
#[derive(Clone, Debug, Eq)]
|
#[derive(Clone, Debug, Eq)]
|
||||||
pub struct ScopeBinopKey {
|
pub struct ScopeBinopKey {
|
||||||
pub operators: (TypeKind, TypeKind),
|
pub params: (TypeKind, TypeKind),
|
||||||
|
pub operator: BinaryOperator,
|
||||||
pub commutative: CommutativeKind,
|
pub commutative: CommutativeKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,14 +184,16 @@ pub enum CommutativeKind {
|
|||||||
|
|
||||||
impl PartialEq for ScopeBinopKey {
|
impl PartialEq for ScopeBinopKey {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
if self.operator != other.operator {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if self.commutative != CommutativeKind::Any && other.commutative != CommutativeKind::Any {
|
if self.commutative != CommutativeKind::Any && other.commutative != CommutativeKind::Any {
|
||||||
if self.commutative != other.commutative {
|
if self.commutative != other.commutative {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let operators_eq = self.operators == other.operators;
|
let operators_eq = self.params == other.params;
|
||||||
let swapped_ops_eq =
|
let swapped_ops_eq = (self.params.1.clone(), self.params.0.clone()) == other.params;
|
||||||
(self.operators.1.clone(), self.operators.0.clone()) == other.operators;
|
|
||||||
if self.commutative == CommutativeKind::True || other.commutative == CommutativeKind::True {
|
if self.commutative == CommutativeKind::True || other.commutative == CommutativeKind::True {
|
||||||
operators_eq || swapped_ops_eq
|
operators_eq || swapped_ops_eq
|
||||||
} else {
|
} else {
|
||||||
@ -202,18 +205,20 @@ impl PartialEq for ScopeBinopKey {
|
|||||||
impl std::hash::Hash for ScopeBinopKey {
|
impl std::hash::Hash for ScopeBinopKey {
|
||||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||||
if self.commutative == CommutativeKind::True {
|
if self.commutative == CommutativeKind::True {
|
||||||
let mut sorted = vec![&self.operators.0, &self.operators.1];
|
let mut sorted = vec![&self.params.0, &self.params.1];
|
||||||
sorted.sort();
|
sorted.sort();
|
||||||
sorted.hash(state);
|
sorted.hash(state);
|
||||||
|
self.operator.hash(state);
|
||||||
} else {
|
} else {
|
||||||
self.operators.hash(state);
|
self.params.hash(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct ScopeBinopDef {
|
pub struct ScopeBinopDef {
|
||||||
pub operators: (TypeKind, TypeKind),
|
pub hands: (TypeKind, TypeKind),
|
||||||
|
pub operator: BinaryOperator,
|
||||||
pub commutative: bool,
|
pub commutative: bool,
|
||||||
pub return_ty: TypeKind,
|
pub return_ty: TypeKind,
|
||||||
}
|
}
|
||||||
@ -358,17 +363,22 @@ impl Module {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for binop in &self.binop_defs {
|
for binop in &self.binop_defs {
|
||||||
scope.binops.set(
|
scope
|
||||||
ScopeBinopKey {
|
.binops
|
||||||
operators: (binop.lhs.1.clone(), binop.rhs.1.clone()),
|
.set(
|
||||||
commutative: CommutativeKind::True,
|
ScopeBinopKey {
|
||||||
},
|
params: (binop.lhs.1.clone(), binop.rhs.1.clone()),
|
||||||
ScopeBinopDef {
|
commutative: CommutativeKind::True,
|
||||||
operators: (binop.lhs.1.clone(), binop.rhs.1.clone()),
|
operator: binop.op,
|
||||||
commutative: true,
|
},
|
||||||
return_ty: binop.return_type.clone(),
|
ScopeBinopDef {
|
||||||
},
|
hands: (binop.lhs.1.clone(), binop.rhs.1.clone()),
|
||||||
);
|
operator: binop.op,
|
||||||
|
commutative: true,
|
||||||
|
return_ty: binop.return_type.clone(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
for function in &self.functions {
|
for function in &self.functions {
|
||||||
|
@ -513,7 +513,7 @@ impl Expression {
|
|||||||
let lhs_res = lhs.typecheck(
|
let lhs_res = lhs.typecheck(
|
||||||
state,
|
state,
|
||||||
&typerefs,
|
&typerefs,
|
||||||
hint_t.and_then(|t| t.binop_hint(op)).as_ref(),
|
hint_t.and_then(|t| t.simple_binop_hint(op)).as_ref(),
|
||||||
);
|
);
|
||||||
let lhs_type = state.or_else(lhs_res, TypeKind::Vague(Vague::Unknown), lhs.1);
|
let lhs_type = state.or_else(lhs_res, TypeKind::Vague(Vague::Unknown), lhs.1);
|
||||||
let rhs_res = rhs.typecheck(state, &typerefs, Some(&lhs_type));
|
let rhs_res = rhs.typecheck(state, &typerefs, Some(&lhs_type));
|
||||||
|
@ -62,8 +62,9 @@ impl<'t> Pass for TypeInference<'t> {
|
|||||||
let mut seen_binops = HashSet::new();
|
let mut seen_binops = HashSet::new();
|
||||||
for binop in &module.binop_defs {
|
for binop in &module.binop_defs {
|
||||||
let binop_key = ScopeBinopKey {
|
let binop_key = ScopeBinopKey {
|
||||||
operators: (binop.lhs.1.clone(), binop.rhs.1.clone()),
|
params: (binop.lhs.1.clone(), binop.rhs.1.clone()),
|
||||||
commutative: pass::CommutativeKind::True,
|
commutative: pass::CommutativeKind::True,
|
||||||
|
operator: binop.op,
|
||||||
};
|
};
|
||||||
if seen_binops.contains(&binop_key) {
|
if seen_binops.contains(&binop_key) {
|
||||||
state.note_errors(
|
state.note_errors(
|
||||||
|
Loading…
Reference in New Issue
Block a user