Impl Tuple type checking & code generating

This commit is contained in:
Shunsuke Shibayama 2022-08-29 12:41:14 +09:00
parent 11e89576e1
commit 451d94d31b
5 changed files with 94 additions and 6 deletions

View file

@ -27,7 +27,7 @@ use crate::compile::{AccessKind, Name, StoreLoadKind};
use crate::error::{CompileError, CompileErrors, CompileResult};
use crate::eval::eval_lit;
use crate::hir::{
Accessor, Args, Array, Block, DefBody, Expr, Signature, SubrSignature, VarSignature, HIR,
Accessor, Args, Array, Block, DefBody, Expr, Signature, SubrSignature, Tuple, VarSignature, HIR,
};
use AccessKind::*;
@ -1216,6 +1216,23 @@ impl CodeGenerator {
}
other => todo!("{other}"),
},
// TODO: tuple comprehension
// TODO: tuples can be const
Expr::Tuple(tup) => match tup {
Tuple::Normal(mut tup) => {
let len = tup.elems.len();
while let Some(arg) = tup.elems.try_remove_pos(0) {
self.codegen_expr(arg.expr);
}
self.write_instr(BUILD_TUPLE);
self.write_arg(len as u8);
if len == 0 {
self.stack_inc();
} else {
self.stack_dec_n(len - 1);
}
}
},
Expr::Record(rec) => {
let attrs_len = rec.attrs.len();
// importing namedtuple

View file

@ -399,6 +399,14 @@ impl Context {
}
_ => todo!(),
},
hir::Expr::Tuple(tuple) => match tuple {
hir::Tuple::Normal(tup) => {
for elem in tup.elems.pos_args.iter_mut() {
self.deref_expr_t(&mut elem.expr)?;
}
Ok(())
}
},
hir::Expr::Dict(_dict) => {
todo!()
}

View file

@ -14,7 +14,7 @@ use erg_common::{
use erg_parser::ast::{fmt_lines, DefId, Identifier, Params, VarPattern};
use erg_parser::token::{Token, TokenKind};
use erg_type::constructors::array;
use erg_type::constructors::{array, tuple};
use erg_type::typaram::TyParam;
use erg_type::value::ValueObj;
use erg_type::{impl_t, impl_t_for_enum, HasType, Type};
@ -545,6 +545,42 @@ impl_display_for_enum!(Array; Normal, Comprehension, WithLength);
impl_locational_for_enum!(Array; Normal, Comprehension, WithLength);
impl_t_for_enum!(Array; Normal, Comprehension, WithLength);
#[derive(Debug, Clone)]
pub struct NormalTuple {
pub elems: Args,
t: Type,
}
impl NestedDisplay for NormalTuple {
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
writeln!(f, "(")?;
self.elems.fmt_nest(f, level + 1)?;
write!(f, "\n{})(: {})", " ".repeat(level), self.t)
}
}
impl_display_from_nested!(NormalTuple);
impl_locational!(NormalTuple, elems);
impl_t!(NormalTuple);
impl NormalTuple {
pub fn new(elems: Args) -> Self {
let t = tuple(elems.pos_args.iter().map(|a| a.expr.t()).collect());
Self { elems, t }
}
}
#[derive(Debug, Clone)]
pub enum Tuple {
Normal(NormalTuple),
// Comprehension(TupleComprehension),
}
impl_nested_display_for_enum!(Tuple; Normal);
impl_display_for_enum!(Tuple; Normal);
impl_locational_for_enum!(Tuple; Normal);
impl_t_for_enum!(Tuple; Normal);
#[derive(Debug, Clone)]
pub struct NormalDict {
pub l_brace: Token,
@ -1174,6 +1210,7 @@ pub enum Expr {
Lit(Literal),
Accessor(Accessor),
Array(Array),
Tuple(Tuple),
// Set(Set),
Dict(Dict),
Record(Record),
@ -1185,10 +1222,10 @@ pub enum Expr {
Def(Def),
}
impl_nested_display_for_chunk_enum!(Expr; Lit, Accessor, Array, Dict, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def);
impl_nested_display_for_chunk_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def);
impl_display_from_nested!(Expr);
impl_locational_for_enum!(Expr; Lit, Accessor, Array, Dict, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def);
impl_t_for_enum!(Expr; Lit, Accessor, Array, Dict, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def);
impl_locational_for_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def);
impl_t_for_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def);
impl Expr {
pub fn receiver_t(&self) -> Option<&Type> {

View file

@ -200,6 +200,24 @@ impl ASTLowerer {
}
}
fn lower_tuple(&mut self, tuple: ast::Tuple) -> LowerResult<hir::Tuple> {
log!("[DEBUG] entered {}({tuple})", fn_name!());
match tuple {
ast::Tuple::Normal(tup) => Ok(hir::Tuple::Normal(self.lower_normal_tuple(tup)?)),
}
}
fn lower_normal_tuple(&mut self, tuple: ast::NormalTuple) -> LowerResult<hir::NormalTuple> {
log!("[DEBUG] entered {}({tuple})", fn_name!());
let mut new_tuple = vec![];
let (elems, _) = tuple.elems.into_iters();
for elem in elems {
let elem = self.lower_expr(elem.expr)?;
new_tuple.push(elem);
}
Ok(hir::NormalTuple::new(hir::Args::from(new_tuple)))
}
fn lower_record(&mut self, record: ast::Record) -> LowerResult<hir::Record> {
log!("[DEBUG] entered {}({record})", fn_name!());
let mut hir_record =
@ -477,6 +495,7 @@ impl ASTLowerer {
match expr {
ast::Expr::Lit(lit) => Ok(hir::Expr::Lit(hir::Literal::from(lit.token))),
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)?)),
ast::Expr::Accessor(acc) => Ok(hir::Expr::Accessor(self.lower_acc(acc)?)),
ast::Expr::BinOp(bin) => Ok(hir::Expr::BinOp(self.lower_bin(bin)?)),

View file

@ -11,7 +11,7 @@ use Visibility::*;
use erg_type::{ArgsOwnership, HasType, Ownership};
use crate::error::{OwnershipError, OwnershipErrors, OwnershipResult};
use crate::hir::{self, Accessor, Array, Block, Def, Expr, Signature, HIR};
use crate::hir::{self, Accessor, Array, Block, Def, Expr, Signature, Tuple, HIR};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum WrapperKind {
@ -186,6 +186,13 @@ impl OwnershipChecker {
}
_ => todo!(),
},
Expr::Tuple(tuple) => match tuple {
Tuple::Normal(arr) => {
for a in arr.elems.pos_args.iter() {
self.check_expr(&a.expr, ownership);
}
}
},
Expr::Dict(dict) => match dict {
hir::Dict::Normal(dic) => {
for a in dic.attrs.kw_args.iter() {