This commit is contained in:
Shunsuke Shibayama 2022-12-09 19:46:59 +09:00
parent a395938413
commit 4ed278e75c
8 changed files with 80 additions and 37 deletions

View file

@ -1859,8 +1859,8 @@ impl PyCodeGenerator {
} }
// _: (Int, Str) // _: (Int, Str)
TypeSpec::Tuple(tup) => { TypeSpec::Tuple(tup) => {
let len = tup.len(); let len = tup.tys.len();
for (i, t_spec) in tup.into_iter().enumerate() { for (i, t_spec) in tup.tys.into_iter().enumerate() {
if i != 0 && i != len - 1 { if i != 0 && i != len - 1 {
self.dup_top(); self.dup_top();
} }

View file

@ -699,9 +699,9 @@ impl Context {
} }
Ok(set_t(elem_t, len)) Ok(set_t(elem_t, len))
} }
TypeSpec::Tuple(tys) => { TypeSpec::Tuple(tup) => {
let mut inst_tys = vec![]; let mut inst_tys = vec![];
for spec in tys { for spec in tup.tys.iter() {
inst_tys.push(self.instantiate_typespec( inst_tys.push(self.instantiate_typespec(
spec, spec,
opt_decl_t, opt_decl_t,

View file

@ -188,7 +188,11 @@ impl Context {
self.locals.insert(ident.name.clone(), vi); self.locals.insert(ident.name.clone(), vi);
return Ok(()); return Ok(());
} }
self.validate_var_sig_t(ident, sig.t_spec.as_ref(), body_t, Normal)?; let (var_t, errs) =
match self.validate_var_sig_t(ident, sig.t_spec.as_ref(), body_t, Normal) {
Ok(()) => (body_t.clone(), None),
Err(errs) => (Type::Failure, Some(errs)),
};
let muty = Mutability::from(&ident.inspect()[..]); let muty = Mutability::from(&ident.inspect()[..]);
let py_name = if let Some(vi) = self let py_name = if let Some(vi) = self
.decls .decls
@ -201,7 +205,7 @@ impl Context {
}; };
let vis = ident.vis(); let vis = ident.vis();
let vi = VarInfo::new( let vi = VarInfo::new(
body_t.clone(), var_t,
muty, muty,
vis, vis,
VarKind::Defined(id), VarKind::Defined(id),
@ -211,8 +215,12 @@ impl Context {
); );
log!(info "Registered {}::{}: {}", self.name, ident.name, vi); log!(info "Registered {}::{}: {}", self.name, ident.name, vi);
self.locals.insert(ident.name.clone(), vi); self.locals.insert(ident.name.clone(), vi);
if let Some(errs) = errs {
Err(errs)
} else {
Ok(()) Ok(())
} }
}
/// 宣言が既にある場合、opt_decl_tに宣言の型を渡す /// 宣言が既にある場合、opt_decl_tに宣言の型を渡す
fn assign_param( fn assign_param(

View file

@ -159,16 +159,7 @@ impl NestedDisplay for Args {
} }
} }
impl From<Vec<Expr>> for Args { // do not implement From<Vec<Expr>> to Args, because it will miss paren info (use `values`)
fn from(exprs: Vec<Expr>) -> Self {
Self {
pos_args: exprs.into_iter().map(PosArg::new).collect(),
var_args: None,
kw_args: Vec::new(),
paren: None,
}
}
}
impl_display_from_nested!(Args); impl_display_from_nested!(Args);
@ -183,6 +174,8 @@ impl Locational for Args {
self.pos_args.first().unwrap(), self.pos_args.first().unwrap(),
self.pos_args.last().unwrap(), self.pos_args.last().unwrap(),
) )
} else if let Some(va) = self.var_args.as_ref() {
va.loc()
} else { } else {
Location::Unknown Location::Unknown
} }
@ -206,6 +199,15 @@ impl Args {
} }
} }
pub fn values(exprs: Vec<Expr>, paren: Option<(Token, Token)>) -> Self {
Self::new(
exprs.into_iter().map(PosArg::new).collect(),
None,
vec![],
paren,
)
}
pub fn empty() -> Self { pub fn empty() -> Self {
Self::new(vec![], None, vec![], None) Self::new(vec![], None, vec![], None)
} }

View file

@ -364,7 +364,7 @@ impl ASTLowerer {
array.l_sqbr, array.l_sqbr,
array.r_sqbr, array.r_sqbr,
elem_t, elem_t,
hir::Args::from(new_array), hir::Args::values(new_array, None),
)) ))
} }
@ -428,12 +428,12 @@ impl ASTLowerer {
fn lower_normal_tuple(&mut self, tuple: ast::NormalTuple) -> LowerResult<hir::NormalTuple> { fn lower_normal_tuple(&mut self, tuple: ast::NormalTuple) -> LowerResult<hir::NormalTuple> {
log!(info "entered {}({tuple})", fn_name!()); log!(info "entered {}({tuple})", fn_name!());
let mut new_tuple = vec![]; let mut new_tuple = vec![];
let (elems, _) = tuple.elems.into_iters(); let (elems, .., paren) = tuple.elems.deconstruct();
for elem in elems { for elem in elems {
let elem = self.lower_expr(elem.expr)?; let elem = self.lower_expr(elem.expr)?;
new_tuple.push(elem); new_tuple.push(elem);
} }
Ok(hir::NormalTuple::new(hir::Args::from(new_tuple))) Ok(hir::NormalTuple::new(hir::Args::values(new_tuple, paren)))
} }
fn lower_record(&mut self, record: ast::Record) -> LowerResult<hir::Record> { fn lower_record(&mut self, record: ast::Record) -> LowerResult<hir::Record> {
@ -526,7 +526,7 @@ impl ASTLowerer {
} }
Ok(normal_set) Ok(normal_set)
*/ */
let elems = hir::Args::from(new_set); let elems = hir::Args::values(new_set, None);
// check if elem_t is Eq // check if elem_t is Eq
if let Err(errs) = self.ctx.sub_unify(&elem_t, &mono("Eq"), elems.loc(), None) { if let Err(errs) = self.ctx.sub_unify(&elem_t, &mono("Eq"), elems.loc(), None) {
self.errs.extend(errs); self.errs.extend(errs);

View file

@ -1916,6 +1916,34 @@ impl SetWithLenTypeSpec {
} }
} }
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct TupleTypeSpec {
pub parens: Option<(Token, Token)>,
pub tys: Vec<TypeSpec>,
}
impl fmt::Display for TupleTypeSpec {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "({})", fmt_vec(&self.tys))
}
}
impl Locational for TupleTypeSpec {
fn loc(&self) -> Location {
if let Some((lparen, rparen)) = &self.parens {
Location::concat(lparen, rparen)
} else {
Location::concat(self.tys.first().unwrap(), self.tys.last().unwrap())
}
}
}
impl TupleTypeSpec {
pub fn new(parens: Option<(Token, Token)>, tys: Vec<TypeSpec>) -> Self {
Self { parens, tys }
}
}
/// * Array: `[Int; 3]`, `[Int, Ratio, Complex]`, etc. /// * Array: `[Int; 3]`, `[Int, Ratio, Complex]`, etc.
/// * Dict: `[Str: Str]`, etc. /// * Dict: `[Str: Str]`, etc.
/// * And (Intersection type): Add and Sub and Mul (== Num), etc. /// * And (Intersection type): Add and Sub and Mul (== Num), etc.
@ -1933,7 +1961,7 @@ pub enum TypeSpec {
/* Composite types */ /* Composite types */
Array(ArrayTypeSpec), Array(ArrayTypeSpec),
SetWithLen(SetWithLenTypeSpec), SetWithLen(SetWithLenTypeSpec),
Tuple(Vec<TypeSpec>), Tuple(TupleTypeSpec),
Dict(Vec<(TypeSpec, TypeSpec)>), Dict(Vec<(TypeSpec, TypeSpec)>),
Record(Vec<(Identifier, TypeSpec)>), Record(Vec<(Identifier, TypeSpec)>),
// Option(), // Option(),
@ -1964,7 +1992,7 @@ impl fmt::Display for TypeSpec {
Self::Or(lhs, rhs) => write!(f, "{lhs} or {rhs}"), Self::Or(lhs, rhs) => write!(f, "{lhs} or {rhs}"),
Self::Array(arr) => write!(f, "{arr}"), Self::Array(arr) => write!(f, "{arr}"),
Self::SetWithLen(set) => write!(f, "{set}"), Self::SetWithLen(set) => write!(f, "{set}"),
Self::Tuple(tys) => write!(f, "({})", fmt_vec(tys)), Self::Tuple(tup) => write!(f, "{tup}"),
Self::Dict(dict) => { Self::Dict(dict) => {
write!(f, "{{")?; write!(f, "{{")?;
for (k, v) in dict.iter() { for (k, v) in dict.iter() {
@ -2003,8 +2031,7 @@ impl Locational for TypeSpec {
} }
Self::Array(arr) => arr.loc(), Self::Array(arr) => arr.loc(),
Self::SetWithLen(set) => set.loc(), Self::SetWithLen(set) => set.loc(),
// TODO: ユニット Self::Tuple(tup) => tup.loc(),
Self::Tuple(tys) => Location::concat(tys.first().unwrap(), tys.last().unwrap()),
Self::Dict(dict) => Location::concat(&dict.first().unwrap().0, &dict.last().unwrap().1), Self::Dict(dict) => Location::concat(&dict.first().unwrap().0, &dict.last().unwrap().1),
Self::Record(rec) => Location::concat(&rec.first().unwrap().0, &rec.last().unwrap().1), Self::Record(rec) => Location::concat(&rec.first().unwrap().0, &rec.last().unwrap().1),
Self::Enum(set) => set.loc(), Self::Enum(set) => set.loc(),

View file

@ -17,9 +17,9 @@ use crate::ast::{
Identifier, KeyValue, KwArg, Lambda, LambdaSignature, Literal, Methods, MixedRecord, Module, Identifier, KeyValue, KwArg, Lambda, LambdaSignature, Literal, Methods, MixedRecord, Module,
NonDefaultParamSignature, NormalArray, NormalDict, NormalRecord, NormalSet, NormalTuple, NonDefaultParamSignature, NormalArray, NormalDict, NormalRecord, NormalSet, NormalTuple,
ParamPattern, ParamRecordAttr, Params, PatchDef, PosArg, Record, RecordAttrOrIdent, ParamPattern, ParamRecordAttr, Params, PatchDef, PosArg, Record, RecordAttrOrIdent,
RecordAttrs, Set as astSet, SetWithLength, Signature, SubrSignature, Tuple, TypeAppArgs, RecordAttrs, Set as astSet, SetWithLength, Signature, SubrSignature, Tuple, TupleTypeSpec,
TypeBoundSpecs, TypeSpec, TypeSpecWithOp, UnaryOp, VarName, VarPattern, VarRecordAttr, TypeAppArgs, TypeBoundSpecs, TypeSpec, TypeSpecWithOp, UnaryOp, VarName, VarPattern,
VarSignature, VarRecordAttr, VarSignature,
}; };
use crate::token::{Token, TokenKind, COLON, DOT}; use crate::token::{Token, TokenKind, COLON, DOT};
@ -766,7 +766,8 @@ impl Desugarer {
); );
} }
if param.t_spec.is_none() { if param.t_spec.is_none() {
param.t_spec = Some(TypeSpecWithOp::new(COLON, TypeSpec::Tuple(tys))); let t_spec = TypeSpec::Tuple(TupleTypeSpec::new(tup.elems.parens.clone(), tys));
param.t_spec = Some(TypeSpecWithOp::new(COLON, t_spec));
} }
param.pat = buf_param; param.pat = buf_param;
} }
@ -901,7 +902,8 @@ impl Desugarer {
); );
} }
if sig.t_spec.is_none() { if sig.t_spec.is_none() {
sig.t_spec = Some(TypeSpecWithOp::new(COLON, TypeSpec::Tuple(tys))); let t_spec = TypeSpec::Tuple(TupleTypeSpec::new(tup.elems.parens.clone(), tys));
sig.t_spec = Some(TypeSpecWithOp::new(COLON, t_spec));
} }
sig.pat = buf_sig; sig.pat = buf_sig;
insertion_idx insertion_idx

View file

@ -1150,7 +1150,7 @@ impl Parser {
enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_))), enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_))),
)); ));
let tup = self let tup = self
.try_reduce_tuple(first_elem, false) .try_reduce_nonempty_tuple(first_elem, false)
.map_err(|_| self.stack_dec())?; .map_err(|_| self.stack_dec())?;
stack.push(ExprOrOp::Expr(Expr::Tuple(tup))); stack.push(ExprOrOp::Expr(Expr::Tuple(tup)));
} }
@ -1329,7 +1329,7 @@ impl Parser {
enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_))), enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_))),
)); ));
let tup = self let tup = self
.try_reduce_tuple(first_elem, line_break) .try_reduce_nonempty_tuple(first_elem, line_break)
.map_err(|_| self.stack_dec())?; .map_err(|_| self.stack_dec())?;
stack.push(ExprOrOp::Expr(Expr::Tuple(tup))); stack.push(ExprOrOp::Expr(Expr::Tuple(tup)));
} }
@ -1423,7 +1423,7 @@ impl Parser {
.map_err(|_| self.stack_dec())?; .map_err(|_| self.stack_dec())?;
let first_elem = PosOrKwArg::Kw(KwArg::new(keyword, t_spec, rhs)); let first_elem = PosOrKwArg::Kw(KwArg::new(keyword, t_spec, rhs));
let tuple = self let tuple = self
.try_reduce_tuple(first_elem, false) .try_reduce_nonempty_tuple(first_elem, false)
.map_err(|_| self.stack_dec())?; .map_err(|_| self.stack_dec())?;
self.level -= 1; self.level -= 1;
Ok(tuple) Ok(tuple)
@ -2097,7 +2097,11 @@ impl Parser {
Err(()) Err(())
} }
fn try_reduce_tuple(&mut self, first_elem: PosOrKwArg, line_break: bool) -> ParseResult<Tuple> { fn try_reduce_nonempty_tuple(
&mut self,
first_elem: PosOrKwArg,
line_break: bool,
) -> ParseResult<Tuple> {
debug_call_info!(self); debug_call_info!(self);
let mut args = match first_elem { let mut args = match first_elem {
PosOrKwArg::Pos(pos) => Args::new(vec![pos], vec![], None), PosOrKwArg::Pos(pos) => Args::new(vec![pos], vec![], None),
@ -3284,16 +3288,16 @@ impl Parser {
} }
} }
fn tuple_to_tuple_type_spec(tuple: Tuple) -> Result<Vec<TypeSpec>, ParseError> { fn tuple_to_tuple_type_spec(tuple: Tuple) -> Result<TupleTypeSpec, ParseError> {
match tuple { match tuple {
Tuple::Normal(tup) => { Tuple::Normal(tup) => {
let mut tup_spec = vec![]; let mut tup_spec = vec![];
let (elems, ..) = tup.elems.deconstruct(); let (elems, .., parens) = tup.elems.deconstruct();
for elem in elems.into_iter() { for elem in elems.into_iter() {
let value = Self::expr_to_type_spec(elem.expr)?; let value = Self::expr_to_type_spec(elem.expr)?;
tup_spec.push(value); tup_spec.push(value);
} }
Ok(tup_spec) Ok(TupleTypeSpec::new(parens, tup_spec))
} }
} }
} }