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)
TypeSpec::Tuple(tup) => {
let len = tup.len();
for (i, t_spec) in tup.into_iter().enumerate() {
let len = tup.tys.len();
for (i, t_spec) in tup.tys.into_iter().enumerate() {
if i != 0 && i != len - 1 {
self.dup_top();
}

View file

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

View file

@ -188,7 +188,11 @@ impl Context {
self.locals.insert(ident.name.clone(), vi);
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 py_name = if let Some(vi) = self
.decls
@ -201,7 +205,7 @@ impl Context {
};
let vis = ident.vis();
let vi = VarInfo::new(
body_t.clone(),
var_t,
muty,
vis,
VarKind::Defined(id),
@ -211,8 +215,12 @@ impl Context {
);
log!(info "Registered {}::{}: {}", self.name, ident.name, vi);
self.locals.insert(ident.name.clone(), vi);
if let Some(errs) = errs {
Err(errs)
} else {
Ok(())
}
}
/// 宣言が既にある場合、opt_decl_tに宣言の型を渡す
fn assign_param(

View file

@ -159,16 +159,7 @@ impl NestedDisplay for Args {
}
}
impl From<Vec<Expr>> for Args {
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,
}
}
}
// do not implement From<Vec<Expr>> to Args, because it will miss paren info (use `values`)
impl_display_from_nested!(Args);
@ -183,6 +174,8 @@ impl Locational for Args {
self.pos_args.first().unwrap(),
self.pos_args.last().unwrap(),
)
} else if let Some(va) = self.var_args.as_ref() {
va.loc()
} else {
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 {
Self::new(vec![], None, vec![], None)
}

View file

@ -364,7 +364,7 @@ impl ASTLowerer {
array.l_sqbr,
array.r_sqbr,
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> {
log!(info "entered {}({tuple})", fn_name!());
let mut new_tuple = vec![];
let (elems, _) = tuple.elems.into_iters();
let (elems, .., paren) = tuple.elems.deconstruct();
for elem in elems {
let elem = self.lower_expr(elem.expr)?;
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> {
@ -526,7 +526,7 @@ impl ASTLowerer {
}
Ok(normal_set)
*/
let elems = hir::Args::from(new_set);
let elems = hir::Args::values(new_set, None);
// check if elem_t is Eq
if let Err(errs) = self.ctx.sub_unify(&elem_t, &mono("Eq"), elems.loc(), None) {
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.
/// * Dict: `[Str: Str]`, etc.
/// * And (Intersection type): Add and Sub and Mul (== Num), etc.
@ -1933,7 +1961,7 @@ pub enum TypeSpec {
/* Composite types */
Array(ArrayTypeSpec),
SetWithLen(SetWithLenTypeSpec),
Tuple(Vec<TypeSpec>),
Tuple(TupleTypeSpec),
Dict(Vec<(TypeSpec, TypeSpec)>),
Record(Vec<(Identifier, TypeSpec)>),
// Option(),
@ -1964,7 +1992,7 @@ impl fmt::Display for TypeSpec {
Self::Or(lhs, rhs) => write!(f, "{lhs} or {rhs}"),
Self::Array(arr) => write!(f, "{arr}"),
Self::SetWithLen(set) => write!(f, "{set}"),
Self::Tuple(tys) => write!(f, "({})", fmt_vec(tys)),
Self::Tuple(tup) => write!(f, "{tup}"),
Self::Dict(dict) => {
write!(f, "{{")?;
for (k, v) in dict.iter() {
@ -2003,8 +2031,7 @@ impl Locational for TypeSpec {
}
Self::Array(arr) => arr.loc(),
Self::SetWithLen(set) => set.loc(),
// TODO: ユニット
Self::Tuple(tys) => Location::concat(tys.first().unwrap(), tys.last().unwrap()),
Self::Tuple(tup) => tup.loc(),
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::Enum(set) => set.loc(),

View file

@ -17,9 +17,9 @@ use crate::ast::{
Identifier, KeyValue, KwArg, Lambda, LambdaSignature, Literal, Methods, MixedRecord, Module,
NonDefaultParamSignature, NormalArray, NormalDict, NormalRecord, NormalSet, NormalTuple,
ParamPattern, ParamRecordAttr, Params, PatchDef, PosArg, Record, RecordAttrOrIdent,
RecordAttrs, Set as astSet, SetWithLength, Signature, SubrSignature, Tuple, TypeAppArgs,
TypeBoundSpecs, TypeSpec, TypeSpecWithOp, UnaryOp, VarName, VarPattern, VarRecordAttr,
VarSignature,
RecordAttrs, Set as astSet, SetWithLength, Signature, SubrSignature, Tuple, TupleTypeSpec,
TypeAppArgs, TypeBoundSpecs, TypeSpec, TypeSpecWithOp, UnaryOp, VarName, VarPattern,
VarRecordAttr, VarSignature,
};
use crate::token::{Token, TokenKind, COLON, DOT};
@ -766,7 +766,8 @@ impl Desugarer {
);
}
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;
}
@ -901,7 +902,8 @@ impl Desugarer {
);
}
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;
insertion_idx

View file

@ -1150,7 +1150,7 @@ impl Parser {
enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_))),
));
let tup = self
.try_reduce_tuple(first_elem, false)
.try_reduce_nonempty_tuple(first_elem, false)
.map_err(|_| self.stack_dec())?;
stack.push(ExprOrOp::Expr(Expr::Tuple(tup)));
}
@ -1329,7 +1329,7 @@ impl Parser {
enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_))),
));
let tup = self
.try_reduce_tuple(first_elem, line_break)
.try_reduce_nonempty_tuple(first_elem, line_break)
.map_err(|_| self.stack_dec())?;
stack.push(ExprOrOp::Expr(Expr::Tuple(tup)));
}
@ -1423,7 +1423,7 @@ impl Parser {
.map_err(|_| self.stack_dec())?;
let first_elem = PosOrKwArg::Kw(KwArg::new(keyword, t_spec, rhs));
let tuple = self
.try_reduce_tuple(first_elem, false)
.try_reduce_nonempty_tuple(first_elem, false)
.map_err(|_| self.stack_dec())?;
self.level -= 1;
Ok(tuple)
@ -2097,7 +2097,11 @@ impl Parser {
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);
let mut args = match first_elem {
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 {
Tuple::Normal(tup) => {
let mut tup_spec = vec![];
let (elems, ..) = tup.elems.deconstruct();
let (elems, .., parens) = tup.elems.deconstruct();
for elem in elems.into_iter() {
let value = Self::expr_to_type_spec(elem.expr)?;
tup_spec.push(value);
}
Ok(tup_spec)
Ok(TupleTypeSpec::new(parens, tup_spec))
}
}
}