dev: replace FieldTy with ParamTy (#830)

This commit is contained in:
Myriad-Dreamin 2024-11-16 13:50:50 +08:00 committed by GitHub
parent d618430f6e
commit 57c6c7a4f6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 188 additions and 146 deletions

View file

@ -3,9 +3,9 @@
use hashbrown::HashSet;
use tinymist_derive::BindTyCtx;
use super::{prelude::*, SharedContext};
use super::{prelude::*, ParamAttrs, SharedContext};
use super::{
ArgsTy, FieldTy, Sig, SigChecker, SigShape, SigSurfaceKind, SigTy, Ty, TyCtx, TyCtxMut,
ArgsTy, ParamTy, Sig, SigChecker, SigShape, SigSurfaceKind, SigTy, Ty, TyCtx, TyCtxMut,
TypeBounds, TypeScheme, TypeVar,
};
use crate::syntax::{get_check_target, get_check_target_by_context, CheckTarget, ParamTarget};
@ -82,8 +82,8 @@ fn check_signature<'a>(
// names
for (name, _) in sig_ins.named_params() {
// todo: reduce fields, fields ty
let field = FieldTy::new_untyped(name.clone());
receiver.insert(&Ty::Field(field), !pol);
let field = ParamTy::new_untyped(name.clone(), ParamAttrs::named());
receiver.insert(&Ty::Param(field), !pol);
}
Some(())

View file

@ -7,7 +7,6 @@ pub use std::sync::{Arc, LazyLock};
pub use comemo::Track;
pub use ecow::*;
pub use serde::{Deserialize, Serialize};
pub use typst::foundations::{Func, Value};
pub use typst::syntax::ast::{self, AstNode};
pub use typst::syntax::{FileId as TypstFileId, LinkedNode, Source, Span, SyntaxKind, SyntaxNode};

View file

@ -2,89 +2,19 @@
use itertools::Either;
use tinymist_derive::BindTyCtx;
use typst::foundations::{Closure, ParamInfo};
use typst::foundations::Closure;
use super::{
prelude::*, BoundChecker, Definition, DocSource, SharedContext, SigTy, SigWithTy, TypeVar,
prelude::*, BoundChecker, Definition, DocSource, ParamTy, SharedContext, SigTy, SigWithTy,
TypeScheme, TypeVar,
};
use crate::analysis::PostTypeChecker;
use crate::docs::{UntypedDefDocs, UntypedSignatureDocs, UntypedVarDocs};
use crate::syntax::get_non_strict_def_target;
use crate::ty::TypeBounds;
use crate::ty::{InsTy, TyCtx};
use crate::ty::{ParamAttrs, TypeBounds};
use crate::upstream::truncated_repr;
/// Describes a function parameter.
#[derive(Debug, Clone, Copy, Serialize, Deserialize, Default)]
pub struct ParamAttrs {
/// Is the parameter positional?
pub positional: bool,
/// Is the parameter named?
///
/// Can be true even if `positional` is true if the parameter can be given
/// in both variants.
pub named: bool,
/// Can the parameter be given any number of times?
pub variadic: bool,
/// Is the parameter settable with a set rule?
pub settable: bool,
}
impl ParamAttrs {
pub(crate) fn positional() -> ParamAttrs {
ParamAttrs {
positional: true,
named: false,
variadic: false,
settable: false,
}
}
pub(crate) fn named() -> ParamAttrs {
ParamAttrs {
positional: false,
named: true,
variadic: false,
settable: false,
}
}
pub(crate) fn variadic() -> ParamAttrs {
ParamAttrs {
positional: true,
named: false,
variadic: true,
settable: false,
}
}
}
impl From<&ParamInfo> for ParamAttrs {
fn from(param: &ParamInfo) -> Self {
ParamAttrs {
positional: param.positional,
named: param.named,
variadic: param.variadic,
settable: param.settable,
}
}
}
/// Describes a function parameter.
#[derive(Debug, Clone)]
pub struct ParamSpec {
/// The name of the parameter.
pub name: StrRef,
/// The docstring of the parameter.
pub docs: Option<EcoString>,
/// The default value of the variable
pub default: Option<EcoString>,
/// The type of the parameter.
pub ty: Ty,
/// The attributes of the parameter.
pub attrs: ParamAttrs,
}
/// Describes a function signature.
#[derive(Debug, Clone)]
pub enum Signature {
@ -112,7 +42,7 @@ impl Signature {
}
/// Returns the all parameters of the function.
pub(crate) fn params(&self) -> impl Iterator<Item = (&ParamSpec, Option<&Ty>)> {
pub(crate) fn params(&self) -> impl Iterator<Item = (&Interned<ParamTy>, Option<&Ty>)> {
let primary = self.primary().params();
// todo: with stack
primary
@ -124,7 +54,7 @@ impl Signature {
primary
}
pub(crate) fn param_shift(&self, _ctx: &mut LocalContext) -> usize {
pub(crate) fn param_shift(&self) -> usize {
match self {
Signature::Primary(_) => 0,
Signature::Partial(sig) => sig
@ -142,7 +72,7 @@ pub struct PrimarySignature {
/// The documentation of the function
pub docs: Option<EcoString>,
/// The documentation of the parameter.
pub param_specs: Vec<ParamSpec>,
pub param_specs: Vec<Interned<ParamTy>>,
/// Whether the function has fill, stroke, or size parameters.
pub has_fill_or_size_or_stroke: bool,
/// The associated signature type.
@ -162,22 +92,22 @@ impl PrimarySignature {
}
/// Returns the positional parameters of the function.
pub fn pos(&self) -> &[ParamSpec] {
pub fn pos(&self) -> &[Interned<ParamTy>] {
&self.param_specs[..self.pos_size()]
}
/// Returns the positional parameters of the function.
pub fn get_pos(&self, offset: usize) -> Option<&ParamSpec> {
pub fn get_pos(&self, offset: usize) -> Option<&Interned<ParamTy>> {
self.pos().get(offset)
}
/// Returns the named parameters of the function.
pub fn named(&self) -> &[ParamSpec] {
pub fn named(&self) -> &[Interned<ParamTy>] {
&self.param_specs[self.pos_size()..self.pos_size() + self.sig_ty.names.names.len()]
}
/// Returns the named parameters of the function.
pub fn get_named(&self, name: &StrRef) -> Option<&ParamSpec> {
pub fn get_named(&self, name: &StrRef) -> Option<&Interned<ParamTy>> {
self.named().get(self.sig_ty.names.find(name)?)
}
@ -187,13 +117,13 @@ impl PrimarySignature {
}
/// Returns the rest parameter of the function.
pub fn rest(&self) -> Option<&ParamSpec> {
pub fn rest(&self) -> Option<&Interned<ParamTy>> {
self.has_spread_right()
.then(|| &self.param_specs[self.pos_size() + self.sig_ty.names.names.len()])
}
/// Returns the all parameters of the function.
pub fn params(&self) -> impl Iterator<Item = (&ParamSpec, Option<&Ty>)> {
pub fn params(&self) -> impl Iterator<Item = (&Interned<ParamTy>, Option<&Ty>)> {
let pos = self.pos();
let named = self.named();
let rest = self.rest();
@ -287,6 +217,14 @@ fn analyze_type_signature(
}
}?;
sig_of_type(ctx, &type_info, ty)
}
pub(crate) fn sig_of_type(
ctx: &Arc<SharedContext>,
type_info: &TypeScheme,
ty: Ty,
) -> Option<Signature> {
// todo multiple sources
let mut srcs = ty.sources();
srcs.sort();
@ -294,7 +232,7 @@ fn analyze_type_signature(
let type_var = srcs.into_iter().next()?;
match type_var {
DocSource::Var(v) => {
let mut ty_ctx = PostTypeChecker::new(ctx.clone(), &type_info);
let mut ty_ctx = PostTypeChecker::new(ctx.clone(), type_info);
let sig_ty = Ty::Func(ty.sig_repr(true, &mut ty_ctx)?);
let sig_ty = type_info.simplify(sig_ty, false);
let Ty::Func(sig_ty) = sig_ty else {
@ -330,13 +268,13 @@ fn analyze_type_signature(
has_fill_or_size_or_stroke = true;
}
param_specs.push(ParamSpec {
param_specs.push(Interned::new(ParamTy {
name,
docs: Some(doc.docs.clone()),
default,
ty,
attrs: ParamAttrs::positional(),
});
}));
}
for (name, ty) in sig_ty.named_params() {
@ -348,25 +286,25 @@ fn analyze_type_signature(
has_fill_or_size_or_stroke = true;
}
param_specs.push(ParamSpec {
param_specs.push(Interned::new(ParamTy {
name: name.clone(),
docs: Some(doc.docs.clone()),
default,
ty,
attrs: ParamAttrs::named(),
});
}));
}
if let Some(doc) = docstring.rest.as_ref() {
let default = doc.default.clone();
param_specs.push(ParamSpec {
param_specs.push(Interned::new(ParamTy {
name: doc.name.clone(),
docs: Some(doc.docs.clone()),
default,
ty: sig_ty.rest_param().cloned().unwrap_or(Ty::Any),
attrs: ParamAttrs::variadic(),
});
}));
}
let sig = Signature::Primary(Arc::new(PrimarySignature {
@ -568,7 +506,7 @@ fn analyze_dyn_signature_inner(func: Func) -> Arc<PrimarySignature> {
let mut broken = false;
let mut has_fill_or_size_or_stroke = false;
let mut add_param = |param: ParamSpec| {
let mut add_param = |param: Interned<ParamTy>| {
let name = param.name.clone();
if param.attrs.named {
if matches!(name.as_ref(), "fill" | "stroke" | "size") {
@ -601,13 +539,13 @@ fn analyze_dyn_signature_inner(func: Func) -> Arc<PrimarySignature> {
}
Repr::Element(..) | Repr::Native(..) => {
for p in func.params().unwrap() {
add_param(ParamSpec {
add_param(Interned::new(ParamTy {
name: p.name.into(),
docs: Some(p.docs.into()),
default: p.default.map(|d| truncated_repr(&d())),
ty: Ty::from_param_site(&func, p),
attrs: p.into(),
});
}));
}
func.returns().map(|r| Ty::from_return_site(&func, r))
@ -632,7 +570,10 @@ fn analyze_dyn_signature_inner(func: Func) -> Arc<PrimarySignature> {
})
}
fn analyze_closure_signature(c: Arc<LazyHash<Closure>>, add_param: &mut impl FnMut(ParamSpec)) {
fn analyze_closure_signature(
c: Arc<LazyHash<Closure>>,
add_param: &mut impl FnMut(Interned<ParamTy>),
) {
log::trace!("closure signature for: {:?}", c.node.kind());
let closure = &c.node;
@ -645,34 +586,34 @@ fn analyze_closure_signature(c: Arc<LazyHash<Closure>>, add_param: &mut impl FnM
match param {
ast::Param::Pos(e) => {
let name = format!("{}", PatternDisplay(&e));
add_param(ParamSpec {
add_param(Interned::new(ParamTy {
name: name.as_str().into(),
docs: None,
default: None,
ty: Ty::Any,
attrs: ParamAttrs::positional(),
});
}));
}
// todo: pattern
ast::Param::Named(n) => {
let expr = unwrap_expr(n.expr()).to_untyped().clone().into_text();
add_param(ParamSpec {
add_param(Interned::new(ParamTy {
name: n.name().get().into(),
docs: Some(eco_format!("Default value: {expr}")),
default: Some(expr),
ty: Ty::Any,
attrs: ParamAttrs::named(),
});
}));
}
ast::Param::Spread(n) => {
let ident = n.sink_ident().map(|e| e.as_str());
add_param(ParamSpec {
add_param(Interned::new(ParamTy {
name: ident.unwrap_or_default().into(),
docs: None,
default: None,
ty: Ty::Any,
attrs: ParamAttrs::variadic(),
});
}));
}
}
}

View file

@ -399,8 +399,8 @@ impl<'a> TypeChecker<'a> {
w.weaken();
}
Ty::Any | Ty::Boolean(_) | Ty::Builtin(_) | Ty::Value(_) => {}
Ty::Field(v) => {
self.weaken(&v.field);
Ty::Param(v) => {
self.weaken(&v.ty);
}
Ty::Func(v) | Ty::Args(v) | Ty::Pattern(v) => {
for ty in v.inputs() {
@ -540,8 +540,8 @@ impl Joiner {
(Ty::Union(..), _) => self.definite = Ty::undef(),
(Ty::Let(w), Ty::Builtin(BuiltinTy::None)) => self.definite = Ty::Let(w),
(Ty::Let(..), _) => self.definite = Ty::undef(),
(Ty::Field(w), Ty::Builtin(BuiltinTy::None)) => self.definite = Ty::Field(w),
(Ty::Field(..), _) => self.definite = Ty::undef(),
(Ty::Param(w), Ty::Builtin(BuiltinTy::None)) => self.definite = Ty::Param(w),
(Ty::Param(..), _) => self.definite = Ty::undef(),
(Ty::Boolean(b), Ty::Builtin(BuiltinTy::None)) => self.definite = Ty::Boolean(b),
(Ty::Boolean(..), _) => self.definite = Ty::undef(),
}

View file

@ -7,7 +7,7 @@ use serde::{Deserialize, Serialize};
use typst::syntax::Span;
use super::tidy::*;
use crate::analysis::{ParamAttrs, ParamSpec, Signature};
use crate::analysis::{ParamAttrs, ParamTy, Signature};
use crate::prelude::*;
use crate::ty::Ty;
use crate::ty::{DocSource, Interned};
@ -279,7 +279,7 @@ pub struct ParamDocsT<T> {
}
impl ParamDocs {
fn new(param: &ParamSpec, ty: Option<&Ty>) -> Self {
fn new(param: &ParamTy, ty: Option<&Ty>) -> Self {
Self {
name: param.name.as_ref().into(),
docs: param.docs.clone().unwrap_or_default(),

View file

@ -43,7 +43,7 @@ impl SemanticRequest for SignatureHelpRequest {
let sig = ctx.sig_of_def(def.clone())?;
log::debug!("got signature {sig:?}");
let param_shift = sig.param_shift(ctx);
let param_shift = sig.param_shift();
let mut active_parameter = None;
let mut label = def.name().as_ref().to_owned();

View file

@ -78,8 +78,9 @@ impl Ty {
Any | Boolean(_) | If(..) | Builtin(..) | Value(..) => {}
Dict(..) | Array(..) | Tuple(..) | Func(..) | Args(..) | Pattern(..) => {}
Unary(..) | Binary(..) => {}
Field(ty) => {
collect(&ty.field, results);
Param(ty) => {
// todo: doc source can be param ty
collect(&ty.ty, results);
}
Union(ty) => {
for ty in ty.iter() {

View file

@ -8,13 +8,14 @@ use std::{
sync::Arc,
};
use ecow::EcoVec;
use ecow::{EcoString, EcoVec};
use once_cell::sync::OnceCell;
use parking_lot::{Mutex, RwLock};
use reflexo_typst::TypstFileId;
use rustc_hash::{FxHashMap, FxHashSet};
use serde::{Deserialize, Serialize};
use typst::{
foundations::Value,
foundations::{ParamInfo, Value},
syntax::{ast, Span, SyntaxKind, SyntaxNode},
};
@ -49,8 +50,8 @@ pub enum Ty {
Builtin(BuiltinTy),
/// A possible typst instance of some type.
Value(Interned<InsTy>),
/// A field type
Field(Interned<FieldTy>),
/// A parameter type
Param(Interned<ParamTy>),
// Combination Types
/// A union type, whose negation is intersection type.
@ -120,7 +121,7 @@ impl fmt::Debug for Ty {
f.write_str(")")
}
Ty::Let(v) => write!(f, "({v:?})"),
Ty::Field(ff) => write!(f, "{:?}: {:?}", ff.name, ff.field),
Ty::Param(ff) => write!(f, "{:?}: {:?}", ff.name, ff.ty),
Ty::Var(v) => v.fmt(f),
Ty::Unary(u) => write!(f, "{u:?}"),
Ty::Binary(b) => write!(f, "{b:?}"),
@ -168,6 +169,39 @@ impl Ty {
Ty::Builtin(BuiltinTy::Undef)
}
/// Get name of the type
pub fn name(&self) -> Interned<str> {
match self {
Ty::Var(v) => v.name.clone(),
ty => ty
.value()
.and_then(|v| Some(Interned::new_str(v.name()?)))
.unwrap_or_default(),
}
}
/// Get span of the type
pub fn span(&self) -> Span {
fn seq(u: &[Ty]) -> Option<Span> {
u.iter().find_map(|ty| {
let sub = ty.span();
if sub.is_detached() {
return None;
}
Some(sub)
})
}
match self {
Ty::Var(v) => v.def.span(),
Ty::Let(u) => seq(&u.ubs)
.or_else(|| seq(&u.lbs))
.unwrap_or_else(Span::detached),
Ty::Union(u) => seq(u).unwrap_or_else(Span::detached),
_ => Span::detached(),
}
}
/// Get value repr of the type
pub fn value(&self) -> Option<Value> {
match self {
@ -437,21 +471,88 @@ impl InsTy {
}
}
/// A field type
#[derive(Debug, Hash, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct FieldTy {
/// The name of the field
pub name: StrRef,
/// The type of the field
pub field: Ty,
/// Describes a function parameter.
#[derive(
Debug, Clone, Copy, Hash, Serialize, Deserialize, Default, PartialEq, Eq, PartialOrd, Ord,
)]
pub struct ParamAttrs {
/// Is the parameter positional?
pub positional: bool,
/// Is the parameter named?
///
/// Can be true even if `positional` is true if the parameter can be given
/// in both variants.
pub named: bool,
/// Can the parameter be given any number of times?
pub variadic: bool,
/// Is the parameter settable with a set rule?
pub settable: bool,
}
impl FieldTy {
impl ParamAttrs {
pub(crate) fn positional() -> ParamAttrs {
ParamAttrs {
positional: true,
named: false,
variadic: false,
settable: false,
}
}
pub(crate) fn named() -> ParamAttrs {
ParamAttrs {
positional: false,
named: true,
variadic: false,
settable: false,
}
}
pub(crate) fn variadic() -> ParamAttrs {
ParamAttrs {
positional: true,
named: false,
variadic: true,
settable: false,
}
}
}
impl From<&ParamInfo> for ParamAttrs {
fn from(param: &ParamInfo) -> Self {
ParamAttrs {
positional: param.positional,
named: param.named,
variadic: param.variadic,
settable: param.settable,
}
}
}
/// Describes a parameter type.
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct ParamTy {
/// The name of the parameter.
pub name: StrRef,
/// The docstring of the parameter.
pub docs: Option<EcoString>,
/// The default value of the variable
pub default: Option<EcoString>,
/// The type of the parameter.
pub ty: Ty,
/// The attributes of the parameter.
pub attrs: ParamAttrs,
}
impl ParamTy {
/// Create an untyped field type
pub fn new_untyped(name: StrRef) -> Interned<Self> {
pub fn new_untyped(name: StrRef, attrs: ParamAttrs) -> Interned<Self> {
Interned::new(Self {
name,
field: Ty::Any,
ty: Ty::Any,
docs: None,
default: None,
attrs,
})
}
}
@ -1163,7 +1264,7 @@ pub(super) struct TypeCanoStore {
impl_internable!(Ty,);
impl_internable!(InsTy,);
impl_internable!(FieldTy,);
impl_internable!(ParamTy,);
impl_internable!(TypeSource,);
impl_internable!(TypeVar,);
impl_internable!(SigWithTy,);

View file

@ -199,8 +199,8 @@ impl TypeDescriber {
Ty::Value(v) if self.value => return truncated_repr_::<181>(&v.val),
Ty::Value(v) if self.repr => return v.val.ty().short_name().into(),
Ty::Value(v) => return v.val.repr(),
Ty::Field(..) => {
return "field".into();
Ty::Param(..) => {
return "param".into();
}
Ty::Args(..) => {
return "arguments".into();

View file

@ -27,8 +27,6 @@ pub enum Iface<'a> {
val: &'a Module,
at: &'a Ty,
},
ArrayCons(&'a TyRef),
Partialize(&'a Iface<'a>),
}
impl<'a> Iface<'a> {
@ -38,11 +36,9 @@ impl<'a> Iface<'a> {
match self {
// Iface::ArrayCons(a) => SigTy::array_cons(a.as_ref().clone(), false),
Iface::ArrayCons(..) => None,
Iface::Dict(d) => d.field_by_name(key).cloned(),
// Iface::Type { val, .. } => ctx?.type_of_func(&val.constructor().ok()?)?,
// Iface::Value { val, .. } => ctx?.type_of_func(val)?, // todo
Iface::Partialize(..) => None,
Iface::Element { .. } => None,
Iface::Type { .. } => None,
Iface::Value { val, at: _ } => ctx.type_of_dict(val).field_by_name(key).cloned(),

View file

@ -16,7 +16,7 @@ pub trait TyMutator {
Func(f) => Some(Func(self.mutate_func(f, pol)?.into())),
Args(args) => Some(Args(self.mutate_func(args, pol)?.into())),
Pattern(args) => Some(Pattern(self.mutate_func(args, pol)?.into())),
Field(f) => Some(Field(self.mutate_field(f, pol)?.into())),
Param(f) => Some(Param(self.mutate_field(f, pol)?.into())),
Select(s) => Some(Select(self.mutate_select(s, pol)?.into())),
With(w) => Some(With(self.mutate_with_sig(w, pol)?.into())),
Unary(u) => Some(Unary(self.mutate_unary(u, pol)?.into())),
@ -71,10 +71,10 @@ pub trait TyMutator {
})
}
fn mutate_field(&mut self, f: &Interned<FieldTy>, pol: bool) -> Option<FieldTy> {
let field = self.mutate(&f.field, pol)?;
fn mutate_field(&mut self, f: &Interned<ParamTy>, pol: bool) -> Option<ParamTy> {
let ty = self.mutate(&f.ty, pol)?;
let mut f = f.as_ref().clone();
f.field = field;
f.ty = ty;
Some(f)
}

View file

@ -237,6 +237,10 @@ impl<'a> SigCheckDriver<'a> {
Ty::Unary(_) => {}
Ty::Binary(_) => {}
Ty::If(_) => {}
Ty::Param(p) => {
// todo: keep type information
self.ty(&p.ty, pol);
}
_ if ty.has_bounds() => ty.bounds(pol, self),
_ => {}
}

View file

@ -152,8 +152,8 @@ impl<'a, 'b> TypeSimplifier<'a, 'b> {
self.analyze(ub, pol);
}
}
Ty::Field(v) => {
self.analyze(&v.field, pol);
Ty::Param(v) => {
self.analyze(&v.ty, pol);
}
Ty::Value(_v) => {}
Ty::Any => {}
@ -225,11 +225,11 @@ impl<'a, 'b> TypeSimplifier<'a, 'b> {
let seq = seq_no_any.collect::<Vec<_>>();
Ty::from_types(seq.into_iter())
}
Ty::Field(ty) => {
Ty::Param(ty) => {
let mut ty = ty.as_ref().clone();
ty.field = self.transform(&ty.field, pol);
ty.ty = self.transform(&ty.ty, pol);
Ty::Field(ty.into())
Ty::Param(ty.into())
}
Ty::Select(sel) => {
let mut sel = sel.as_ref().clone();

View file

@ -717,7 +717,7 @@ fn type_completion(
ctx.snippet_completion("false", "false", "No / Disabled.");
ctx.snippet_completion("true", "true", "Yes / Enabled.");
}
Ty::Field(f) => {
Ty::Param(f) => {
let f = &f.name;
if ctx.seen_field(f.clone()) {
return Some(());