Add: codegen (left open) range

This commit is contained in:
Shunsuke Shibayama 2022-08-13 01:25:56 +09:00
parent 62452d5a2a
commit 499221cde1
3 changed files with 66 additions and 6 deletions

View file

@ -317,6 +317,7 @@ impl CodeGenerator {
let name = escape_name(name);
match self.rec_search(&name) {
Some(st @ (StoreLoadKind::Local | StoreLoadKind::Global)) => {
let st = if current_is_toplevel { StoreLoadKind::Local } else { st };
self.mut_cur_block_codeobj().names.push(name);
Name::new(st, self.cur_block_codeobj().names.len() - 1)
}
@ -932,6 +933,13 @@ impl CodeGenerator {
}
Expr::BinOp(bin) => {
// TODO: and/orのプリミティブ命令の実装
// Range operators are not operators in Python
match &bin.op.kind {
// l..<r == range(l, r)
TokenKind::RightOpen => { self.emit_load_name_instr(Str::ever("range")).unwrap(); },
TokenKind::LeftOpen | TokenKind::Closed | TokenKind::Open => todo!(),
_ => {}
}
let type_pair = TypePair::new(bin.lhs_t(), bin.rhs_t());
self.codegen_expr(*bin.lhs);
self.codegen_expr(*bin.rhs);
@ -950,7 +958,8 @@ impl CodeGenerator {
| TokenKind::NotEq
| TokenKind::Gre
| TokenKind::GreEq => COMPARE_OP,
TokenKind::Closed => ERG_BINARY_RANGE,
TokenKind::LeftOpen | TokenKind::RightOpen
| TokenKind::Closed | TokenKind::Open => CALL_FUNCTION, // ERG_BINARY_RANGE,
_ => {
self.errs.push(CompileError::feature_error(
self.cfg.input.clone(),
@ -968,11 +977,18 @@ impl CodeGenerator {
TokenKind::NotEq => 3,
TokenKind::Gre => 4,
TokenKind::GreEq => 5,
TokenKind::LeftOpen | TokenKind::RightOpen
| TokenKind::Closed | TokenKind::Open => 2,
_ => type_pair as u8,
};
self.write_instr(instr);
self.write_arg(arg);
self.stack_dec();
match &bin.op.kind {
TokenKind::LeftOpen | TokenKind::RightOpen
| TokenKind::Open | TokenKind::Closed => { self.stack_dec(); },
_ => {}
}
}
Expr::Call(call) => {
// TODO: unwrap

View file

@ -1495,7 +1495,9 @@ impl Context {
/// Assuming that `sub` is a subtype of `sup`, fill in the type variable to satisfy the assumption
/// ```
/// sub_unify({I: Int | I == 0}, ?T(<: Ord)): (Ord :> ?T :> {I: Int | I == 0})
/// sub_unify({I: Int | I == 0}, ?T(<: Ord)): (/* OK */)
/// sub_unify(Int, ?T(:> Nat)): (?T :> Int)
/// sub_unify(Nat, ?T(:> Int)): (/* OK */)
/// sub_unify(Nat, Add(?R, ?O)): (?R => Nat, ?O => Nat)
/// sub_unify([?T; 0], Mutate): (/* OK */)
/// ```
@ -1516,9 +1518,32 @@ impl Context {
))
}
match (maybe_sub, maybe_sup) {
(_l, Type::FreeVar(fv)) if fv.is_unbound() => {
todo!()
(l, Type::FreeVar(fv)) if fv.is_unbound() => {
match &mut *fv.borrow_mut() {
FreeKind::NamedUnbound{ constraint, .. }
| FreeKind::Unbound{ constraint, .. } => match constraint {
// sub_unify(Nat, ?T(:> Int)): (/* OK */)
// sub_unify(Int, ?T(:> Nat)): (?T :> Int)
Constraint::SupertypeOf(sub) if self.rec_supertype_of(l, sub) => {
*constraint = Constraint::SupertypeOf(l.clone());
},
// sub_unify(Nat, ?T(<: Int)): (/* OK */)
// sub_unify(Int, ?T(<: Nat)): Error!
Constraint::SubtypeOf(sup) if self.rec_supertype_of(l, sup) => {
return Err(TyCheckError::subtyping_error(l, sup, sub_loc, sup_loc, self.caused_by()))
},
// sub_unify(Nat, (Ratio :> ?T :> Int)): (/* OK */)
// sub_unify(Int, (Ratio :> ?T :> Nat)): (Ratio :> ?T :> Int)
Constraint::Sandwiched{ sub, sup } if self.rec_supertype_of(l, sub) => {
*constraint = Constraint::Sandwiched{ sub: l.clone(), sup: mem::take(sup) };
},
_ => {}
},
_ => {},
}
return Ok(())
},
(Type::FreeVar(fv), _r) if fv.is_linked() => todo!(),
(l @ Refinement(_), r @ Refinement(_)) => {
return self.unify(l ,r, sub_loc, sup_loc)
},
@ -2434,13 +2459,19 @@ impl Context {
fn is_sub_constraint_of(&self, l: &Constraint, r: &Constraint) -> bool {
match (l, r) {
// |T <: Nat| <: |T <: Int|
// |T :> Nat| <: |T :> Int|
// |I: Nat| <: |I: Int|
(Constraint::SubtypeOf(lhs), Constraint::SubtypeOf(rhs))
| (Constraint::SupertypeOf(lhs), Constraint::SupertypeOf(rhs))
| (Constraint::TypeOf(lhs), Constraint::TypeOf(rhs)) =>
self.rec_subtype_of(lhs, rhs),
// |Int <: T| <: |Nat <: T|
(Constraint::SupertypeOf(lhs), Constraint::SupertypeOf(rhs)) =>
self.rec_supertype_of(lhs, rhs),
(Constraint::SubtypeOf(_), Constraint::TypeOf(Type)) => true,
// |Int <: T <: Ratio| <: |Nat <: T <: Complex|
(
Constraint::Sandwiched{ sub: lsub, sup: lsup },
Constraint::Sandwiched{ sub: rsub, sup: rsup },
) => self.rec_supertype_of(lsub, rsub) && self.rec_subtype_of(lsup, rsup),
_ => false,
}
}

View file

@ -392,6 +392,19 @@ passed keyword args: {RED}{kw_args_len}{RESET}"),
), None), caused_by)
}
pub fn subtyping_error(sub_t: &Type, sup_t: &Type, sub_loc: Option<Location>, sup_loc: Option<Location>, caused_by: Str) -> Self {
let loc = match (sub_loc, sup_loc) {
(Some(l), Some(r)) => Location::pair(l, r),
(Some(l), None) => l,
(None, Some(r)) => r,
(None, None) => Location::Unknown,
};
Self::new(ErrorCore::new(0, TypeError, loc, switch_lang!(
format!("subtype constraints cannot be satisfied:\nsubtype: {YELLOW}{sub_t}{RESET}\nsupertype: {YELLOW}{sup_t}{RESET}"),
format!("部分型制約を満たせません:\nサブタイプ: {YELLOW}{sub_t}{RESET}\nスーパータイプ: {YELLOW}{sup_t}{RESET}")
), None), caused_by)
}
pub fn pred_unification_error(lhs: &Predicate, rhs: &Predicate, caused_by: Str) -> Self {
Self::new(ErrorCore::new(0, TypeError, Location::Unknown, switch_lang!(
format!("predicate unification failed:\nlhs: {YELLOW}{lhs}{RESET}\nrhs: {YELLOW}{rhs}{RESET}"),