mirror of
https://github.com/erg-lang/erg.git
synced 2025-08-04 10:49:54 +00:00
feat(parser): add type_spec_to_expr
This commit is contained in:
parent
a2a55b0645
commit
d8f4d14abd
10 changed files with 148 additions and 49 deletions
|
@ -139,7 +139,7 @@ impl ASTSemanticState {
|
|||
|
||||
fn gen_from_expr(&mut self, expr: Expr) -> Vec<SemanticToken> {
|
||||
match expr {
|
||||
Expr::Lit(lit) => {
|
||||
Expr::Literal(lit) => {
|
||||
let typ = match lit.token.kind {
|
||||
TokenKind::StrLit => SemanticTokenType::STRING,
|
||||
TokenKind::NatLit | TokenKind::IntLit | TokenKind::RatioLit => {
|
||||
|
|
|
@ -810,6 +810,19 @@ macro_rules! impl_nested_display_for_chunk_enum {
|
|||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_from_trait_for_enum {
|
||||
($Enum: ident; $($Variant: ident $(,)?)*) => {
|
||||
$(
|
||||
impl From<$Variant> for $Enum {
|
||||
fn from(v: $Variant) -> Self {
|
||||
$Enum::$Variant(v)
|
||||
}
|
||||
}
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_nested_display_for_enum {
|
||||
($Enum: ident; $($Variant: ident $(,)?)*) => {
|
||||
|
|
|
@ -523,7 +523,7 @@ impl Context {
|
|||
|
||||
pub(crate) fn eval_const_expr(&self, expr: &Expr) -> EvalResult<ValueObj> {
|
||||
match expr {
|
||||
Expr::Lit(lit) => self.eval_lit(lit),
|
||||
Expr::Literal(lit) => self.eval_lit(lit),
|
||||
Expr::Accessor(acc) => self.eval_const_acc(acc),
|
||||
Expr::BinOp(bin) => self.eval_const_bin(bin),
|
||||
Expr::UnaryOp(unary) => self.eval_const_unary(unary),
|
||||
|
@ -535,7 +535,7 @@ impl Context {
|
|||
Expr::Record(rec) => self.eval_const_record(rec),
|
||||
Expr::Lambda(lambda) => self.eval_const_lambda(lambda),
|
||||
// FIXME: type check
|
||||
Expr::TypeAsc(tasc) => self.eval_const_expr(&tasc.expr),
|
||||
Expr::TypeAscription(tasc) => self.eval_const_expr(&tasc.expr),
|
||||
other => Err(EvalErrors::from(EvalError::not_const_expr(
|
||||
self.cfg.input.clone(),
|
||||
line!() as usize,
|
||||
|
@ -553,7 +553,7 @@ impl Context {
|
|||
match expr {
|
||||
// TODO: ClassDef, PatchDef
|
||||
Expr::Def(def) => self.eval_const_def(def),
|
||||
Expr::Lit(lit) => self.eval_lit(lit),
|
||||
Expr::Literal(lit) => self.eval_lit(lit),
|
||||
Expr::Accessor(acc) => self.eval_const_acc(acc),
|
||||
Expr::BinOp(bin) => self.eval_const_bin(bin),
|
||||
Expr::UnaryOp(unary) => self.eval_const_unary(unary),
|
||||
|
@ -564,7 +564,7 @@ impl Context {
|
|||
Expr::Tuple(tuple) => self.eval_const_tuple(tuple),
|
||||
Expr::Record(rec) => self.eval_const_record(rec),
|
||||
Expr::Lambda(lambda) => self.eval_const_lambda(lambda),
|
||||
Expr::TypeAsc(tasc) => self.eval_const_expr(&tasc.expr),
|
||||
Expr::TypeAscription(tasc) => self.eval_const_expr(&tasc.expr),
|
||||
other => Err(EvalErrors::from(EvalError::not_const_expr(
|
||||
self.cfg.input.clone(),
|
||||
line!() as usize,
|
||||
|
|
|
@ -302,11 +302,11 @@ impl ASTLowerer {
|
|||
fn declare_chunk(&mut self, expr: ast::Expr) -> LowerResult<hir::Expr> {
|
||||
log!(info "entered {}", fn_name!());
|
||||
match expr {
|
||||
ast::Expr::Lit(lit) if lit.is_doc_comment() => {
|
||||
ast::Expr::Literal(lit) if lit.is_doc_comment() => {
|
||||
Ok(hir::Expr::Lit(self.lower_literal(lit)?))
|
||||
}
|
||||
ast::Expr::Def(def) => Ok(hir::Expr::Def(self.declare_def(def)?)),
|
||||
ast::Expr::TypeAsc(tasc) => Ok(hir::Expr::TypeAsc(self.declare_ident(tasc)?)),
|
||||
ast::Expr::TypeAscription(tasc) => Ok(hir::Expr::TypeAsc(self.declare_ident(tasc)?)),
|
||||
ast::Expr::Call(call)
|
||||
if call
|
||||
.additional_operation()
|
||||
|
|
|
@ -1404,7 +1404,7 @@ impl ASTLowerer {
|
|||
ast::TypeSpec::TypeApp { spec, args } => {
|
||||
let (impl_trait, loc) = match &args.args.pos_args().first().unwrap().expr {
|
||||
// TODO: check `tasc.op`
|
||||
ast::Expr::TypeAsc(tasc) => (
|
||||
ast::Expr::TypeAscription(tasc) => (
|
||||
self.module.context.instantiate_typespec(
|
||||
&tasc.t_spec,
|
||||
None,
|
||||
|
@ -2143,7 +2143,7 @@ impl ASTLowerer {
|
|||
fn lower_expr(&mut self, expr: ast::Expr) -> LowerResult<hir::Expr> {
|
||||
log!(info "entered {}", fn_name!());
|
||||
match expr {
|
||||
ast::Expr::Lit(lit) => Ok(hir::Expr::Lit(self.lower_literal(lit)?)),
|
||||
ast::Expr::Literal(lit) => Ok(hir::Expr::Lit(self.lower_literal(lit)?)),
|
||||
ast::Expr::Array(arr) => Ok(hir::Expr::Array(self.lower_array(arr)?)),
|
||||
ast::Expr::Tuple(tup) => Ok(hir::Expr::Tuple(self.lower_tuple(tup)?)),
|
||||
ast::Expr::Record(rec) => Ok(hir::Expr::Record(self.lower_record(rec)?)),
|
||||
|
@ -2155,7 +2155,7 @@ impl ASTLowerer {
|
|||
ast::Expr::Call(call) => Ok(hir::Expr::Call(self.lower_call(call)?)),
|
||||
ast::Expr::DataPack(pack) => Ok(hir::Expr::Call(self.lower_pack(pack)?)),
|
||||
ast::Expr::Lambda(lambda) => Ok(hir::Expr::Lambda(self.lower_lambda(lambda)?)),
|
||||
ast::Expr::TypeAsc(tasc) => Ok(hir::Expr::TypeAsc(self.lower_type_asc(tasc)?)),
|
||||
ast::Expr::TypeAscription(tasc) => Ok(hir::Expr::TypeAsc(self.lower_type_asc(tasc)?)),
|
||||
// Checking is also performed for expressions in Dummy. However, it has no meaning in code generation
|
||||
ast::Expr::Dummy(dummy) => Ok(hir::Expr::Dummy(self.lower_dummy(dummy)?)),
|
||||
other => {
|
||||
|
@ -2175,7 +2175,7 @@ impl ASTLowerer {
|
|||
ast::Expr::ClassDef(defs) => Ok(hir::Expr::ClassDef(self.lower_class_def(defs)?)),
|
||||
ast::Expr::PatchDef(defs) => Ok(hir::Expr::PatchDef(self.lower_patch_def(defs)?)),
|
||||
ast::Expr::ReDef(redef) => Ok(hir::Expr::ReDef(self.lower_redef(redef)?)),
|
||||
ast::Expr::TypeAsc(tasc) => Ok(hir::Expr::TypeAsc(self.lower_decl(tasc)?)),
|
||||
ast::Expr::TypeAscription(tasc) => Ok(hir::Expr::TypeAsc(self.lower_decl(tasc)?)),
|
||||
other => self.lower_expr(other),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,9 +10,9 @@ use erg_common::traits::{Locational, NestedDisplay, Stream};
|
|||
use erg_common::vis::{Field, Visibility};
|
||||
use erg_common::{
|
||||
fmt_option, fmt_vec, impl_display_for_enum, impl_display_for_single_struct,
|
||||
impl_display_from_nested, impl_displayable_stream_for_wrapper, impl_locational,
|
||||
impl_locational_for_enum, impl_nested_display_for_chunk_enum, impl_nested_display_for_enum,
|
||||
impl_stream, option_enum_unwrap,
|
||||
impl_display_from_nested, impl_displayable_stream_for_wrapper, impl_from_trait_for_enum,
|
||||
impl_locational, impl_locational_for_enum, impl_nested_display_for_chunk_enum,
|
||||
impl_nested_display_for_enum, impl_stream, option_enum_unwrap,
|
||||
};
|
||||
use erg_common::{fmt_vec_split_with, Str};
|
||||
|
||||
|
@ -1629,7 +1629,7 @@ impl ConstExpr {
|
|||
|
||||
pub fn downcast(self) -> Expr {
|
||||
match self {
|
||||
Self::Lit(lit) => Expr::Lit(lit),
|
||||
Self::Lit(lit) => Expr::Literal(lit),
|
||||
Self::Accessor(acc) => Expr::Accessor(acc.downcast()),
|
||||
Self::App(app) => Expr::Call(app.downcast()),
|
||||
Self::Array(arr) => Expr::Array(arr.downcast()),
|
||||
|
@ -2450,6 +2450,12 @@ impl From<&Identifier> for Field {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<Identifier> for Expr {
|
||||
fn from(ident: Identifier) -> Self {
|
||||
Self::Accessor(Accessor::Ident(ident))
|
||||
}
|
||||
}
|
||||
|
||||
impl Identifier {
|
||||
pub const fn new(dot: Option<Token>, name: VarName) -> Self {
|
||||
Self { dot, name }
|
||||
|
@ -3703,7 +3709,7 @@ impl PatchDef {
|
|||
/// Expression(式)
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum Expr {
|
||||
Lit(Literal),
|
||||
Literal(Literal),
|
||||
Accessor(Accessor),
|
||||
Array(Array),
|
||||
Tuple(Tuple),
|
||||
|
@ -3715,7 +3721,7 @@ pub enum Expr {
|
|||
Call(Call),
|
||||
DataPack(DataPack),
|
||||
Lambda(Lambda),
|
||||
TypeAsc(TypeAscription),
|
||||
TypeAscription(TypeAscription),
|
||||
Def(Def),
|
||||
Methods(Methods),
|
||||
ClassDef(ClassDef),
|
||||
|
@ -3725,9 +3731,10 @@ pub enum Expr {
|
|||
Dummy(Dummy),
|
||||
}
|
||||
|
||||
impl_nested_display_for_chunk_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Set, Record, BinOp, UnaryOp, Call, DataPack, Lambda, TypeAsc, Def, Methods, ClassDef, PatchDef, ReDef, Dummy);
|
||||
impl_nested_display_for_chunk_enum!(Expr; Literal, Accessor, Array, Tuple, Dict, Set, Record, BinOp, UnaryOp, Call, DataPack, Lambda, TypeAscription, Def, Methods, ClassDef, PatchDef, ReDef, Dummy);
|
||||
impl_from_trait_for_enum!(Expr; Literal, Accessor, Array, Tuple, Dict, Set, Record, BinOp, UnaryOp, Call, DataPack, Lambda, TypeAscription, Def, Methods, ClassDef, PatchDef, ReDef, Dummy);
|
||||
impl_display_from_nested!(Expr);
|
||||
impl_locational_for_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Set, Record, BinOp, UnaryOp, Call, DataPack, Lambda, TypeAsc, Def, Methods, ClassDef, PatchDef, ReDef, Dummy);
|
||||
impl_locational_for_enum!(Expr; Literal, Accessor, Array, Tuple, Dict, Set, Record, BinOp, UnaryOp, Call, DataPack, Lambda, TypeAscription, Def, Methods, ClassDef, PatchDef, ReDef, Dummy);
|
||||
|
||||
impl Expr {
|
||||
pub fn is_match_call(&self) -> bool {
|
||||
|
@ -3752,7 +3759,7 @@ impl Expr {
|
|||
pub fn need_to_be_closed(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
Expr::BinOp(_) | Expr::UnaryOp(_) | Expr::Lambda(_) | Expr::TypeAsc(_)
|
||||
Expr::BinOp(_) | Expr::UnaryOp(_) | Expr::Lambda(_) | Expr::TypeAscription(_)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -3824,7 +3831,7 @@ impl Expr {
|
|||
}
|
||||
|
||||
pub fn type_asc_expr(self, op: Token, t_spec: TypeSpec) -> Self {
|
||||
Self::TypeAsc(self.type_asc(op, t_spec))
|
||||
Self::TypeAscription(self.type_asc(op, t_spec))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ impl Parser {
|
|||
debug_exit_info!(self);
|
||||
Ok(Signature::Var(var))
|
||||
}
|
||||
Expr::TypeAsc(tasc) => {
|
||||
Expr::TypeAscription(tasc) => {
|
||||
let sig = self
|
||||
.convert_type_asc_to_sig(tasc)
|
||||
.map_err(|_| self.stack_dec(fn_name!()))?;
|
||||
|
@ -326,7 +326,7 @@ impl Parser {
|
|||
|
||||
fn convert_type_arg_to_bound(&mut self, arg: PosArg) -> ParseResult<TypeBoundSpec> {
|
||||
match arg.expr {
|
||||
Expr::TypeAsc(tasc) => {
|
||||
Expr::TypeAscription(tasc) => {
|
||||
let lhs = self
|
||||
.convert_rhs_to_sig(*tasc.expr)
|
||||
.map_err(|_| self.stack_dec(fn_name!()))?;
|
||||
|
@ -406,7 +406,7 @@ impl Parser {
|
|||
debug_exit_info!(self);
|
||||
Ok(param)
|
||||
}
|
||||
Expr::Lit(lit) => {
|
||||
Expr::Literal(lit) => {
|
||||
let pat = ParamPattern::Lit(lit);
|
||||
let param = NonDefaultParamSignature::new(pat, None);
|
||||
debug_exit_info!(self);
|
||||
|
@ -439,7 +439,7 @@ impl Parser {
|
|||
debug_exit_info!(self);
|
||||
Ok(param)
|
||||
}
|
||||
Expr::TypeAsc(tasc) => {
|
||||
Expr::TypeAscription(tasc) => {
|
||||
let param = self
|
||||
.convert_type_asc_to_param_pattern(tasc, allow_self)
|
||||
.map_err(|_| self.stack_dec(fn_name!()))?;
|
||||
|
@ -607,7 +607,7 @@ impl Parser {
|
|||
pub(crate) fn convert_rhs_to_lambda_sig(&mut self, rhs: Expr) -> ParseResult<LambdaSignature> {
|
||||
debug_call_info!(self);
|
||||
match rhs {
|
||||
Expr::Lit(lit) => {
|
||||
Expr::Literal(lit) => {
|
||||
let param = NonDefaultParamSignature::new(ParamPattern::Lit(lit), None);
|
||||
let params = Params::new(vec![param], None, vec![], None);
|
||||
Ok(LambdaSignature::new(params, None, TypeBoundSpecs::empty()))
|
||||
|
@ -645,7 +645,7 @@ impl Parser {
|
|||
debug_exit_info!(self);
|
||||
Ok(LambdaSignature::new(params, None, TypeBoundSpecs::empty()))
|
||||
}
|
||||
Expr::TypeAsc(tasc) => {
|
||||
Expr::TypeAscription(tasc) => {
|
||||
let sig = self
|
||||
.convert_type_asc_to_lambda_sig(tasc)
|
||||
.map_err(|_| self.stack_dec(fn_name!()))?;
|
||||
|
@ -738,7 +738,7 @@ impl Parser {
|
|||
) -> ParseResult<LambdaSignature> {
|
||||
debug_call_info!(self);
|
||||
let sig = self
|
||||
.convert_rhs_to_param(Expr::TypeAsc(tasc), true)
|
||||
.convert_rhs_to_param(Expr::TypeAscription(tasc), true)
|
||||
.map_err(|_| self.stack_dec(fn_name!()))?;
|
||||
debug_exit_info!(self);
|
||||
Ok(LambdaSignature::new(
|
||||
|
|
|
@ -96,7 +96,7 @@ impl Desugarer {
|
|||
|
||||
fn perform_desugar(mut desugar: impl FnMut(Expr) -> Expr, expr: Expr) -> Expr {
|
||||
match expr {
|
||||
Expr::Lit(_) => expr,
|
||||
Expr::Literal(_) => expr,
|
||||
Expr::Record(record) => match record {
|
||||
Record::Normal(rec) => {
|
||||
let mut new_attrs = vec![];
|
||||
|
@ -268,7 +268,7 @@ impl Desugarer {
|
|||
let body = Block::new(chunks);
|
||||
Expr::Lambda(Lambda::new(lambda.sig, lambda.op, body, lambda.id))
|
||||
}
|
||||
Expr::TypeAsc(tasc) => {
|
||||
Expr::TypeAscription(tasc) => {
|
||||
let expr = desugar(*tasc.expr);
|
||||
expr.type_asc_expr(tasc.op, tasc.t_spec)
|
||||
}
|
||||
|
@ -605,7 +605,10 @@ impl Desugarer {
|
|||
sig.ln_begin().unwrap(),
|
||||
sig.col_begin().unwrap(),
|
||||
);
|
||||
obj.subscr(Expr::Lit(Literal::nat(n, sig.ln_begin().unwrap())), r_brace)
|
||||
obj.subscr(
|
||||
Expr::Literal(Literal::nat(n, sig.ln_begin().unwrap())),
|
||||
r_brace,
|
||||
)
|
||||
}
|
||||
BufIndex::Record(attr) => obj.attr(attr.clone()),
|
||||
};
|
||||
|
@ -887,7 +890,10 @@ impl Desugarer {
|
|||
sig.ln_begin().unwrap(),
|
||||
sig.col_begin().unwrap(),
|
||||
);
|
||||
obj.subscr(Expr::Lit(Literal::nat(n, sig.ln_begin().unwrap())), r_brace)
|
||||
obj.subscr(
|
||||
Expr::Literal(Literal::nat(n, sig.ln_begin().unwrap())),
|
||||
r_brace,
|
||||
)
|
||||
}
|
||||
BufIndex::Record(attr) => obj.attr(attr.clone()),
|
||||
};
|
||||
|
@ -1096,7 +1102,7 @@ impl Desugarer {
|
|||
}
|
||||
// x.0 => x.__Tuple_getitem__(0)
|
||||
Accessor::TupleAttr(tattr) => {
|
||||
let args = Args::pos_only(vec![PosArg::new(Expr::Lit(tattr.index))], None);
|
||||
let args = Args::pos_only(vec![PosArg::new(Expr::Literal(tattr.index))], None);
|
||||
let line = tattr.obj.ln_begin().unwrap();
|
||||
let call = Call::new(
|
||||
Self::rec_desugar_acc(*tattr.obj),
|
||||
|
|
|
@ -719,7 +719,7 @@ impl Parser {
|
|||
Args::new(vec![], Some(pos_args), vec![], None)
|
||||
}
|
||||
PosOrKwArg::Pos(PosArg {
|
||||
expr: Expr::TypeAsc(TypeAscription { expr, op, t_spec }),
|
||||
expr: Expr::TypeAscription(TypeAscription { expr, op, t_spec }),
|
||||
}) if matches!(expr.as_ref(), Expr::UnaryOp(unary) if unary.op.is(PreStar)) => {
|
||||
let Expr::UnaryOp(unary) = *expr else { unreachable!() };
|
||||
let var_args = PosArg::new(unary.deconstruct().1.type_asc_expr(op, t_spec));
|
||||
|
@ -789,7 +789,7 @@ impl Parser {
|
|||
args.set_var_args(PosArg::new(unary.deconstruct().1));
|
||||
}
|
||||
PosOrKwArg::Pos(PosArg {
|
||||
expr: Expr::TypeAsc(TypeAscription { expr, op, t_spec }),
|
||||
expr: Expr::TypeAscription(TypeAscription { expr, op, t_spec }),
|
||||
}) if matches!(expr.as_ref(), Expr::UnaryOp(unary) if unary.op.is(PreStar)) =>
|
||||
{
|
||||
let Expr::UnaryOp(unary) = *expr else { unreachable!() };
|
||||
|
@ -909,7 +909,7 @@ impl Parser {
|
|||
self.skip();
|
||||
let (kw, t_spec) = match expr {
|
||||
Expr::Accessor(Accessor::Ident(n)) => (n.name.into_token(), None),
|
||||
Expr::TypeAsc(tasc) => {
|
||||
Expr::TypeAscription(tasc) => {
|
||||
if let Expr::Accessor(Accessor::Ident(n)) = *tasc.expr {
|
||||
let t_spec = TypeSpecWithOp::new(tasc.op, tasc.t_spec);
|
||||
(n.name.into_token(), Some(t_spec))
|
||||
|
@ -1010,8 +1010,8 @@ impl Parser {
|
|||
.map_err(|_| self.stack_dec(fn_name!()))?;
|
||||
let first = match first {
|
||||
Expr::Def(def) => ClassAttr::Def(def),
|
||||
Expr::TypeAsc(tasc) => ClassAttr::Decl(tasc),
|
||||
Expr::Lit(lit) if lit.is_doc_comment() => ClassAttr::Doc(lit),
|
||||
Expr::TypeAscription(tasc) => ClassAttr::Decl(tasc),
|
||||
Expr::Literal(lit) if lit.is_doc_comment() => ClassAttr::Doc(lit),
|
||||
_ => {
|
||||
// self.restore();
|
||||
let err = self.skip_and_throw_syntax_err(caused_by!());
|
||||
|
@ -1040,7 +1040,7 @@ impl Parser {
|
|||
Expr::Def(def) => {
|
||||
attrs.push(ClassAttr::Def(def));
|
||||
}
|
||||
Expr::TypeAsc(tasc) => {
|
||||
Expr::TypeAscription(tasc) => {
|
||||
attrs.push(ClassAttr::Decl(tasc));
|
||||
}
|
||||
other => {
|
||||
|
@ -1597,7 +1597,7 @@ impl Parser {
|
|||
let first_elem = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
|
||||
let (keyword, t_spec) = match first_elem {
|
||||
Expr::Accessor(Accessor::Ident(ident)) => (ident.name.into_token(), None),
|
||||
Expr::TypeAsc(tasc) => {
|
||||
Expr::TypeAscription(tasc) => {
|
||||
if let Expr::Accessor(Accessor::Ident(ident)) = *tasc.expr {
|
||||
(
|
||||
ident.name.into_token(),
|
||||
|
@ -1658,7 +1658,7 @@ impl Parser {
|
|||
}
|
||||
}
|
||||
debug_exit_info!(self);
|
||||
Ok(Expr::Lit(lit))
|
||||
Ok(Expr::Literal(lit))
|
||||
}
|
||||
Some(t) if t.is(StrInterpLeft) => {
|
||||
let str_interp = self
|
||||
|
@ -2370,7 +2370,7 @@ impl Parser {
|
|||
Args::new(vec![], var_args, vec![], None)
|
||||
}
|
||||
PosOrKwArg::Pos(PosArg {
|
||||
expr: Expr::TypeAsc(TypeAscription { expr, op, t_spec }),
|
||||
expr: Expr::TypeAscription(TypeAscription { expr, op, t_spec }),
|
||||
}) if matches!(expr.as_ref(), Expr::UnaryOp(unary) if unary.op.is(PreStar)) => {
|
||||
let Expr::UnaryOp(unary) = *expr else { unreachable!() };
|
||||
let expr = unary.deconstruct().1;
|
||||
|
@ -2405,7 +2405,7 @@ impl Parser {
|
|||
Expr::UnaryOp(unary) if unary.op.is(PreStar) => {
|
||||
args.set_var_args(PosArg::new(unary.deconstruct().1));
|
||||
}
|
||||
Expr::TypeAsc(TypeAscription { expr, op, t_spec }) if matches!(expr.as_ref(), Expr::UnaryOp(unary) if unary.op.is(PreStar)) =>
|
||||
Expr::TypeAscription(TypeAscription { expr, op, t_spec }) if matches!(expr.as_ref(), Expr::UnaryOp(unary) if unary.op.is(PreStar)) =>
|
||||
{
|
||||
let Expr::UnaryOp(unary) = *expr else { unreachable!() };
|
||||
let expr = unary.deconstruct().1;
|
||||
|
@ -2473,7 +2473,7 @@ impl Parser {
|
|||
let mut left = self.lpop();
|
||||
left.content = Str::from(left.content.trim_end_matches("\\{").to_string() + "\"");
|
||||
left.kind = StrLit;
|
||||
let mut expr = Expr::Lit(Literal::from(left));
|
||||
let mut expr = Expr::Literal(Literal::from(left));
|
||||
loop {
|
||||
match self.peek() {
|
||||
Some(l) if l.is(StrInterpRight) => {
|
||||
|
@ -2481,7 +2481,7 @@ impl Parser {
|
|||
right.content =
|
||||
Str::from(format!("\"{}", right.content.trim_start_matches('}')));
|
||||
right.kind = StrLit;
|
||||
let right = Expr::Lit(Literal::from(right));
|
||||
let right = Expr::Literal(Literal::from(right));
|
||||
let op = Token::new(
|
||||
Plus,
|
||||
"+",
|
||||
|
@ -2519,7 +2519,7 @@ impl Parser {
|
|||
mid.content.trim_start_matches('}').trim_end_matches("\\{")
|
||||
));
|
||||
mid.kind = StrLit;
|
||||
let mid = Expr::Lit(Literal::from(mid));
|
||||
let mid = Expr::Literal(Literal::from(mid));
|
||||
let op = Token::new(
|
||||
Plus,
|
||||
"+",
|
||||
|
|
|
@ -3,14 +3,14 @@ use erg_common::traits::{Locational, Stream};
|
|||
|
||||
use crate::ast::*;
|
||||
use crate::error::ParseError;
|
||||
use crate::token::TokenKind;
|
||||
use crate::token::{Token, TokenKind};
|
||||
use crate::Parser;
|
||||
|
||||
// The APIs defined below are also used by `ASTLowerer` to interpret expressions as types.
|
||||
impl Parser {
|
||||
pub fn validate_const_expr(expr: Expr) -> Result<ConstExpr, ParseError> {
|
||||
match expr {
|
||||
Expr::Lit(l) => Ok(ConstExpr::Lit(l)),
|
||||
Expr::Literal(l) => Ok(ConstExpr::Lit(l)),
|
||||
Expr::Accessor(Accessor::Ident(local)) => {
|
||||
Ok(ConstExpr::Accessor(ConstAccessor::Local(local)))
|
||||
}
|
||||
|
@ -399,7 +399,7 @@ impl Parser {
|
|||
Err(err)
|
||||
}
|
||||
}
|
||||
Expr::Lit(lit) => {
|
||||
Expr::Literal(lit) => {
|
||||
let mut err = ParseError::simple_syntax_error(line!() as usize, lit.loc());
|
||||
if lit.is(TokenKind::NoneLit) {
|
||||
err.set_hint("you mean: `NoneType`?");
|
||||
|
@ -412,4 +412,77 @@ impl Parser {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn simple_type_spec_to_ident(simple: SimpleTypeSpec) -> Result<Identifier, ParseError> {
|
||||
Ok(simple.ident)
|
||||
}
|
||||
|
||||
fn simple_type_spec_to_call(simple: SimpleTypeSpec) -> Result<Call, ParseError> {
|
||||
let (pos_args_, var_args_, kw_args_, paren) = simple.args.deconstruct();
|
||||
let pos_args = pos_args_
|
||||
.into_iter()
|
||||
.map(|arg| PosArg::new(arg.expr.downcast()))
|
||||
.collect::<Vec<_>>();
|
||||
let var_args = var_args_.map(|arg| PosArg::new(arg.expr.downcast()));
|
||||
let kw_args = kw_args_
|
||||
.into_iter()
|
||||
.map(|arg| KwArg::new(arg.keyword, None, arg.expr.downcast()))
|
||||
.collect::<Vec<_>>();
|
||||
let args = Args::new(pos_args, var_args, kw_args, paren);
|
||||
let call = Call::new(simple.ident.into(), None, args);
|
||||
Ok(call)
|
||||
}
|
||||
|
||||
fn predecl_type_spec_to_expr(predecl: PreDeclTypeSpec) -> Result<Expr, ParseError> {
|
||||
match predecl {
|
||||
PreDeclTypeSpec::Simple(simple) if simple.args.is_empty() => {
|
||||
Ok(Self::simple_type_spec_to_ident(simple)?.into())
|
||||
}
|
||||
PreDeclTypeSpec::Simple(simple) => Ok(Self::simple_type_spec_to_call(simple)?.into()),
|
||||
PreDeclTypeSpec::Attr { namespace, t } => {
|
||||
let ident = Self::simple_type_spec_to_ident(t)?;
|
||||
Ok(namespace.attr_expr(ident))
|
||||
}
|
||||
other => Err(ParseError::feature_error(
|
||||
line!() as usize,
|
||||
other.loc(),
|
||||
"compound predecl type spec to call conversion",
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn type_spec_to_expr(t_spec: TypeSpec) -> Result<Expr, ParseError> {
|
||||
match t_spec {
|
||||
TypeSpec::PreDeclTy(predecl) => Self::predecl_type_spec_to_expr(predecl),
|
||||
TypeSpec::Or(lhs, rhs) => {
|
||||
let lhs = Self::type_spec_to_expr(*lhs)?;
|
||||
let rhs = Self::type_spec_to_expr(*rhs)?;
|
||||
let op = Token::new(
|
||||
TokenKind::OrOp,
|
||||
"or",
|
||||
lhs.ln_begin().unwrap(),
|
||||
lhs.col_end().unwrap(),
|
||||
);
|
||||
let bin = BinOp::new(op, lhs, rhs);
|
||||
Ok(Expr::BinOp(bin))
|
||||
}
|
||||
TypeSpec::And(lhs, rhs) => {
|
||||
let lhs = Self::type_spec_to_expr(*lhs)?;
|
||||
let rhs = Self::type_spec_to_expr(*rhs)?;
|
||||
let op = Token::new(
|
||||
TokenKind::AndOp,
|
||||
"and",
|
||||
lhs.ln_begin().unwrap(),
|
||||
lhs.col_end().unwrap(),
|
||||
);
|
||||
let bin = BinOp::new(op, lhs, rhs);
|
||||
Ok(Expr::BinOp(bin))
|
||||
}
|
||||
other => Err(ParseError::feature_error(
|
||||
line!() as usize,
|
||||
other.loc(),
|
||||
"compound type spec to expr conversion",
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue