mirror of
https://github.com/erg-lang/erg.git
synced 2025-10-02 05:31:11 +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 => {
|
other => {
|
||||||
log!(err "todo: {other}");
|
log!(err "todo: {other}");
|
||||||
return unreachable_error!(LowerErrors, LowerError, self.ctx);
|
return unreachable_error!(LowerErrors, LowerError, self.ctx);
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
let arg_t = call.args.get(0).unwrap().ref_t();
|
let arg_t = call.args.get(0).unwrap().ref_t();
|
||||||
self.ctx.sub_unify(arg_t, &ret_t, call.loc(), None)?;
|
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)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct ConstArray {
|
pub struct ConstArray {
|
||||||
pub l_sqbr: Token,
|
pub l_sqbr: Token,
|
||||||
|
@ -1389,7 +1388,7 @@ impl NestedDisplay for ConstArray {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_display_from_nested!(ConstArray);
|
impl_display_from_nested!(ConstArray);
|
||||||
impl_locational!(ConstArray, l_sqbr, r_sqbr);
|
impl_locational!(ConstArray, l_sqbr, elems, r_sqbr);
|
||||||
|
|
||||||
impl ConstArray {
|
impl ConstArray {
|
||||||
pub fn new(l_sqbr: Token, r_sqbr: Token, elems: ConstArgs, guard: Option<ConstExpr>) -> Self {
|
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)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct ConstDict {
|
pub struct ConstDict {
|
||||||
l_brace: Token,
|
l_brace: Token,
|
||||||
r_brace: Token,
|
r_brace: Token,
|
||||||
pub attrs: ConstArgs,
|
pub kvs: Vec<ConstKeyValue>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NestedDisplay for ConstDict {
|
impl NestedDisplay for ConstDict {
|
||||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
|
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_locational!(ConstDict, l_brace, r_brace);
|
||||||
|
|
||||||
impl ConstDict {
|
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 {
|
Self {
|
||||||
l_brace,
|
l_brace,
|
||||||
r_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)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct ConstBinOp {
|
pub struct ConstBinOp {
|
||||||
pub op: Token,
|
pub op: Token,
|
||||||
|
@ -1542,15 +1620,16 @@ pub enum ConstExpr {
|
||||||
Accessor(ConstAccessor),
|
Accessor(ConstAccessor),
|
||||||
App(ConstApp),
|
App(ConstApp),
|
||||||
Array(ConstArray),
|
Array(ConstArray),
|
||||||
Set(Set),
|
Set(ConstSet),
|
||||||
Dict(ConstDict),
|
Dict(ConstDict),
|
||||||
|
Tuple(ConstTuple),
|
||||||
BinOp(ConstBinOp),
|
BinOp(ConstBinOp),
|
||||||
UnaryOp(ConstUnaryOp),
|
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_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 {
|
impl ConstExpr {
|
||||||
pub fn need_to_be_closed(&self) -> bool {
|
pub fn need_to_be_closed(&self) -> bool {
|
||||||
|
|
|
@ -3086,9 +3086,57 @@ impl Parser {
|
||||||
other => Err(ParseError::feature_error(
|
other => Err(ParseError::feature_error(
|
||||||
line!() as usize,
|
line!() as usize,
|
||||||
other.loc(),
|
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) => {
|
Expr::BinOp(bin) => {
|
||||||
let mut args = bin.args.into_iter();
|
let mut args = bin.args.into_iter();
|
||||||
let lhs = Self::validate_const_expr(*args.next().unwrap())?;
|
let lhs = Self::validate_const_expr(*args.next().unwrap())?;
|
||||||
|
@ -3100,6 +3148,24 @@ impl Parser {
|
||||||
let arg = Self::validate_const_expr(*args.next().unwrap())?;
|
let arg = Self::validate_const_expr(*args.next().unwrap())?;
|
||||||
Ok(ConstExpr::UnaryOp(ConstUnaryOp::new(unary.op, arg)))
|
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,
|
// TODO: App, Record,
|
||||||
other => Err(ParseError::syntax_error(
|
other => Err(ParseError::syntax_error(
|
||||||
line!() as usize,
|
line!() as usize,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue