mirror of
https://github.com/erg-lang/erg.git
synced 2025-10-01 05:11:09 +00:00
Add: codegen (left open) range
This commit is contained in:
parent
62452d5a2a
commit
499221cde1
3 changed files with 66 additions and 6 deletions
|
@ -317,6 +317,7 @@ impl CodeGenerator {
|
||||||
let name = escape_name(name);
|
let name = escape_name(name);
|
||||||
match self.rec_search(&name) {
|
match self.rec_search(&name) {
|
||||||
Some(st @ (StoreLoadKind::Local | StoreLoadKind::Global)) => {
|
Some(st @ (StoreLoadKind::Local | StoreLoadKind::Global)) => {
|
||||||
|
let st = if current_is_toplevel { StoreLoadKind::Local } else { st };
|
||||||
self.mut_cur_block_codeobj().names.push(name);
|
self.mut_cur_block_codeobj().names.push(name);
|
||||||
Name::new(st, self.cur_block_codeobj().names.len() - 1)
|
Name::new(st, self.cur_block_codeobj().names.len() - 1)
|
||||||
}
|
}
|
||||||
|
@ -932,6 +933,13 @@ impl CodeGenerator {
|
||||||
}
|
}
|
||||||
Expr::BinOp(bin) => {
|
Expr::BinOp(bin) => {
|
||||||
// TODO: and/orのプリミティブ命令の実装
|
// 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());
|
let type_pair = TypePair::new(bin.lhs_t(), bin.rhs_t());
|
||||||
self.codegen_expr(*bin.lhs);
|
self.codegen_expr(*bin.lhs);
|
||||||
self.codegen_expr(*bin.rhs);
|
self.codegen_expr(*bin.rhs);
|
||||||
|
@ -950,7 +958,8 @@ impl CodeGenerator {
|
||||||
| TokenKind::NotEq
|
| TokenKind::NotEq
|
||||||
| TokenKind::Gre
|
| TokenKind::Gre
|
||||||
| TokenKind::GreEq => COMPARE_OP,
|
| 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.errs.push(CompileError::feature_error(
|
||||||
self.cfg.input.clone(),
|
self.cfg.input.clone(),
|
||||||
|
@ -968,11 +977,18 @@ impl CodeGenerator {
|
||||||
TokenKind::NotEq => 3,
|
TokenKind::NotEq => 3,
|
||||||
TokenKind::Gre => 4,
|
TokenKind::Gre => 4,
|
||||||
TokenKind::GreEq => 5,
|
TokenKind::GreEq => 5,
|
||||||
|
TokenKind::LeftOpen | TokenKind::RightOpen
|
||||||
|
| TokenKind::Closed | TokenKind::Open => 2,
|
||||||
_ => type_pair as u8,
|
_ => type_pair as u8,
|
||||||
};
|
};
|
||||||
self.write_instr(instr);
|
self.write_instr(instr);
|
||||||
self.write_arg(arg);
|
self.write_arg(arg);
|
||||||
self.stack_dec();
|
self.stack_dec();
|
||||||
|
match &bin.op.kind {
|
||||||
|
TokenKind::LeftOpen | TokenKind::RightOpen
|
||||||
|
| TokenKind::Open | TokenKind::Closed => { self.stack_dec(); },
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Expr::Call(call) => {
|
Expr::Call(call) => {
|
||||||
// TODO: unwrap
|
// TODO: unwrap
|
||||||
|
|
|
@ -1495,7 +1495,9 @@ impl Context {
|
||||||
|
|
||||||
/// Assuming that `sub` is a subtype of `sup`, fill in the type variable to satisfy the assumption
|
/// 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(Nat, Add(?R, ?O)): (?R => Nat, ?O => Nat)
|
||||||
/// sub_unify([?T; 0], Mutate): (/* OK */)
|
/// sub_unify([?T; 0], Mutate): (/* OK */)
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -1516,9 +1518,32 @@ impl Context {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
match (maybe_sub, maybe_sup) {
|
match (maybe_sub, maybe_sup) {
|
||||||
(_l, Type::FreeVar(fv)) if fv.is_unbound() => {
|
(l, Type::FreeVar(fv)) if fv.is_unbound() => {
|
||||||
todo!()
|
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(_)) => {
|
(l @ Refinement(_), r @ Refinement(_)) => {
|
||||||
return self.unify(l ,r, sub_loc, sup_loc)
|
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 {
|
fn is_sub_constraint_of(&self, l: &Constraint, r: &Constraint) -> bool {
|
||||||
match (l, r) {
|
match (l, r) {
|
||||||
// |T <: Nat| <: |T <: Int|
|
// |T <: Nat| <: |T <: Int|
|
||||||
// |T :> Nat| <: |T :> Int|
|
|
||||||
// |I: Nat| <: |I: Int|
|
// |I: Nat| <: |I: Int|
|
||||||
(Constraint::SubtypeOf(lhs), Constraint::SubtypeOf(rhs))
|
(Constraint::SubtypeOf(lhs), Constraint::SubtypeOf(rhs))
|
||||||
| (Constraint::SupertypeOf(lhs), Constraint::SupertypeOf(rhs))
|
|
||||||
| (Constraint::TypeOf(lhs), Constraint::TypeOf(rhs)) =>
|
| (Constraint::TypeOf(lhs), Constraint::TypeOf(rhs)) =>
|
||||||
self.rec_subtype_of(lhs, 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,
|
(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,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -392,6 +392,19 @@ passed keyword args: {RED}{kw_args_len}{RESET}"),
|
||||||
), None), caused_by)
|
), 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 {
|
pub fn pred_unification_error(lhs: &Predicate, rhs: &Predicate, caused_by: Str) -> Self {
|
||||||
Self::new(ErrorCore::new(0, TypeError, Location::Unknown, switch_lang!(
|
Self::new(ErrorCore::new(0, TypeError, Location::Unknown, switch_lang!(
|
||||||
format!("predicate unification failed:\nlhs: {YELLOW}{lhs}{RESET}\nrhs: {YELLOW}{rhs}{RESET}"),
|
format!("predicate unification failed:\nlhs: {YELLOW}{lhs}{RESET}\nrhs: {YELLOW}{rhs}{RESET}"),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue