mirror of
https://github.com/erg-lang/erg.git
synced 2025-08-04 02:39:20 +00:00
feat: add ConstTypeAsc
This commit is contained in:
parent
1dbfb4b834
commit
aaa259d6c0
4 changed files with 81 additions and 7 deletions
|
@ -892,6 +892,28 @@ impl Context {
|
|||
let val = self.instantiate_const_expr(&unary.expr, erased_idx, tmp_tv_cache)?;
|
||||
Ok(TyParam::unary(op, val))
|
||||
}
|
||||
ast::ConstExpr::TypeAsc(tasc) => {
|
||||
let tp = self.instantiate_const_expr(&tasc.expr, erased_idx, tmp_tv_cache)?;
|
||||
let spec_t = self.instantiate_typespec(
|
||||
&tasc.t_spec.t_spec,
|
||||
None,
|
||||
tmp_tv_cache,
|
||||
RegistrationMode::Normal,
|
||||
false,
|
||||
)?;
|
||||
if self.subtype_of(&self.get_tp_t(&tp)?, &spec_t, true) {
|
||||
Ok(tp)
|
||||
} else {
|
||||
Err(TyCheckErrors::from(TyCheckError::subtyping_error(
|
||||
self.cfg.input.clone(),
|
||||
line!() as usize,
|
||||
&self.get_tp_t(&tp)?,
|
||||
&spec_t,
|
||||
tasc.loc(),
|
||||
self.caused_by(),
|
||||
)))
|
||||
}
|
||||
}
|
||||
other => type_feature_error!(
|
||||
self,
|
||||
other.loc(),
|
||||
|
|
|
@ -388,6 +388,22 @@ impl ASTLowerer {
|
|||
Ok(hir::Dummy::new(dummy_))
|
||||
}
|
||||
|
||||
fn fake_lower_type_asc(&self, tasc: ast::TypeAscription) -> LowerResult<hir::TypeAscription> {
|
||||
let expr = self.fake_lower_expr(*tasc.expr)?;
|
||||
let t_spec_as_expr = self.fake_lower_expr(*tasc.t_spec.t_spec_as_expr)?;
|
||||
let mut dummy_tv_cache = TyVarCache::new(self.module.context.level, &self.module.context);
|
||||
let spec_t = self.module.context.instantiate_typespec(
|
||||
&tasc.t_spec.t_spec,
|
||||
None,
|
||||
&mut dummy_tv_cache,
|
||||
RegistrationMode::Normal,
|
||||
false,
|
||||
)?;
|
||||
let spec =
|
||||
hir::TypeSpecWithOp::new(tasc.t_spec.op, tasc.t_spec.t_spec, t_spec_as_expr, spec_t);
|
||||
Ok(hir::TypeAscription::new(expr, spec))
|
||||
}
|
||||
|
||||
pub(crate) fn fake_lower_expr(&self, expr: ast::Expr) -> LowerResult<hir::Expr> {
|
||||
match expr {
|
||||
ast::Expr::Literal(lit) => Ok(hir::Expr::Lit(self.lower_literal(lit)?)),
|
||||
|
@ -401,6 +417,9 @@ impl ASTLowerer {
|
|||
ast::Expr::Call(call) => Ok(hir::Expr::Call(self.fake_lower_call(call)?)),
|
||||
ast::Expr::Lambda(lambda) => Ok(hir::Expr::Lambda(self.fake_lower_lambda(lambda)?)),
|
||||
ast::Expr::Dummy(dummy) => Ok(hir::Expr::Dummy(self.fake_lower_dummy(dummy)?)),
|
||||
ast::Expr::TypeAscription(tasc) => {
|
||||
Ok(hir::Expr::TypeAsc(self.fake_lower_type_asc(tasc)?))
|
||||
}
|
||||
other => Err(LowerErrors::from(LowerError::declare_error(
|
||||
self.cfg().input.clone(),
|
||||
line!() as usize,
|
||||
|
|
|
@ -1773,6 +1773,38 @@ impl ConstApp {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct ConstTypeAsc {
|
||||
pub expr: Box<ConstExpr>,
|
||||
pub t_spec: Box<TypeSpecWithOp>,
|
||||
}
|
||||
|
||||
impl NestedDisplay for ConstTypeAsc {
|
||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
|
||||
writeln!(f, "{}{}", self.expr, self.t_spec)
|
||||
}
|
||||
}
|
||||
|
||||
impl_display_from_nested!(ConstTypeAsc);
|
||||
impl_locational!(ConstTypeAsc, expr, t_spec);
|
||||
|
||||
impl ConstTypeAsc {
|
||||
pub fn new(expr: ConstExpr, t_spec: TypeSpecWithOp) -> Self {
|
||||
Self {
|
||||
expr: Box::new(expr),
|
||||
t_spec: Box::new(t_spec),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_instance_ascription(&self) -> bool {
|
||||
self.t_spec.op.is(TokenKind::Colon)
|
||||
}
|
||||
|
||||
pub fn is_subtype_ascription(&self) -> bool {
|
||||
self.t_spec.op.is(TokenKind::SubtypeOf)
|
||||
}
|
||||
}
|
||||
|
||||
/// valid expression for an argument of polymorphic types
|
||||
/// 多相型の実引数として有効な式
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
|
@ -1790,11 +1822,12 @@ pub enum ConstExpr {
|
|||
Lambda(ConstLambda),
|
||||
BinOp(ConstBinOp),
|
||||
UnaryOp(ConstUnaryOp),
|
||||
TypeAsc(ConstTypeAsc),
|
||||
}
|
||||
|
||||
impl_nested_display_for_chunk_enum!(ConstExpr; Lit, Accessor, App, Array, Set, Dict, Tuple, Record, BinOp, UnaryOp, Def, Lambda, Erased, Set);
|
||||
impl_nested_display_for_chunk_enum!(ConstExpr; Lit, Accessor, App, Array, Set, Dict, Tuple, Record, BinOp, UnaryOp, Def, Lambda, Erased, Set, TypeAsc);
|
||||
impl_display_from_nested!(ConstExpr);
|
||||
impl_locational_for_enum!(ConstExpr; Lit, Accessor, App, Array, Set, Dict, Tuple, Record, BinOp, UnaryOp, Def, Lambda, Erased, Set);
|
||||
impl_locational_for_enum!(ConstExpr; Lit, Accessor, App, Array, Set, Dict, Tuple, Record, BinOp, UnaryOp, Def, Lambda, Erased, Set, TypeAsc);
|
||||
|
||||
impl ConstExpr {
|
||||
pub fn need_to_be_closed(&self) -> bool {
|
||||
|
|
|
@ -130,13 +130,13 @@ impl Parser {
|
|||
const_fields,
|
||||
)))
|
||||
}
|
||||
// TODO: Lambda, ...
|
||||
Expr::TypeAscription(tasc) => {
|
||||
let expr = Self::validate_const_expr(*tasc.expr)?;
|
||||
Ok(ConstExpr::TypeAsc(ConstTypeAsc::new(expr, tasc.t_spec)))
|
||||
}
|
||||
other => Err(ParseError::syntax_error(
|
||||
line!() as usize,
|
||||
{
|
||||
erg_common::log!(err "{other}");
|
||||
other.loc()
|
||||
},
|
||||
other.loc(),
|
||||
switch_lang!(
|
||||
"japanese" => "この式はコンパイル時計算できないため、型引数には使用できません",
|
||||
"simplified_chinese" => "此表达式在编译时不可计算,因此不能用作类型参数",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue