mirror of
https://github.com/erg-lang/erg.git
synced 2025-10-02 21:44:34 +00:00
Enhance: Parser::validate_const_expr
This commit is contained in:
parent
68e0622efb
commit
d393ace9a6
3 changed files with 156 additions and 11 deletions
|
@ -901,7 +901,7 @@ impl ASTLowerer {
|
|||
other => {
|
||||
log!(err "todo: {other}");
|
||||
return unreachable_error!(LowerErrors, LowerError, self.ctx);
|
||||
},
|
||||
}
|
||||
};
|
||||
let arg_t = call.args.get(0).unwrap().ref_t();
|
||||
self.ctx.sub_unify(arg_t, &ret_t, call.loc(), None)?;
|
||||
|
|
|
@ -1369,7 +1369,6 @@ impl ConstAccessor {
|
|||
}
|
||||
}
|
||||
|
||||
/// DictはキーつきArray(型としては別物)
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct ConstArray {
|
||||
pub l_sqbr: Token,
|
||||
|
@ -1389,7 +1388,7 @@ impl NestedDisplay for ConstArray {
|
|||
}
|
||||
|
||||
impl_display_from_nested!(ConstArray);
|
||||
impl_locational!(ConstArray, l_sqbr, r_sqbr);
|
||||
impl_locational!(ConstArray, l_sqbr, elems, r_sqbr);
|
||||
|
||||
impl ConstArray {
|
||||
pub fn new(l_sqbr: Token, r_sqbr: Token, elems: ConstArgs, guard: Option<ConstExpr>) -> Self {
|
||||
|
@ -1410,16 +1409,71 @@ impl ConstArray {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct ConstSet {
|
||||
pub l_brace: Token,
|
||||
pub r_brace: Token,
|
||||
pub elems: ConstArgs,
|
||||
}
|
||||
|
||||
impl NestedDisplay for ConstSet {
|
||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
|
||||
write!(f, "{{{}}}", self.elems)
|
||||
}
|
||||
}
|
||||
|
||||
impl_display_from_nested!(ConstSet);
|
||||
impl_locational!(ConstSet, l_brace, elems, r_brace);
|
||||
|
||||
impl ConstSet {
|
||||
pub fn new(l_brace: Token, r_brace: Token, elems: ConstArgs) -> Self {
|
||||
Self {
|
||||
l_brace,
|
||||
r_brace,
|
||||
elems,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn downcast(self) -> Set {
|
||||
Set::Normal(NormalSet::new(
|
||||
self.l_brace,
|
||||
self.r_brace,
|
||||
self.elems.downcast(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct ConstKeyValue {
|
||||
pub key: ConstExpr,
|
||||
pub value: ConstExpr,
|
||||
}
|
||||
|
||||
impl NestedDisplay for ConstKeyValue {
|
||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
|
||||
write!(f, "{}: {}", self.key, self.value)
|
||||
}
|
||||
}
|
||||
|
||||
impl_display_from_nested!(ConstKeyValue);
|
||||
impl_locational!(ConstKeyValue, key, value);
|
||||
|
||||
impl ConstKeyValue {
|
||||
pub const fn new(key: ConstExpr, value: ConstExpr) -> Self {
|
||||
Self { key, value }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct ConstDict {
|
||||
l_brace: Token,
|
||||
r_brace: Token,
|
||||
pub attrs: ConstArgs,
|
||||
pub kvs: Vec<ConstKeyValue>,
|
||||
}
|
||||
|
||||
impl NestedDisplay for ConstDict {
|
||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
|
||||
write!(f, "{{{}}}", self.attrs)
|
||||
write!(f, "{{{}}}", fmt_vec(&self.kvs))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1427,11 +1481,11 @@ impl_display_from_nested!(ConstDict);
|
|||
impl_locational!(ConstDict, l_brace, r_brace);
|
||||
|
||||
impl ConstDict {
|
||||
pub const fn new(l_brace: Token, r_brace: Token, attrs: ConstArgs) -> Self {
|
||||
pub const fn new(l_brace: Token, r_brace: Token, kvs: Vec<ConstKeyValue>) -> Self {
|
||||
Self {
|
||||
l_brace,
|
||||
r_brace,
|
||||
attrs,
|
||||
kvs,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1440,6 +1494,30 @@ impl ConstDict {
|
|||
}*/
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct ConstTuple {
|
||||
pub elems: ConstArgs,
|
||||
}
|
||||
|
||||
impl NestedDisplay for ConstTuple {
|
||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
|
||||
write!(f, "({})", self.elems)
|
||||
}
|
||||
}
|
||||
|
||||
impl_display_from_nested!(ConstTuple);
|
||||
impl_locational!(ConstTuple, elems);
|
||||
|
||||
impl ConstTuple {
|
||||
pub const fn new(elems: ConstArgs) -> Self {
|
||||
Self { elems }
|
||||
}
|
||||
|
||||
pub fn downcast(self) -> Tuple {
|
||||
Tuple::Normal(NormalTuple::new(self.elems.downcast()))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct ConstBinOp {
|
||||
pub op: Token,
|
||||
|
@ -1542,15 +1620,16 @@ pub enum ConstExpr {
|
|||
Accessor(ConstAccessor),
|
||||
App(ConstApp),
|
||||
Array(ConstArray),
|
||||
Set(Set),
|
||||
Set(ConstSet),
|
||||
Dict(ConstDict),
|
||||
Tuple(ConstTuple),
|
||||
BinOp(ConstBinOp),
|
||||
UnaryOp(ConstUnaryOp),
|
||||
}
|
||||
|
||||
impl_nested_display_for_chunk_enum!(ConstExpr; Lit, Accessor, App, Array, Dict, BinOp, UnaryOp, Erased, Set);
|
||||
impl_nested_display_for_chunk_enum!(ConstExpr; Lit, Accessor, App, Array, Set, Dict, Tuple, BinOp, UnaryOp, Erased, Set);
|
||||
impl_display_from_nested!(ConstExpr);
|
||||
impl_locational_for_enum!(ConstExpr; Lit, Accessor, App, Array, Dict, BinOp, UnaryOp, Erased, Set);
|
||||
impl_locational_for_enum!(ConstExpr; Lit, Accessor, App, Array, Set Dict, Tuple, BinOp, UnaryOp, Erased, Set);
|
||||
|
||||
impl ConstExpr {
|
||||
pub fn need_to_be_closed(&self) -> bool {
|
||||
|
|
|
@ -3086,9 +3086,57 @@ impl Parser {
|
|||
other => Err(ParseError::feature_error(
|
||||
line!() as usize,
|
||||
other.loc(),
|
||||
"???",
|
||||
"const array comprehension",
|
||||
)),
|
||||
},
|
||||
Expr::Set(set) => match set {
|
||||
Set::Normal(set) => {
|
||||
let (elems, _, _) = set.elems.deconstruct();
|
||||
let mut const_elems = vec![];
|
||||
for elem in elems.into_iter() {
|
||||
let const_expr = Self::validate_const_expr(elem.expr)?;
|
||||
const_elems.push(ConstPosArg::new(const_expr));
|
||||
}
|
||||
let elems = ConstArgs::new(const_elems, vec![], None);
|
||||
let const_set = ConstSet::new(set.l_brace, set.r_brace, elems);
|
||||
Ok(ConstExpr::Set(const_set))
|
||||
}
|
||||
other => Err(ParseError::feature_error(
|
||||
line!() as usize,
|
||||
other.loc(),
|
||||
"const set comprehension",
|
||||
)),
|
||||
},
|
||||
Expr::Dict(dict) => match dict {
|
||||
Dict::Normal(dict) => {
|
||||
let mut const_kvs = vec![];
|
||||
for kv in dict.kvs.into_iter() {
|
||||
let key = Self::validate_const_expr(kv.key)?;
|
||||
let value = Self::validate_const_expr(kv.value)?;
|
||||
const_kvs.push(ConstKeyValue::new(key, value));
|
||||
}
|
||||
let const_dict = ConstDict::new(dict.l_brace, dict.r_brace, const_kvs);
|
||||
Ok(ConstExpr::Dict(const_dict))
|
||||
}
|
||||
other => Err(ParseError::feature_error(
|
||||
line!() as usize,
|
||||
other.loc(),
|
||||
"const dict comprehension",
|
||||
)),
|
||||
},
|
||||
Expr::Tuple(tuple) => match tuple {
|
||||
Tuple::Normal(tup) => {
|
||||
let (elems, _, paren) = tup.elems.deconstruct();
|
||||
let mut const_elems = vec![];
|
||||
for elem in elems.into_iter() {
|
||||
let const_expr = Self::validate_const_expr(elem.expr)?;
|
||||
const_elems.push(ConstPosArg::new(const_expr));
|
||||
}
|
||||
let elems = ConstArgs::new(const_elems, vec![], paren);
|
||||
let const_tup = ConstTuple::new(elems);
|
||||
Ok(ConstExpr::Tuple(const_tup))
|
||||
}
|
||||
},
|
||||
Expr::BinOp(bin) => {
|
||||
let mut args = bin.args.into_iter();
|
||||
let lhs = Self::validate_const_expr(*args.next().unwrap())?;
|
||||
|
@ -3100,6 +3148,24 @@ impl Parser {
|
|||
let arg = Self::validate_const_expr(*args.next().unwrap())?;
|
||||
Ok(ConstExpr::UnaryOp(ConstUnaryOp::new(unary.op, arg)))
|
||||
}
|
||||
Expr::Call(call) => {
|
||||
let obj = Self::validate_const_expr(*call.obj)?;
|
||||
let ConstExpr::Accessor(acc) = obj else {
|
||||
return Err(ParseError::feature_error(
|
||||
line!() as usize,
|
||||
obj.loc(),
|
||||
"complex const function call",
|
||||
));
|
||||
};
|
||||
let (pos_args, _, paren) = call.args.deconstruct();
|
||||
let mut const_pos_args = vec![];
|
||||
for elem in pos_args.into_iter() {
|
||||
let const_expr = Self::validate_const_expr(elem.expr)?;
|
||||
const_pos_args.push(ConstPosArg::new(const_expr));
|
||||
}
|
||||
let args = ConstArgs::new(const_pos_args, vec![], paren);
|
||||
Ok(ConstExpr::App(ConstApp::new(acc, args)))
|
||||
}
|
||||
// TODO: App, Record,
|
||||
other => Err(ParseError::syntax_error(
|
||||
line!() as usize,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue