diff --git a/compiler/erg_common/opcode.rs b/compiler/erg_common/opcode.rs index ccd97fc1..5f3e522c 100644 --- a/compiler/erg_common/opcode.rs +++ b/compiler/erg_common/opcode.rs @@ -59,6 +59,7 @@ pub enum CommonOpcode { // POP_JUMP_IF_FALSE = 114, // POP_JUMP_IF_TRUE = 115, LOAD_GLOBAL = 116, + CONTAINS_OP = 118, LOAD_FAST = 124, STORE_FAST = 125, DELETE_FAST = 126, @@ -123,6 +124,7 @@ impl TryFrom for CommonOpcode { // 114 => POP_JUMP_IF_FALSE, // 115 => POP_JUMP_IF_TRUE, 116 => LOAD_GLOBAL, + 118 => CONTAINS_OP, 124 => LOAD_FAST, 125 => STORE_FAST, 126 => DELETE_FAST, diff --git a/compiler/erg_compiler/codegen.rs b/compiler/erg_compiler/codegen.rs index b252300a..96c67344 100644 --- a/compiler/erg_compiler/codegen.rs +++ b/compiler/erg_compiler/codegen.rs @@ -1677,19 +1677,20 @@ impl PyCodeGenerator { #[allow(clippy::single_match)] match t_spec { TypeSpec::Enum(enm) => { - let (mut elems, ..) = enm.deconstruct(); - if elems.len() != 1 { - todo!() - } - let ConstExpr::Lit(lit) = elems.remove(0).expr else { - todo!() - }; - let value = { - let t = type_from_token_kind(lit.token.kind); - ValueObj::from_str(t, lit.token.content).unwrap() - }; - self.emit_load_const(value); - self.emit_compare_op(CompareOp::EQ); + let elems = enm + .deconstruct() + .0 + .into_iter() + .map(|elem| { + let ConstExpr::Lit(lit) = elem.expr else { todo!() }; + let t = type_from_token_kind(lit.token.kind); + ValueObj::from_str(t, lit.token.content).unwrap() + }) + .collect::>(); + self.emit_load_const(elems); + self.write_instr(CONTAINS_OP); + self.write_arg(0); + self.stack_dec(); pop_jump_points.push(self.lasti()); // in 3.11, POP_JUMP_IF_FALSE is replaced with POP_JUMP_FORWARD_IF_FALSE // but the numbers are the same, only the way the jumping points are calculated is different. @@ -1697,8 +1698,14 @@ impl PyCodeGenerator { self.write_arg(0); self.stack_dec(); } + /*TypeSpec::Interval { op, lhs, rhs } => { + let binop = BinOp::new(op, lhs.downcast(), rhs.downcast(), VarInfo::default()); + self.emit_binop(binop); + }*/ // TODO: - _ => {} + other => { + log!(err "{other}") + } } } diff --git a/compiler/erg_parser/ast.rs b/compiler/erg_parser/ast.rs index 6d2a87e1..e8b43328 100644 --- a/compiler/erg_parser/ast.rs +++ b/compiler/erg_parser/ast.rs @@ -1159,6 +1159,10 @@ impl ConstLocal { pub const fn inspect(&self) -> &Str { &self.symbol.content } + + pub fn downcast(self) -> Identifier { + Identifier::new(None, VarName::new(self.symbol)) + } } /// type variables @@ -1190,6 +1194,10 @@ impl ConstAttribute { name, } } + + pub fn downcast(self) -> Attribute { + Attribute::new(self.obj.downcast(), self.name.downcast()) + } } #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -1277,6 +1285,16 @@ impl ConstAccessor { pub fn subscr(obj: ConstExpr, index: ConstExpr) -> Self { Self::Subscr(ConstSubscript::new(obj, index)) } + + pub fn downcast(self) -> Accessor { + match self { + Self::Local(local) => Accessor::Ident(local.downcast()), + Self::Attr(attr) => Accessor::Attr(attr.downcast()), + // Self::TupleAttr(attr) => Accessor::TupleAttr(attr.downcast()), + // Self::Subscr(subscr) => Accessor::Subscr(subscr.downcast()), + _ => todo!(), + } + } } /// DictはキーつきArray(型としては別物) @@ -1310,6 +1328,14 @@ impl ConstArray { guard: guard.map(Box::new), } } + + pub fn downcast(self) -> Array { + Array::Normal(NormalArray::new( + self.l_sqbr, + self.r_sqbr, + self.elems.downcast(), + )) + } } #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -1336,6 +1362,10 @@ impl ConstDict { attrs, } } + + /*pub fn downcast(self) -> Dict { + Dict::Normal(NormalDict::new(self.l_brace, self.r_brace, self.attrs.downcast())) + }*/ } #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -1362,6 +1392,10 @@ impl ConstBinOp { rhs: Box::new(rhs), } } + + pub fn downcast(self) -> BinOp { + BinOp::new(self.op, self.lhs.downcast(), self.rhs.downcast()) + } } #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -1386,6 +1420,10 @@ impl ConstUnaryOp { expr: Box::new(expr), } } + + pub fn downcast(self) -> UnaryOp { + UnaryOp::new(self.op, self.expr.downcast()) + } } /// Application @@ -1417,6 +1455,10 @@ impl ConstApp { pub const fn new(acc: ConstAccessor, args: ConstArgs) -> Self { Self { acc, args } } + + pub fn downcast(self) -> Call { + Expr::Accessor(self.acc.downcast()).call(self.args.downcast()) + } } /// valid expression for an argument of polymorphic types @@ -1442,6 +1484,20 @@ impl ConstExpr { pub fn need_to_be_closed(&self) -> bool { matches!(self, Self::BinOp(_) | Self::UnaryOp(_)) } + + pub fn downcast(self) -> Expr { + match self { + Self::Lit(lit) => Expr::Lit(lit), + Self::Accessor(acc) => Expr::Accessor(acc.downcast()), + Self::App(app) => Expr::Call(app.downcast()), + Self::Array(arr) => Expr::Array(arr.downcast()), + // Self::Set(set) => Expr::Set(set.downcast()), + // Self::Dict(dict) => Expr::Dict(dict.downcast()), + Self::BinOp(binop) => Expr::BinOp(binop.downcast()), + Self::UnaryOp(unop) => Expr::UnaryOp(unop.downcast()), + _ => todo!(), + } + } } #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -1565,6 +1621,22 @@ impl ConstArgs { pub fn push_kw(&mut self, arg: ConstKwArg) { self.kw_args.push(arg); } + + pub fn downcast(self) -> Args { + let (pos_args, kw_args, paren) = self.deconstruct(); + Args::new( + pos_args + .into_iter() + .map(|arg| PosArg::new(arg.expr.downcast())) + .collect(), + kw_args + .into_iter() + // TODO t_spec + .map(|arg| KwArg::new(arg.keyword, None, arg.expr.downcast())) + .collect(), + paren, + ) + } } #[derive(Clone, Debug, PartialEq, Eq, Hash)]