Enhance: Parser::validate_const_expr

This commit is contained in:
Shunsuke Shibayama 2022-12-26 22:36:39 +09:00
parent 68e0622efb
commit d393ace9a6
3 changed files with 156 additions and 11 deletions

View file

@ -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)?;

View file

@ -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 {

View file

@ -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,