erg_compiler/ty/
constructors.rs

1use std::convert::TryInto;
2
3use erg_common::consts::PYTHON_MODE;
4use erg_common::dict;
5use erg_common::fresh::FRESH_GEN;
6
7use crate::ty::*;
8
9#[macro_export]
10macro_rules! fn_t {
11    ($input: expr => $ret: expr) => {
12        Type::Subr($crate::ty::SubrType::new(
13            $crate::ty::SubrKind::Func,
14            vec![$crate::ty::ParamTy::Pos($input)],
15            None,
16            vec![],
17            None,
18            $ret,
19        ))
20    };
21}
22
23#[inline]
24pub fn pos(ty: Type) -> ParamTy {
25    ParamTy::Pos(ty)
26}
27
28#[inline]
29pub fn kw(name: &'static str, ty: Type) -> ParamTy {
30    ParamTy::kw(Str::ever(name), ty)
31}
32
33#[inline]
34pub const fn kw_default(name: &'static str, ty: Type, default: Type) -> ParamTy {
35    ParamTy::kw_default(Str::ever(name), ty, default)
36}
37
38#[inline]
39pub const fn anon(ty: Type) -> ParamTy {
40    ParamTy::Pos(ty)
41}
42
43#[inline]
44pub fn free_var(level: usize, constraint: Constraint) -> Type {
45    Type::FreeVar(Free::new_unbound(level, constraint.to_type_constraint()))
46}
47
48#[inline]
49pub fn named_free_var(name: Str, level: usize, constraint: Constraint) -> Type {
50    Type::FreeVar(Free::new_named_unbound(
51        name,
52        level,
53        constraint.to_type_constraint(),
54    ))
55}
56
57#[inline]
58pub fn named_uninit_var(name: Str) -> Type {
59    Type::FreeVar(Free::new_named_unbound(name, 1, Constraint::Uninited))
60}
61
62pub fn list_t(elem_t: Type, len: TyParam) -> Type {
63    poly("List", vec![TyParam::t(elem_t), len])
64}
65
66pub fn list_mut(elem_t: Type, len: TyParam) -> Type {
67    poly("List!", vec![TyParam::t(elem_t), len])
68}
69
70pub fn out_list_t(elem_t: Type, len: TyParam) -> Type {
71    if PYTHON_MODE {
72        list_mut(elem_t, len)
73    } else {
74        list_t(elem_t, len)
75    }
76}
77
78pub fn unknown_len_list_t(elem_t: Type) -> Type {
79    list_t(elem_t, TyParam::erased(Type::Nat))
80}
81
82pub fn unknown_len_list_mut(elem_t: Type) -> Type {
83    list_mut(elem_t, TyParam::erased(Type::Nat))
84}
85
86pub fn out_unknown_len_list_t(elem_t: Type) -> Type {
87    if PYTHON_MODE {
88        unknown_len_list_mut(elem_t)
89    } else {
90        unknown_len_list_t(elem_t)
91    }
92}
93
94pub fn str_dict_t(value: Type) -> Type {
95    dict! { Type::Str => value }.into()
96}
97
98/// `UnsizedList` is a type of `[x; _]` (unsized list literal).
99/// `UnsizedList(T) != List(T, _)`
100pub fn unsized_list_t(elem_t: Type) -> Type {
101    poly("UnsizedList", vec![TyParam::t(elem_t)])
102}
103
104pub fn tuple_t(args: Vec<Type>) -> Type {
105    poly(
106        "Tuple",
107        vec![TyParam::List(args.into_iter().map(TyParam::t).collect())],
108    )
109}
110
111pub fn homo_tuple_t(t: Type) -> Type {
112    poly("HomogenousTuple", vec![TyParam::t(t)])
113}
114
115pub fn set_t(elem_t: Type, len: TyParam) -> Type {
116    poly("Set", vec![TyParam::t(elem_t), len])
117}
118
119pub fn unknown_len_set_t(elem_t: Type) -> Type {
120    set_t(elem_t, TyParam::erased(Type::Nat))
121}
122
123pub fn set_mut(elem_t: Type, len: TyParam) -> Type {
124    poly("Set!", vec![TyParam::t(elem_t), len])
125}
126
127pub fn out_set_t(elem_t: Type, len: TyParam) -> Type {
128    if PYTHON_MODE {
129        set_mut(elem_t, len)
130    } else {
131        set_t(elem_t, len)
132    }
133}
134
135pub fn dict_t(dict: TyParam) -> Type {
136    poly("Dict", vec![dict])
137}
138
139pub fn dict_mut(dict: TyParam) -> Type {
140    poly("Dict!", vec![dict])
141}
142
143pub fn out_dict_t(dict: TyParam) -> Type {
144    if PYTHON_MODE {
145        dict_mut(dict)
146    } else {
147        dict_t(dict)
148    }
149}
150
151#[inline]
152pub fn range(t: Type) -> Type {
153    poly("Range", vec![TyParam::t(t)])
154}
155
156#[inline]
157pub fn module(path: TyParam) -> Type {
158    poly("Module", vec![path])
159}
160
161#[inline]
162pub fn py_module(path: TyParam) -> Type {
163    poly("PyModule", vec![path])
164}
165
166pub fn module_from_path<P: Into<PathBuf>>(path: P) -> Type {
167    let s = ValueObj::Str(Str::rc(&path.into().to_string_lossy()));
168    module(TyParam::Value(s))
169}
170
171pub fn try_v_enum(s: Set<ValueObj>) -> Result<Type, Set<ValueObj>> {
172    if !is_homogeneous(&s) {
173        return Err(s);
174    }
175    let name = FRESH_GEN.fresh_varname();
176    let t = inner_class(&s);
177    let preds = s
178        .into_iter()
179        .map(|o| Predicate::eq(name.clone(), TyParam::value(o)))
180        .fold(Predicate::FALSE, |acc, p| acc | p);
181    let refine = RefinementType::new(name, t, preds);
182    Ok(Type::Refinement(refine))
183}
184
185pub fn v_enum(s: Set<ValueObj>) -> Type {
186    try_v_enum(s).unwrap_or_else(|set| panic!("not homogeneous: {}", set))
187}
188
189pub fn t_enum(s: Set<Type>) -> Type {
190    try_v_enum(s.into_iter().map(ValueObj::builtin_type).collect())
191        .unwrap_or_else(|set| panic!("not homogeneous: {}", set))
192}
193
194pub fn t_singleton(t: Type) -> Type {
195    t_enum(set! {t})
196}
197
198pub fn tp_enum(ty: Type, s: Set<TyParam>) -> Type {
199    let name = FRESH_GEN.fresh_varname();
200    let preds = s
201        .into_iter()
202        .map(|tp| Predicate::eq(name.clone(), tp))
203        .fold(Predicate::FALSE, |acc, p| acc | p);
204    let refine = RefinementType::new(name, ty, preds);
205    Type::Refinement(refine)
206}
207
208pub fn singleton(ty: Type, tp: TyParam) -> Type {
209    let name = FRESH_GEN.fresh_varname();
210    let preds = Predicate::eq(name.clone(), tp);
211    let refine = RefinementType::new(name, ty, preds);
212    Type::Refinement(refine)
213}
214
215#[inline]
216pub fn int_interval<P, PErr, Q, QErr>(op: IntervalOp, l: P, r: Q) -> Type
217where
218    P: TryInto<TyParam, Error = PErr>,
219    PErr: fmt::Debug,
220    Q: TryInto<TyParam, Error = QErr>,
221    QErr: fmt::Debug,
222{
223    interval(op, Type::Int, l, r)
224}
225
226#[inline]
227pub fn closed_range<P, PErr, Q, QErr>(t: Type, l: P, r: Q) -> Type
228where
229    P: TryInto<TyParam, Error = PErr>,
230    PErr: fmt::Debug,
231    Q: TryInto<TyParam, Error = QErr>,
232    QErr: fmt::Debug,
233{
234    interval(IntervalOp::Closed, t, l, r)
235}
236
237#[inline]
238pub fn interval<P, PErr, Q, QErr>(op: IntervalOp, t: Type, l: P, r: Q) -> Type
239where
240    P: TryInto<TyParam, Error = PErr>,
241    PErr: fmt::Debug,
242    Q: TryInto<TyParam, Error = QErr>,
243    QErr: fmt::Debug,
244{
245    let l = l.try_into().unwrap_or_else(|l| todo!("{l:?}"));
246    let r = r.try_into().unwrap_or_else(|r| todo!("{r:?}"));
247    let name = FRESH_GEN.fresh_varname();
248    let pred = match op {
249        IntervalOp::LeftOpen if l == TyParam::value(NegInf) => Predicate::le(name.clone(), r),
250        // l<..r => {I: classof(l) | I >= l+ε and I <= r}
251        IntervalOp::LeftOpen => Predicate::and(
252            Predicate::ge(name.clone(), TyParam::succ(l)),
253            Predicate::le(name.clone(), r),
254        ),
255        IntervalOp::RightOpen if r == TyParam::value(Inf) => Predicate::ge(name.clone(), l),
256        // l..<r => {I: classof(l) | I >= l and I <= r-ε}
257        IntervalOp::RightOpen => Predicate::and(
258            Predicate::ge(name.clone(), l),
259            Predicate::le(name.clone(), TyParam::pred(r)),
260        ),
261        // l..r => {I: classof(l) | I >= l and I <= r}
262        IntervalOp::Closed => Predicate::and(
263            Predicate::ge(name.clone(), l),
264            Predicate::le(name.clone(), r),
265        ),
266        IntervalOp::Open if l == TyParam::value(NegInf) && r == TyParam::value(Inf) => {
267            return refinement(name, t, Predicate::TRUE)
268        }
269        // l<..<r => {I: classof(l) | I >= l+ε and I <= r-ε}
270        IntervalOp::Open => Predicate::and(
271            Predicate::ge(name.clone(), TyParam::succ(l)),
272            Predicate::le(name.clone(), TyParam::pred(r)),
273        ),
274    };
275    refinement(name, t, pred)
276}
277
278pub fn iter(t: Type) -> Type {
279    poly("Iter", vec![TyParam::t(t)])
280}
281
282pub fn ref_(t: Type) -> Type {
283    Type::Ref(Box::new(t))
284}
285
286pub fn ref_mut(before: Type, after: Option<Type>) -> Type {
287    Type::RefMut {
288        before: Box::new(before),
289        after: after.map(Box::new),
290    }
291}
292
293/*pub fn option(t: Type) -> Type {
294    builtin_poly("Option", vec![TyParam::t(t)])
295}
296
297pub fn option_mut(t: Type) -> Type {
298    builtin_poly("Option!", vec![TyParam::t(t)])
299}*/
300
301pub fn subr_t(
302    kind: SubrKind,
303    non_default_params: Vec<ParamTy>,
304    var_params: Option<ParamTy>,
305    default_params: Vec<ParamTy>,
306    kw_var_params: Option<ParamTy>,
307    return_t: Type,
308) -> Type {
309    Type::Subr(SubrType::new(
310        kind,
311        non_default_params,
312        var_params,
313        default_params,
314        kw_var_params,
315        return_t,
316    ))
317}
318
319pub fn func(
320    non_default_params: Vec<ParamTy>,
321    var_params: Option<ParamTy>,
322    default_params: Vec<ParamTy>,
323    kw_var_params: Option<ParamTy>,
324    return_t: Type,
325) -> Type {
326    Type::Subr(SubrType::new(
327        SubrKind::Func,
328        non_default_params,
329        var_params,
330        default_params,
331        kw_var_params,
332        return_t,
333    ))
334}
335
336pub fn no_var_func(
337    non_default_params: Vec<ParamTy>,
338    default_params: Vec<ParamTy>,
339    return_t: Type,
340) -> Type {
341    func(non_default_params, None, default_params, None, return_t)
342}
343
344pub fn func0(return_t: Type) -> Type {
345    func(vec![], None, vec![], None, return_t)
346}
347
348pub fn func1(param_t: Type, return_t: Type) -> Type {
349    func(vec![ParamTy::Pos(param_t)], None, vec![], None, return_t)
350}
351
352pub fn kind1(param: Type) -> Type {
353    func1(param, Type::Type)
354}
355
356pub fn func2(l: Type, r: Type, return_t: Type) -> Type {
357    func(
358        vec![ParamTy::Pos(l), ParamTy::Pos(r)],
359        None,
360        vec![],
361        None,
362        return_t,
363    )
364}
365
366pub fn func3(l: Type, m: Type, r: Type, return_t: Type) -> Type {
367    func(
368        vec![ParamTy::Pos(l), ParamTy::Pos(m), ParamTy::Pos(r)],
369        None,
370        vec![],
371        None,
372        return_t,
373    )
374}
375
376pub fn default_func(defaults: Vec<ParamTy>, return_t: Type) -> Type {
377    func(vec![], None, defaults, None, return_t)
378}
379
380pub fn bin_op(l: Type, r: Type, return_t: Type) -> Type {
381    nd_func(
382        vec![
383            ParamTy::kw(Str::ever("lhs"), l),
384            ParamTy::kw(Str::ever("rhs"), r),
385        ],
386        None,
387        return_t,
388    )
389}
390
391pub fn proc(
392    non_default_params: Vec<ParamTy>,
393    var_params: Option<ParamTy>,
394    default_params: Vec<ParamTy>,
395    kw_var_params: Option<ParamTy>,
396    return_t: Type,
397) -> Type {
398    Type::Subr(SubrType::new(
399        SubrKind::Proc,
400        non_default_params,
401        var_params,
402        default_params,
403        kw_var_params,
404        return_t,
405    ))
406}
407
408pub fn no_var_proc(
409    non_default_params: Vec<ParamTy>,
410    default_params: Vec<ParamTy>,
411    return_t: Type,
412) -> Type {
413    proc(non_default_params, None, default_params, None, return_t)
414}
415
416pub fn proc0(return_t: Type) -> Type {
417    proc(vec![], None, vec![], None, return_t)
418}
419
420pub fn proc1(param_t: Type, return_t: Type) -> Type {
421    proc(vec![ParamTy::Pos(param_t)], None, vec![], None, return_t)
422}
423
424pub fn proc2(l: Type, r: Type, return_t: Type) -> Type {
425    proc(
426        vec![ParamTy::Pos(l), ParamTy::Pos(r)],
427        None,
428        vec![],
429        None,
430        return_t,
431    )
432}
433
434pub fn fn_met(
435    self_t: Type,
436    mut non_default_params: Vec<ParamTy>,
437    var_params: Option<ParamTy>,
438    default_params: Vec<ParamTy>,
439    kw_var_params: Option<ParamTy>,
440    return_t: Type,
441) -> Type {
442    non_default_params.insert(0, ParamTy::kw(Str::ever("self"), self_t));
443    Type::Subr(SubrType::new(
444        SubrKind::Func,
445        non_default_params,
446        var_params,
447        default_params,
448        kw_var_params,
449        return_t,
450    ))
451}
452
453pub fn no_var_fn_met(
454    self_t: Type,
455    non_default_params: Vec<ParamTy>,
456    default_params: Vec<ParamTy>,
457    return_t: Type,
458) -> Type {
459    fn_met(
460        self_t,
461        non_default_params,
462        None,
463        default_params,
464        None,
465        return_t,
466    )
467}
468
469pub fn fn0_met(self_t: Type, return_t: Type) -> Type {
470    fn_met(self_t, vec![], None, vec![], None, return_t)
471}
472
473pub fn fn1_met(self_t: Type, input_t: Type, return_t: Type) -> Type {
474    fn_met(
475        self_t,
476        vec![ParamTy::Pos(input_t)],
477        None,
478        vec![],
479        None,
480        return_t,
481    )
482}
483
484pub fn fn1_kw_met(self_t: Type, input: ParamTy, return_t: Type) -> Type {
485    fn_met(self_t, vec![input], None, vec![], None, return_t)
486}
487
488pub fn fn2_met(self_t: Type, l: Type, r: Type, return_t: Type) -> Type {
489    fn_met(
490        self_t,
491        vec![ParamTy::Pos(l), ParamTy::Pos(r)],
492        None,
493        vec![],
494        None,
495        return_t,
496    )
497}
498
499pub fn pr_met(
500    self_t: Type,
501    non_default_params: Vec<ParamTy>,
502    var_params: Option<ParamTy>,
503    default_params: Vec<ParamTy>,
504    return_t: Type,
505) -> Type {
506    kw_var_pr_met(
507        self_t,
508        non_default_params,
509        var_params,
510        default_params,
511        None,
512        return_t,
513    )
514}
515
516pub fn pr0_met(self_t: Type, return_t: Type) -> Type {
517    pr_met(self_t, vec![], None, vec![], return_t)
518}
519
520pub fn pr1_met(self_t: Type, input_t: Type, return_t: Type) -> Type {
521    pr_met(self_t, vec![ParamTy::Pos(input_t)], None, vec![], return_t)
522}
523
524pub fn pr1_kw_met(self_t: Type, input: ParamTy, return_t: Type) -> Type {
525    pr_met(self_t, vec![input], None, vec![], return_t)
526}
527
528pub fn kw_var_pr_met(
529    self_t: Type,
530    mut non_default_params: Vec<ParamTy>,
531    var_params: Option<ParamTy>,
532    default_params: Vec<ParamTy>,
533    kw_var_params: Option<ParamTy>,
534    return_t: Type,
535) -> Type {
536    non_default_params.insert(0, ParamTy::kw(Str::ever("self"), self_t));
537    Type::Subr(SubrType::new(
538        SubrKind::Proc,
539        non_default_params,
540        var_params,
541        default_params,
542        kw_var_params,
543        return_t,
544    ))
545}
546
547/// function type with non-default parameters
548#[inline]
549pub fn nd_func(params: Vec<ParamTy>, var_params: Option<ParamTy>, ret: Type) -> Type {
550    func(params, var_params, vec![], None, ret)
551}
552
553#[inline]
554pub fn nd_proc(params: Vec<ParamTy>, var_params: Option<ParamTy>, ret: Type) -> Type {
555    proc(params, var_params, vec![], None, ret)
556}
557
558#[inline]
559pub fn d_func(default_params: Vec<ParamTy>, return_t: Type) -> Type {
560    func(vec![], None, default_params, None, return_t)
561}
562
563#[inline]
564pub fn nd_proc1(pt: ParamTy, ret: Type) -> Type {
565    nd_proc(vec![pt], None, ret)
566}
567
568pub fn callable(param_ts: Vec<Type>, return_t: Type) -> Type {
569    Type::Callable {
570        param_ts,
571        return_t: Box::new(return_t),
572    }
573}
574
575#[inline]
576pub fn mono_q<S: Into<Str>>(name: S, constr: Constraint) -> Type {
577    named_free_var(name.into(), free::GENERIC_LEVEL, constr)
578}
579
580#[inline]
581pub fn type_q<S: Into<Str>>(name: S) -> Type {
582    mono_q(name, instanceof(Type::Type))
583}
584
585#[inline]
586pub fn subtype_q<S: Into<Str>>(name: S, sup: Type) -> Type {
587    mono_q(name, subtypeof(sup))
588}
589
590#[inline]
591pub fn mono<S: Into<Str>>(name: S) -> Type {
592    let name = name.into();
593    if cfg!(feature = "debug") {
594        // do not use for: `Int`, `Nat`, ...
595        match &name[..] {
596            "Obj" | "Int" | "Nat" | "Ratio" | "Float" | "Complex" | "Bool" | "Str" | "NoneType"
597            | "Code" | "Frame" | "Error" | "Inf" | "NegInf" | "Type" | "ClassType"
598            | "TraitType" | "Patch" | "NotImplementedType" | "Ellipsis" | "Never" => {
599                unreachable!("built-in type: {name}")
600            }
601            _ => {}
602        }
603    }
604    Type::Mono(name)
605}
606
607pub fn from_str(name: impl Into<Str>) -> Type {
608    let name = name.into();
609    match &name[..] {
610        "Obj" => Type::Obj,
611        "Int" => Type::Int,
612        "Nat" => Type::Nat,
613        "Ratio" => Type::Ratio,
614        "Float" => Type::Float,
615        "Complex" => Type::Complex,
616        "Bool" => Type::Bool,
617        "Str" => Type::Str,
618        "NoneType" => Type::NoneType,
619        "Code" => Type::Code,
620        "Frame" => Type::Frame,
621        "Error" => Type::Error,
622        "Inf" => Type::Inf,
623        "NegInf" => Type::NegInf,
624        "Type" => Type::Type,
625        "ClassType" => Type::ClassType,
626        "TraitType" => Type::TraitType,
627        "Patch" => Type::Patch,
628        "NotImplementedType" => Type::NotImplementedType,
629        "Ellipsis" => Type::Ellipsis,
630        "Never" => Type::Never,
631        _ => Type::Mono(name),
632    }
633}
634
635#[inline]
636pub fn poly<S: Into<Str>>(name: S, params: Vec<TyParam>) -> Type {
637    Type::Poly {
638        name: name.into(),
639        params,
640    }
641}
642
643pub fn type_poly<S: Into<Str>>(name: S, ts: Vec<Type>) -> Type {
644    poly(name, ts.into_iter().map(TyParam::t).collect())
645}
646
647#[inline]
648pub fn proj<S: Into<Str>>(lhs: Type, rhs: S) -> Type {
649    Type::Proj {
650        lhs: Box::new(lhs),
651        rhs: rhs.into(),
652    }
653}
654
655#[inline]
656pub fn proj_call<S: Into<Str>>(lhs: TyParam, attr_name: S, args: Vec<TyParam>) -> Type {
657    Type::ProjCall {
658        lhs: Box::new(lhs),
659        attr_name: attr_name.into(),
660        args,
661    }
662}
663
664/// ```erg
665/// {I: Int | I >= 0}
666/// => Refinement{
667///     layout: TyParam::MonoQ "I",
668///     bounds: [TyBound::Instance("I", "Int")],
669///     pred: Predicate::GreaterEqual("I", 0)
670/// }
671/// ```
672#[inline]
673pub fn refinement(var: Str, t: Type, pred: Predicate) -> Type {
674    Type::Refinement(RefinementType::new(var, t, pred))
675}
676
677pub fn and(lhs: Type, rhs: Type) -> Type {
678    lhs & rhs
679}
680
681pub fn or(lhs: Type, rhs: Type) -> Type {
682    lhs | rhs
683}
684
685pub fn ors(tys: impl IntoIterator<Item = Type>) -> Type {
686    tys.into_iter().fold(Type::Never, or)
687}
688
689pub fn ands(tys: impl IntoIterator<Item = Type>) -> Type {
690    tys.into_iter().fold(Type::Obj, and)
691}
692
693pub fn not(ty: Type) -> Type {
694    Type::Not(Box::new(ty))
695}
696
697pub fn guard(namespace: Str, target: CastTarget, to: Type) -> Type {
698    Type::Guard(GuardType::new(namespace, target, to))
699}
700
701pub fn bounded(sub: Type, sup: Type) -> Type {
702    if sub == Type::Never {
703        sup
704    } else {
705        Type::Bounded {
706            sub: Box::new(sub),
707            sup: Box::new(sup),
708        }
709    }
710}
711
712#[inline]
713pub fn instanceof(t: Type) -> Constraint {
714    Constraint::new_type_of(t)
715}
716
717/// Sub <: Sup
718#[inline]
719pub fn subtypeof(sup: Type) -> Constraint {
720    Constraint::new_sandwiched(Type::Never, sup)
721}
722
723#[inline]
724pub fn supertypeof(sub: Type) -> Constraint {
725    Constraint::new_sandwiched(sub, Type::Obj)
726}
727
728#[inline]
729pub fn mono_q_tp<S: Into<Str>>(name: S, constr: Constraint) -> TyParam {
730    TyParam::mono_q(name, constr)
731}
732
733#[inline]
734pub fn mono_tp<S: Into<Str>>(name: S) -> TyParam {
735    TyParam::mono(name)
736}
737
738#[inline]
739pub fn ty_tp(t: Type) -> TyParam {
740    TyParam::t(t)
741}
742
743/// NOTE: Always add postfix when entering numbers. For example, `value(1)` will be of type Int.
744#[inline]
745pub fn value<V: Into<ValueObj>>(v: V) -> TyParam {
746    TyParam::value(v)
747}