|
1 | 1 | use std::ops::Deref;
|
2 | 2 |
|
3 |
| -use crate::alloc::{zip_eq, zip_eq3}; |
| 3 | +use sus_proc_macro::get_builtin_type; |
| 4 | + |
| 5 | +use crate::alloc::{zip_eq, zip_eq3, UUID}; |
4 | 6 | use crate::errors::ErrorInfoObject;
|
5 | 7 | use crate::flattening::{DeclarationKind, ExpressionSource, WireReferenceRoot, WrittenType};
|
6 | 8 | use crate::linker::LinkInfo;
|
@@ -52,7 +54,7 @@ impl InstantiationContext<'_, '_> {
|
52 | 54 | )))
|
53 | 55 | }
|
54 | 56 |
|
55 |
| - fn typecheck_all_wires(&self) { |
| 57 | + fn typecheck_all_wires(&self, delayed_constraints: &mut DelayedConstraintsList<Self>) { |
56 | 58 | for this_wire_id in self.wires.id_range() {
|
57 | 59 | let this_wire = &self.wires[this_wire_id];
|
58 | 60 | let span = self.md.get_instruction_span(this_wire.original_instruction);
|
@@ -104,6 +106,14 @@ impl InstantiationContext<'_, '_> {
|
104 | 106 | }
|
105 | 107 | &RealWireDataSource::BinaryOp { op, left, right } => {
|
106 | 108 | // TODO overloading
|
| 109 | + // Typecheck generic INT |
| 110 | + delayed_constraints.push(BinaryOpTypecheckConstraint::new( |
| 111 | + op, |
| 112 | + left, |
| 113 | + right, |
| 114 | + this_wire_id, |
| 115 | + span, |
| 116 | + )); |
107 | 117 | let ((in_left, in_right), out) = match op {
|
108 | 118 | BinaryOperator::And => {
|
109 | 119 | ((BOOL_CONCRETE_TYPE, BOOL_CONCRETE_TYPE), BOOL_CONCRETE_TYPE)
|
@@ -249,7 +259,7 @@ impl InstantiationContext<'_, '_> {
|
249 | 259 | delayed_constraints.push(SubmoduleTypecheckConstraint { sm_id });
|
250 | 260 | }
|
251 | 261 |
|
252 |
| - self.typecheck_all_wires(); |
| 262 | + self.typecheck_all_wires(&mut delayed_constraints); |
253 | 263 |
|
254 | 264 | delayed_constraints.resolve_delayed_constraints(self);
|
255 | 265 |
|
@@ -500,3 +510,79 @@ impl DelayedConstraint<InstantiationContext<'_, '_>> for SubmoduleTypecheckConst
|
500 | 510 | .error(submod_instr.get_most_relevant_span(), message);
|
501 | 511 | }
|
502 | 512 | }
|
| 513 | + |
| 514 | +#[derive(Debug)] |
| 515 | +struct BinaryOpTypecheckConstraint { |
| 516 | + _op: BinaryOperator, |
| 517 | + left: UUID<WireIDMarker>, |
| 518 | + right: UUID<WireIDMarker>, |
| 519 | + out: UUID<WireIDMarker>, |
| 520 | + span: Span, |
| 521 | +} |
| 522 | + |
| 523 | +impl BinaryOpTypecheckConstraint { |
| 524 | + fn new( |
| 525 | + _op: BinaryOperator, |
| 526 | + left: UUID<WireIDMarker>, |
| 527 | + right: UUID<WireIDMarker>, |
| 528 | + out: UUID<WireIDMarker>, |
| 529 | + span: Span, |
| 530 | + ) -> Self { |
| 531 | + Self { |
| 532 | + _op, |
| 533 | + left, |
| 534 | + right, |
| 535 | + out, |
| 536 | + span, |
| 537 | + } |
| 538 | + } |
| 539 | +} |
| 540 | + |
| 541 | +impl DelayedConstraint<InstantiationContext<'_, '_>> for BinaryOpTypecheckConstraint { |
| 542 | + fn try_apply(&mut self, context: &mut InstantiationContext<'_, '_>) -> DelayedConstraintStatus { |
| 543 | + if context.wires[self.out].typ.contains_unknown() |
| 544 | + || context.wires[self.left].typ.contains_unknown() |
| 545 | + || context.wires[self.right].typ.contains_unknown() |
| 546 | + { |
| 547 | + return DelayedConstraintStatus::NoProgress; |
| 548 | + } |
| 549 | + let left_size = context.wires[self.left] |
| 550 | + .typ |
| 551 | + .try_fully_substitute(&context.type_substitutor) |
| 552 | + .unwrap() |
| 553 | + .unwrap_named() |
| 554 | + .template_args[UUID::from_hidden_value(0)] |
| 555 | + .unwrap_value() |
| 556 | + .unwrap_integer() |
| 557 | + .clone(); |
| 558 | + let right_size = context.wires[self.right] |
| 559 | + .typ |
| 560 | + .try_fully_substitute(&context.type_substitutor) |
| 561 | + .unwrap() |
| 562 | + .unwrap_named() |
| 563 | + .template_args[UUID::from_hidden_value(0)] |
| 564 | + .unwrap_value() |
| 565 | + .unwrap_integer() |
| 566 | + .clone(); |
| 567 | + let out_size = left_size + right_size; |
| 568 | + let mut template_args: FlatAlloc<ConcreteType, TemplateIDMarker> = FlatAlloc::new(); |
| 569 | + template_args.alloc(ConcreteType::new_int(out_size)); |
| 570 | + let expected_out = ConcreteType::Named(ConcreteGlobalReference { |
| 571 | + id: get_builtin_type!("int"), |
| 572 | + template_args, |
| 573 | + }); |
| 574 | + |
| 575 | + context.type_substitutor.unify_report_error( |
| 576 | + &context.wires[self.out].typ, |
| 577 | + &expected_out, |
| 578 | + self.span, |
| 579 | + "binary output", |
| 580 | + ); |
| 581 | + |
| 582 | + DelayedConstraintStatus::Resolved |
| 583 | + } |
| 584 | + |
| 585 | + fn report_could_not_resolve_error(&self, _context: &InstantiationContext<'_, '_>) { |
| 586 | + todo!() |
| 587 | + } |
| 588 | +} |
0 commit comments