Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ranged Integers #66

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 31 additions & 5 deletions src/alloc.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{
cmp::Ordering,
fmt::{Debug, Formatter, Result},
fmt::{Debug, Formatter},
hash::{Hash, Hasher},
iter::Enumerate,
marker::PhantomData,
Expand Down Expand Up @@ -40,7 +40,7 @@ pub trait UUIDMarker {
}

impl<IndexMarker: UUIDMarker> Debug for UUID<IndexMarker> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
f.write_str(IndexMarker::DISPLAY_NAME)?;
self.0.fmt(f)
}
Expand Down Expand Up @@ -105,7 +105,7 @@ impl<IndexMarker> UUIDAllocator<IndexMarker> {
}

impl<IndexMarker: UUIDMarker> std::fmt::Debug for UUIDAllocator<IndexMarker> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
f.debug_struct("UUIDAllocator")
.field("count: ", &self.cur.0)
.finish()
Expand Down Expand Up @@ -151,6 +151,19 @@ impl<IndexMarker> UUIDRange<IndexMarker> {
_ph: PhantomData,
}
}
pub fn try_map<OT, ErrT>(
&self,
mut f: impl FnMut(UUID<IndexMarker>) -> Result<OT, ErrT>,
) -> Result<FlatAlloc<OT, IndexMarker>, ErrT> {
let mut data = Vec::with_capacity(self.len());
for id in self.iter() {
data.push(f(id)?);
}
Ok(FlatAlloc {
data,
_ph: PhantomData,
})
}
pub fn len(&self) -> usize {
self.1 .0 - self.0 .0
}
Expand All @@ -163,7 +176,7 @@ impl<IndexMarker> UUIDRange<IndexMarker> {
}

impl<IndexMarker: UUIDMarker> Debug for UUIDRange<IndexMarker> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
f.write_str(IndexMarker::DISPLAY_NAME)?;
self.0.fmt(f)?;
f.write_str("..")?;
Expand Down Expand Up @@ -571,6 +584,19 @@ impl<T, IndexMarker> FlatAlloc<T, IndexMarker> {
_ph: PhantomData,
}
}
pub fn try_map<OT, ErrT>(
&self,
mut f: impl FnMut((UUID<IndexMarker>, &T)) -> Result<OT, ErrT>,
) -> Result<FlatAlloc<OT, IndexMarker>, ErrT> {
let mut data = Vec::with_capacity(self.len());
for id_v in self {
data.push(f(id_v)?);
}
Ok(FlatAlloc {
data,
_ph: PhantomData,
})
}
pub fn find(
&self,
mut predicate: impl FnMut(UUID<IndexMarker>, &T) -> bool,
Expand Down Expand Up @@ -638,7 +664,7 @@ impl<T, IndexMarker> IndexMut<UUID<IndexMarker>> for FlatAlloc<T, IndexMarker> {
}

impl<T: Debug, IndexMarker> Debug for FlatAlloc<T, IndexMarker> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
self.data.fmt(f)
}
}
Expand Down
183 changes: 143 additions & 40 deletions src/instantiation/concrete_typecheck.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
use std::ops::Deref;

use crate::alloc::{zip_eq, zip_eq3};
use sus_proc_macro::get_builtin_type;

use crate::alloc::{zip_eq, zip_eq3, UUID};
use crate::errors::ErrorInfoObject;
use crate::flattening::{DeclarationKind, ExpressionSource, WireReferenceRoot, WrittenType};
use crate::linker::LinkInfo;
use crate::typing::concrete_type::ConcreteGlobalReference;
use crate::typing::template::TemplateArgKind;
use crate::typing::{
concrete_type::{ConcreteType, BOOL_CONCRETE_TYPE, INT_CONCRETE_TYPE},
concrete_type::{ConcreteType, BOOL_CONCRETE_TYPE},
type_inference::{
DelayedConstraint, DelayedConstraintStatus, DelayedConstraintsList, FailedUnification,
},
Expand Down Expand Up @@ -52,7 +54,7 @@ impl InstantiationContext<'_, '_> {
)))
}

fn typecheck_all_wires(&self) {
fn typecheck_all_wires(&self, delayed_constraints: &mut DelayedConstraintsList<Self>) {
for this_wire_id in self.wires.id_range() {
let this_wire = &self.wires[this_wire_id];
let span = self.md.get_instruction_span(this_wire.original_instruction);
Expand Down Expand Up @@ -80,13 +82,17 @@ impl InstantiationContext<'_, '_> {
// TODO overloading
let (input_typ, output_typ) = match op {
UnaryOperator::Not => (BOOL_CONCRETE_TYPE, BOOL_CONCRETE_TYPE),
UnaryOperator::Negate => (INT_CONCRETE_TYPE, INT_CONCRETE_TYPE),
UnaryOperator::Negate => (
self.type_substitutor.new_int_type(),
self.type_substitutor.new_int_type(),
),
UnaryOperator::And | UnaryOperator::Or | UnaryOperator::Xor => {
(self.make_array_of(BOOL_CONCRETE_TYPE), BOOL_CONCRETE_TYPE)
}
UnaryOperator::Sum | UnaryOperator::Product => {
(self.make_array_of(INT_CONCRETE_TYPE), INT_CONCRETE_TYPE)
}
UnaryOperator::Sum | UnaryOperator::Product => (
self.make_array_of(self.type_substitutor.new_int_type()),
self.type_substitutor.new_int_type(),
),
};

self.type_substitutor.unify_report_error(
Expand All @@ -104,6 +110,7 @@ impl InstantiationContext<'_, '_> {
}
&RealWireDataSource::BinaryOp { op, left, right } => {
// TODO overloading
// Typecheck generic INT
let ((in_left, in_right), out) = match op {
BinaryOperator::And => {
((BOOL_CONCRETE_TYPE, BOOL_CONCRETE_TYPE), BOOL_CONCRETE_TYPE)
Expand All @@ -114,39 +121,62 @@ impl InstantiationContext<'_, '_> {
BinaryOperator::Xor => {
((BOOL_CONCRETE_TYPE, BOOL_CONCRETE_TYPE), BOOL_CONCRETE_TYPE)
}
BinaryOperator::Add => {
((INT_CONCRETE_TYPE, INT_CONCRETE_TYPE), INT_CONCRETE_TYPE)
}
BinaryOperator::Subtract => {
((INT_CONCRETE_TYPE, INT_CONCRETE_TYPE), INT_CONCRETE_TYPE)
}
BinaryOperator::Multiply => {
((INT_CONCRETE_TYPE, INT_CONCRETE_TYPE), INT_CONCRETE_TYPE)
}
BinaryOperator::Divide => {
((INT_CONCRETE_TYPE, INT_CONCRETE_TYPE), INT_CONCRETE_TYPE)
}
BinaryOperator::Modulo => {
((INT_CONCRETE_TYPE, INT_CONCRETE_TYPE), INT_CONCRETE_TYPE)
}
BinaryOperator::Equals => {
((INT_CONCRETE_TYPE, INT_CONCRETE_TYPE), BOOL_CONCRETE_TYPE)
}
BinaryOperator::NotEquals => {
((INT_CONCRETE_TYPE, INT_CONCRETE_TYPE), BOOL_CONCRETE_TYPE)
}
BinaryOperator::GreaterEq => {
((INT_CONCRETE_TYPE, INT_CONCRETE_TYPE), BOOL_CONCRETE_TYPE)
}
BinaryOperator::Greater => {
((INT_CONCRETE_TYPE, INT_CONCRETE_TYPE), BOOL_CONCRETE_TYPE)
}
BinaryOperator::LesserEq => {
((INT_CONCRETE_TYPE, INT_CONCRETE_TYPE), BOOL_CONCRETE_TYPE)
}
BinaryOperator::Lesser => {
((INT_CONCRETE_TYPE, INT_CONCRETE_TYPE), BOOL_CONCRETE_TYPE)
BinaryOperator::Add
| BinaryOperator::Subtract
| BinaryOperator::Multiply
| BinaryOperator::Divide
| BinaryOperator::Modulo => {
delayed_constraints.push(BinaryOpTypecheckConstraint {
op,
left,
right,
out: this_wire_id,
span,
});
continue;
}
BinaryOperator::Equals => (
(
self.type_substitutor.new_int_type(),
self.type_substitutor.new_int_type(),
),
BOOL_CONCRETE_TYPE,
),
BinaryOperator::NotEquals => (
(
self.type_substitutor.new_int_type(),
self.type_substitutor.new_int_type(),
),
BOOL_CONCRETE_TYPE,
),
BinaryOperator::GreaterEq => (
(
self.type_substitutor.new_int_type(),
self.type_substitutor.new_int_type(),
),
BOOL_CONCRETE_TYPE,
),
BinaryOperator::Greater => (
(
self.type_substitutor.new_int_type(),
self.type_substitutor.new_int_type(),
),
BOOL_CONCRETE_TYPE,
),
BinaryOperator::LesserEq => (
(
self.type_substitutor.new_int_type(),
self.type_substitutor.new_int_type(),
),
BOOL_CONCRETE_TYPE,
),
BinaryOperator::Lesser => (
(
self.type_substitutor.new_int_type(),
self.type_substitutor.new_int_type(),
),
BOOL_CONCRETE_TYPE,
),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder, it's not something that should concern us too badly, but maybe the boolean comparison ops should unify(left, right). Maybe, maybe not.

};
self.type_substitutor.unify_report_error(
&self.wires[this_wire_id].typ,
Expand Down Expand Up @@ -249,7 +279,7 @@ impl InstantiationContext<'_, '_> {
delayed_constraints.push(SubmoduleTypecheckConstraint { sm_id });
}

self.typecheck_all_wires();
self.typecheck_all_wires(&mut delayed_constraints);

delayed_constraints.resolve_delayed_constraints(self);

Expand Down Expand Up @@ -500,3 +530,76 @@ impl DelayedConstraint<InstantiationContext<'_, '_>> for SubmoduleTypecheckConst
.error(submod_instr.get_most_relevant_span(), message);
}
}

#[derive(Debug)]
struct BinaryOpTypecheckConstraint {
op: BinaryOperator,
left: UUID<WireIDMarker>,
right: UUID<WireIDMarker>,
out: UUID<WireIDMarker>,
span: Span,
}

impl DelayedConstraint<InstantiationContext<'_, '_>> for BinaryOpTypecheckConstraint {
fn try_apply(&mut self, context: &mut InstantiationContext<'_, '_>) -> DelayedConstraintStatus {
if let (Some(left_complete_type), Some(right_complete_type)) = (
context.wires[self.left]
.typ
.try_fully_substitute(&context.type_substitutor),
context.wires[self.right]
.typ
.try_fully_substitute(&context.type_substitutor),
) {
#[rustfmt::skip]
let left_size = left_complete_type.unwrap_named().template_args
[UUID::from_hidden_value(0)]
.unwrap_value()
.unwrap_integer();
#[rustfmt::skip]
let right_size = right_complete_type.unwrap_named().template_args
[UUID::from_hidden_value(0)]
.unwrap_value()
.unwrap_integer();
let out_size = match self.op {
BinaryOperator::Add => left_size + right_size,
BinaryOperator::Subtract => left_size.clone(),
BinaryOperator::Multiply => left_size * right_size,
BinaryOperator::Divide => left_size.clone(),
BinaryOperator::Modulo => right_size.clone(),
_ => {
unreachable!("The BinaryOpTypecheckConstraint should only check arithmetic operation but got {}", self.op);
}
};
let mut template_args: FlatAlloc<ConcreteType, TemplateIDMarker> = FlatAlloc::new();
template_args.alloc(ConcreteType::new_int(out_size));
let expected_out = ConcreteType::Named(ConcreteGlobalReference {
id: get_builtin_type!("int"),
template_args,
});
context.type_substitutor.unify_report_error(
&context.wires[self.out].typ,
&expected_out,
self.span,
"binary output",
);
DelayedConstraintStatus::Resolved
} else {
DelayedConstraintStatus::NoProgress
}
}

fn report_could_not_resolve_error(&self, context: &InstantiationContext<'_, '_>) {
let mut left_fully_substituted = context.wires[self.left].typ.clone();
left_fully_substituted.fully_substitute(&context.type_substitutor);
let mut right_fully_substituted = context.wires[self.right].typ.clone();
right_fully_substituted.fully_substitute(&context.type_substitutor);
let mut out_fully_substituted = context.wires[self.out].typ.clone();
out_fully_substituted.fully_substitute(&context.type_substitutor);
let message = format!(
"Failed to Typecheck {:?} = {:?} {} {:?}",
out_fully_substituted, left_fully_substituted, self.op, right_fully_substituted,
);

context.errors.error(self.span, message);
}
}
28 changes: 23 additions & 5 deletions src/instantiation/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,13 @@ use crate::prelude::*;
use crate::typing::template::GlobalReference;

use num::BigInt;
use sus_proc_macro::get_builtin_type;

use crate::flattening::*;
use crate::value::{compute_binary_op, compute_unary_op, Value};

use crate::typing::{
abstract_type::DomainType,
concrete_type::{ConcreteType, INT_CONCRETE_TYPE},
template::TemplateArgKind,
abstract_type::DomainType, concrete_type::ConcreteType, template::TemplateArgKind,
};

use super::*;
Expand Down Expand Up @@ -181,9 +180,27 @@ impl InstantiationContext<'_, '_> {
self.template_args[*template_id].clone()
}
WrittenType::Named(named_type) => {
let template_args = named_type.template_args.try_map(|template_arg| {
if let (_, Some(template_arg)) = template_arg {
match &template_arg.kind {
TemplateArgKind::Type(written_type) => {
self.concretize_type(written_type)
}
TemplateArgKind::Value(uuid) => Ok(ConcreteType::Value(
self.generation_state
.get_generation_value(*uuid)
.unwrap()
.clone(),
)),
}
} else {
Ok(ConcreteType::Unknown(self.type_substitutor.alloc()))
}
})?;

ConcreteType::Named(crate::typing::concrete_type::ConcreteGlobalReference {
id: named_type.id,
template_args: FlatAlloc::new(),
template_args,
})
}
WrittenType::Array(_, arr_box) => {
Expand Down Expand Up @@ -320,7 +337,8 @@ impl InstantiationContext<'_, '_> {
&WireReferencePathElement::ArrayAccess { idx, bracket_span } => {
let idx_wire = self.get_wire_or_constant_as_wire(idx, domain);
assert_eq!(
self.wires[idx_wire].typ, INT_CONCRETE_TYPE,
self.wires[idx_wire].typ.unwrap_named().id,
get_builtin_type!("int"),
"Caught by typecheck"
);
preamble.push(RealWirePathElem::ArrayAccess {
Expand Down
8 changes: 6 additions & 2 deletions src/to_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,12 @@ pub struct ConcreteTypeDisplay<'a, T: Index<TypeUUID, Output = StructType>> {
impl<T: Index<TypeUUID, Output = StructType>> Display for ConcreteTypeDisplay<'_, T> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self.inner {
ConcreteType::Named(name) => {
f.write_str(&self.linker_types[name.id].link_info.get_full_name())
ConcreteType::Named(global_ref) => {
f.write_str(&self.linker_types[global_ref.id].link_info.get_full_name())?;
for template_arg in global_ref.template_args.iter() {
write!(f, "{}", template_arg.1.display(self.linker_types))?;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should add the field names. Actually, there is a function that does this already: pretty_print_concrete_instance

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where do I get the &LinkInfo from? Should it be added to the display proxy?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

&self.linker_types[global_ref.id].link_info

}
Ok(())
}
ConcreteType::Array(arr_box) => {
let (elem_typ, arr_size) = arr_box.deref();
Expand Down
Loading