mirror of
https://github.com/erg-lang/erg.git
synced 2025-10-03 14:04:33 +00:00
Merge branch 'main' into pr/191
This commit is contained in:
commit
6b14add8f8
47 changed files with 1306 additions and 540 deletions
10
Cargo.lock
generated
10
Cargo.lock
generated
|
@ -15,7 +15,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "erg"
|
name = "erg"
|
||||||
version = "0.5.6"
|
version = "0.5.7-nightly.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"erg_common",
|
"erg_common",
|
||||||
"erg_compiler",
|
"erg_compiler",
|
||||||
|
@ -25,14 +25,14 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "erg_common"
|
name = "erg_common"
|
||||||
version = "0.5.6"
|
version = "0.5.7-nightly.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atty",
|
"atty",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "erg_compiler"
|
name = "erg_compiler"
|
||||||
version = "0.5.6"
|
version = "0.5.7-nightly.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"erg_common",
|
"erg_common",
|
||||||
"erg_parser",
|
"erg_parser",
|
||||||
|
@ -41,14 +41,14 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "erg_parser"
|
name = "erg_parser"
|
||||||
version = "0.5.6"
|
version = "0.5.7-nightly.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"erg_common",
|
"erg_common",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "erg_type"
|
name = "erg_type"
|
||||||
version = "0.5.6"
|
version = "0.5.7-nightly.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"erg_common",
|
"erg_common",
|
||||||
"erg_parser",
|
"erg_parser",
|
||||||
|
|
10
Cargo.toml
10
Cargo.toml
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "erg"
|
name = "erg"
|
||||||
version = "0.5.6"
|
version = "0.5.7-nightly.1"
|
||||||
description = "The Erg programming language"
|
description = "The Erg programming language"
|
||||||
authors = ["erg-lang team <moderation.erglang@gmail.com>"]
|
authors = ["erg-lang team <moderation.erglang@gmail.com>"]
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
|
@ -47,10 +47,10 @@ traditional_chinese = [
|
||||||
pre-commit = []
|
pre-commit = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
erg_common = { version = "0.5.6", path = "./compiler/erg_common" }
|
erg_common = { version = "0.5.7-nightly.1", path = "./compiler/erg_common" }
|
||||||
erg_parser = { version = "0.5.6", path = "./compiler/erg_parser" }
|
erg_parser = { version = "0.5.7-nightly.1", path = "./compiler/erg_parser" }
|
||||||
erg_compiler = { version = "0.5.6", path = "./compiler/erg_compiler" }
|
erg_compiler = { version = "0.5.7-nightly.1", path = "./compiler/erg_compiler" }
|
||||||
erg_type = { version = "0.5.6", path = "./compiler/erg_type" }
|
erg_type = { version = "0.5.7-nightly.1", path = "./compiler/erg_type" }
|
||||||
|
|
||||||
# [workspace]
|
# [workspace]
|
||||||
# member = ["cm", "dyne"]
|
# member = ["cm", "dyne"]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "erg_common"
|
name = "erg_common"
|
||||||
version = "0.5.6"
|
version = "0.5.7-nightly.1"
|
||||||
description = "A common components library of Erg"
|
description = "A common components library of Erg"
|
||||||
authors = ["erg-lang team <moderation.erglang@gmail.com>"]
|
authors = ["erg-lang team <moderation.erglang@gmail.com>"]
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
|
|
|
@ -93,7 +93,7 @@ impl Input {
|
||||||
let mut codes = vec![];
|
let mut codes = vec![];
|
||||||
let mut lines = BufReader::new(file).lines().skip(ln_begin - 1);
|
let mut lines = BufReader::new(file).lines().skip(ln_begin - 1);
|
||||||
for _ in ln_begin..=ln_end {
|
for _ in ln_begin..=ln_end {
|
||||||
codes.push(lines.next().unwrap().unwrap());
|
codes.push(lines.next().unwrap_or_else(|| Ok("".to_string())).unwrap());
|
||||||
}
|
}
|
||||||
codes
|
codes
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,6 +114,20 @@ use ErrorKind::*;
|
||||||
|
|
||||||
impl_display_from_debug!(ErrorKind);
|
impl_display_from_debug!(ErrorKind);
|
||||||
|
|
||||||
|
impl ErrorKind {
|
||||||
|
pub fn is_warning(&self) -> bool {
|
||||||
|
(60..=100).contains(&(*self as u8)) || (180..=200).contains(&(*self as u8))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_error(&self) -> bool {
|
||||||
|
(0..=59).contains(&(*self as u8)) || (100..=179).contains(&(*self as u8))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_exception(&self) -> bool {
|
||||||
|
(200..=255).contains(&(*self as u8))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<&str> for ErrorKind {
|
impl From<&str> for ErrorKind {
|
||||||
fn from(s: &str) -> ErrorKind {
|
fn from(s: &str) -> ErrorKind {
|
||||||
match s {
|
match s {
|
||||||
|
@ -467,10 +481,9 @@ pub trait ErrorDisplay {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn format_header(&self) -> String {
|
fn format_header(&self) -> String {
|
||||||
let kind = self.core().kind as u8;
|
let (color, err_or_warn) = if self.core().kind.is_warning() {
|
||||||
let (color, err_or_warn) = if (60..=100).contains(&kind) || (180..=200).contains(&kind) {
|
|
||||||
(YELLOW, "Warning")
|
(YELLOW, "Warning")
|
||||||
} else if kind >= 200 {
|
} else if self.core().kind.is_exception() {
|
||||||
("", "Exception")
|
("", "Exception")
|
||||||
} else {
|
} else {
|
||||||
(RED, "Error")
|
(RED, "Error")
|
||||||
|
|
|
@ -177,6 +177,10 @@ impl<T: Hash + Eq> Set<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Hash + Eq + Clone> Set<T> {
|
impl<T: Hash + Eq + Clone> Set<T> {
|
||||||
|
/// ```
|
||||||
|
/// # use erg_common::set;
|
||||||
|
/// assert_eq!(set!{1, 2, 3}.union(&set!{2, 3, 4}), set!{1, 2, 3, 4});
|
||||||
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn union(&self, other: &Set<T>) -> Set<T> {
|
pub fn union(&self, other: &Set<T>) -> Set<T> {
|
||||||
let u = self.elems.union(&other.elems);
|
let u = self.elems.union(&other.elems);
|
||||||
|
@ -185,6 +189,10 @@ impl<T: Hash + Eq + Clone> Set<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// ```
|
||||||
|
/// # use erg_common::set;
|
||||||
|
/// assert_eq!(set!{1, 2, 3}.intersection(&set!{2, 3, 4}), set!{2, 3});
|
||||||
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn intersection(&self, other: &Set<T>) -> Set<T> {
|
pub fn intersection(&self, other: &Set<T>) -> Set<T> {
|
||||||
let u = self.elems.intersection(&other.elems);
|
let u = self.elems.intersection(&other.elems);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "erg_compiler"
|
name = "erg_compiler"
|
||||||
version = "0.5.6"
|
version = "0.5.7-nightly.1"
|
||||||
description = "Centimetre: the Erg compiler"
|
description = "Centimetre: the Erg compiler"
|
||||||
authors = ["erg-lang team <moderation.erglang@gmail.com>"]
|
authors = ["erg-lang team <moderation.erglang@gmail.com>"]
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
|
@ -17,9 +17,9 @@ simplified_chinese = [ "erg_common/simplified_chinese", "erg_parser/simplified_c
|
||||||
traditional_chinese = [ "erg_common/traditional_chinese", "erg_parser/traditional_chinese", "erg_type/traditional_chinese" ]
|
traditional_chinese = [ "erg_common/traditional_chinese", "erg_parser/traditional_chinese", "erg_type/traditional_chinese" ]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
erg_common = { version = "0.5.6", path = "../erg_common" }
|
erg_common = { version = "0.5.7-nightly.1", path = "../erg_common" }
|
||||||
erg_parser = { version = "0.5.6", path = "../erg_parser" }
|
erg_parser = { version = "0.5.7-nightly.1", path = "../erg_parser" }
|
||||||
erg_type = { version = "0.5.6", path = "../erg_type" }
|
erg_type = { version = "0.5.7-nightly.1", path = "../erg_type" }
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
path = "lib.rs"
|
path = "lib.rs"
|
||||||
|
|
|
@ -207,7 +207,7 @@ fn is_fake_method(class: &str, name: &str) -> bool {
|
||||||
matches!(
|
matches!(
|
||||||
(class, name),
|
(class, name),
|
||||||
(
|
(
|
||||||
"Complex" | "Float" | "Ratio" | "Int" | "Nat" | "Bool",
|
_, // "Complex" | "Float" | "Ratio" | "Int" | "Nat" | "Bool",
|
||||||
"abs"
|
"abs"
|
||||||
) | (_, "iter")
|
) | (_, "iter")
|
||||||
| (_, "map")
|
| (_, "map")
|
||||||
|
@ -1205,6 +1205,17 @@ impl CodeGenerator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn emit_del_instr(&mut self, mut args: Args) {
|
||||||
|
let ident = enum_unwrap!(args.remove_left_or_key("obj").unwrap(), Expr::Accessor:(Accessor::Ident:(_)));
|
||||||
|
log!(info "entered {} ({ident})", fn_name!());
|
||||||
|
let escaped = escape_name(ident);
|
||||||
|
let name = self
|
||||||
|
.local_search(&escaped, Name)
|
||||||
|
.unwrap_or_else(|| self.register_name(escaped));
|
||||||
|
self.write_instr(DELETE_NAME);
|
||||||
|
self.write_arg(name.idx as u8);
|
||||||
|
}
|
||||||
|
|
||||||
fn emit_discard_instr(&mut self, mut args: Args) {
|
fn emit_discard_instr(&mut self, mut args: Args) {
|
||||||
log!(info "entered {}", fn_name!());
|
log!(info "entered {}", fn_name!());
|
||||||
while let Some(arg) = args.try_remove(0) {
|
while let Some(arg) = args.try_remove(0) {
|
||||||
|
@ -1448,6 +1459,7 @@ impl CodeGenerator {
|
||||||
log!(info "entered {}", fn_name!());
|
log!(info "entered {}", fn_name!());
|
||||||
match &local.inspect()[..] {
|
match &local.inspect()[..] {
|
||||||
"assert" => self.emit_assert_instr(args),
|
"assert" => self.emit_assert_instr(args),
|
||||||
|
"Del" => self.emit_del_instr(args),
|
||||||
"discard" => self.emit_discard_instr(args),
|
"discard" => self.emit_discard_instr(args),
|
||||||
"for" | "for!" => self.emit_for_instr(args),
|
"for" | "for!" => self.emit_for_instr(args),
|
||||||
"if" | "if!" => self.emit_if_instr(args),
|
"if" | "if!" => self.emit_if_instr(args),
|
||||||
|
|
|
@ -278,6 +278,11 @@ impl Context {
|
||||||
if let Some((_, ty_ctx)) = self.get_nominal_type_ctx(rhs) {
|
if let Some((_, ty_ctx)) = self.get_nominal_type_ctx(rhs) {
|
||||||
for rhs_sup in ty_ctx.super_classes.iter() {
|
for rhs_sup in ty_ctx.super_classes.iter() {
|
||||||
let rhs_sup = if rhs_sup.has_qvar() {
|
let rhs_sup = if rhs_sup.has_qvar() {
|
||||||
|
let rhs = match rhs {
|
||||||
|
Type::Ref(t) => t,
|
||||||
|
Type::RefMut { before, .. } => before,
|
||||||
|
other => other,
|
||||||
|
};
|
||||||
let subst_ctx = SubstContext::new(rhs, ty_ctx);
|
let subst_ctx = SubstContext::new(rhs, ty_ctx);
|
||||||
subst_ctx
|
subst_ctx
|
||||||
.substitute(rhs_sup.clone(), self, Location::Unknown)
|
.substitute(rhs_sup.clone(), self, Location::Unknown)
|
||||||
|
@ -311,6 +316,11 @@ impl Context {
|
||||||
if let Some((_, rhs_ctx)) = self.get_nominal_type_ctx(rhs) {
|
if let Some((_, rhs_ctx)) = self.get_nominal_type_ctx(rhs) {
|
||||||
for rhs_sup in rhs_ctx.super_traits.iter() {
|
for rhs_sup in rhs_ctx.super_traits.iter() {
|
||||||
let rhs_sup = if rhs_sup.has_qvar() {
|
let rhs_sup = if rhs_sup.has_qvar() {
|
||||||
|
let rhs = match rhs {
|
||||||
|
Type::Ref(t) => t,
|
||||||
|
Type::RefMut { before, .. } => before,
|
||||||
|
other => other,
|
||||||
|
};
|
||||||
let subst_ctx = SubstContext::new(rhs, rhs_ctx);
|
let subst_ctx = SubstContext::new(rhs, rhs_ctx);
|
||||||
subst_ctx
|
subst_ctx
|
||||||
.substitute(rhs_sup.clone(), self, Location::Unknown)
|
.substitute(rhs_sup.clone(), self, Location::Unknown)
|
||||||
|
@ -638,8 +648,26 @@ impl Context {
|
||||||
(l, MonoQVar(name)) | (l, PolyQVar { name, .. }) => {
|
(l, MonoQVar(name)) | (l, PolyQVar { name, .. }) => {
|
||||||
panic!("internal error: not instantiated type variable: '{name}, l: {l}")
|
panic!("internal error: not instantiated type variable: '{name}, l: {l}")
|
||||||
}
|
}
|
||||||
(MonoProj { .. }, _) => todo!(),
|
(MonoProj { .. }, _) => {
|
||||||
(_, MonoProj { .. }) => todo!(),
|
if let Some(cands) = self.get_candidates(lhs) {
|
||||||
|
for cand in cands.into_iter() {
|
||||||
|
if self.supertype_of(&cand, rhs) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
(_, MonoProj { .. }) => {
|
||||||
|
if let Some(cands) = self.get_candidates(rhs) {
|
||||||
|
for cand in cands.into_iter() {
|
||||||
|
if self.supertype_of(lhs, &cand) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
(_l, _r) => false,
|
(_l, _r) => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -810,13 +838,19 @@ impl Context {
|
||||||
|
|
||||||
/// returns union of two types (A or B)
|
/// returns union of two types (A or B)
|
||||||
pub(crate) fn union(&self, lhs: &Type, rhs: &Type) -> Type {
|
pub(crate) fn union(&self, lhs: &Type, rhs: &Type) -> Type {
|
||||||
|
// ?T or ?U will not be unified
|
||||||
|
if lhs.has_no_unbound_var() && rhs.has_no_unbound_var() {
|
||||||
match (self.supertype_of(lhs, rhs), self.subtype_of(lhs, rhs)) {
|
match (self.supertype_of(lhs, rhs), self.subtype_of(lhs, rhs)) {
|
||||||
(true, true) => return lhs.clone(), // lhs = rhs
|
(true, true) => return lhs.clone(), // lhs = rhs
|
||||||
(true, false) => return lhs.clone(), // lhs :> rhs
|
(true, false) => return lhs.clone(), // lhs :> rhs
|
||||||
(false, true) => return rhs.clone(),
|
(false, true) => return rhs.clone(),
|
||||||
(false, false) => {}
|
(false, false) => {}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
match (lhs, rhs) {
|
match (lhs, rhs) {
|
||||||
|
(FreeVar(lfv), FreeVar(rfv)) if lfv.is_linked() && rfv.is_linked() => {
|
||||||
|
self.union(&lfv.crack(), &rfv.crack())
|
||||||
|
}
|
||||||
(Refinement(l), Refinement(r)) => Type::Refinement(self.union_refinement(l, r)),
|
(Refinement(l), Refinement(r)) => Type::Refinement(self.union_refinement(l, r)),
|
||||||
(t, Type::Never) | (Type::Never, t) => t.clone(),
|
(t, Type::Never) | (Type::Never, t) => t.clone(),
|
||||||
(t, Refinement(r)) | (Refinement(r), t) => {
|
(t, Refinement(r)) | (Refinement(r), t) => {
|
||||||
|
@ -842,16 +876,19 @@ impl Context {
|
||||||
|
|
||||||
/// returns intersection of two types (A and B)
|
/// returns intersection of two types (A and B)
|
||||||
pub(crate) fn intersection(&self, lhs: &Type, rhs: &Type) -> Type {
|
pub(crate) fn intersection(&self, lhs: &Type, rhs: &Type) -> Type {
|
||||||
|
// ?T and ?U will not be unified
|
||||||
|
if !lhs.is_unbound_var() && !rhs.is_unbound_var() {
|
||||||
match (self.supertype_of(lhs, rhs), self.subtype_of(lhs, rhs)) {
|
match (self.supertype_of(lhs, rhs), self.subtype_of(lhs, rhs)) {
|
||||||
(true, true) => return lhs.clone(), // lhs = rhs
|
(true, true) => return lhs.clone(), // lhs = rhs
|
||||||
(true, false) => return rhs.clone(), // lhs :> rhs
|
(true, false) => return rhs.clone(), // lhs :> rhs
|
||||||
(false, true) => return lhs.clone(),
|
(false, true) => return lhs.clone(),
|
||||||
(false, false) => {}
|
(false, false) => {}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
match (lhs, rhs) {
|
match (lhs, rhs) {
|
||||||
/*(Type::FreeVar(_), _) | (_, Type::FreeVar(_)) => {
|
(FreeVar(lfv), FreeVar(rfv)) if lfv.is_linked() && rfv.is_linked() => {
|
||||||
todo!()
|
self.intersection(&lfv.crack(), &rfv.crack())
|
||||||
}*/
|
}
|
||||||
// {.i = Int} and {.s = Str} == {.i = Int; .s = Str}
|
// {.i = Int} and {.s = Str} == {.i = Int; .s = Str}
|
||||||
(Type::Record(l), Type::Record(r)) => Type::Record(l.clone().concat(r.clone())),
|
(Type::Record(l), Type::Record(r)) => Type::Record(l.clone().concat(r.clone())),
|
||||||
(l, r) if self.is_trait(l) && self.is_trait(r) => and(l.clone(), r.clone()),
|
(l, r) if self.is_trait(l) && self.is_trait(r) => and(l.clone(), r.clone()),
|
||||||
|
@ -1008,7 +1045,7 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn max<'t>(&self, lhs: &'t Type, rhs: &'t Type) -> Option<&'t Type> {
|
pub(crate) fn _max<'t>(&self, lhs: &'t Type, rhs: &'t Type) -> Option<&'t Type> {
|
||||||
// 同じならどちらを返しても良い
|
// 同じならどちらを返しても良い
|
||||||
match (self.supertype_of(lhs, rhs), self.subtype_of(lhs, rhs)) {
|
match (self.supertype_of(lhs, rhs), self.subtype_of(lhs, rhs)) {
|
||||||
(true, true) | (true, false) => Some(lhs),
|
(true, true) | (true, false) => Some(lhs),
|
||||||
|
|
|
@ -2,6 +2,7 @@ use std::fmt;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
use erg_common::dict::Dict;
|
use erg_common::dict::Dict;
|
||||||
|
use erg_common::enum_unwrap;
|
||||||
use erg_common::error::Location;
|
use erg_common::error::Location;
|
||||||
use erg_common::set::Set;
|
use erg_common::set::Set;
|
||||||
use erg_common::shared::Shared;
|
use erg_common::shared::Shared;
|
||||||
|
@ -15,19 +16,18 @@ use erg_parser::ast::*;
|
||||||
use erg_parser::token::{Token, TokenKind};
|
use erg_parser::token::{Token, TokenKind};
|
||||||
|
|
||||||
use erg_type::constructors::{
|
use erg_type::constructors::{
|
||||||
and, builtin_mono, builtin_poly, mono_proj, not, or, poly, ref_, ref_mut, refinement, subr_t,
|
builtin_mono, builtin_poly, mono_proj, not, poly, ref_, ref_mut, refinement, subr_t, v_enum,
|
||||||
v_enum,
|
|
||||||
};
|
};
|
||||||
use erg_type::typaram::{OpKind, TyParam};
|
use erg_type::typaram::{OpKind, TyParam};
|
||||||
use erg_type::value::ValueObj;
|
use erg_type::value::ValueObj;
|
||||||
use erg_type::{
|
use erg_type::{ConstSubr, HasType, Predicate, SubrKind, TyBound, Type, UserConstSubr, ValueArgs};
|
||||||
ConstSubr, HasType, ParamTy, Predicate, SubrKind, TyBound, Type, UserConstSubr, ValueArgs,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::context::instantiate::TyVarContext;
|
use crate::context::instantiate::TyVarContext;
|
||||||
use crate::context::{ClassDefType, Context, ContextKind, RegistrationMode};
|
use crate::context::{ClassDefType, Context, ContextKind, RegistrationMode};
|
||||||
use crate::error::{EvalError, EvalErrors, EvalResult, SingleEvalResult, TyCheckResult};
|
use crate::error::{EvalError, EvalErrors, EvalResult, SingleEvalResult, TyCheckResult};
|
||||||
|
|
||||||
|
use super::Variance;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn type_from_token_kind(kind: TokenKind) -> Type {
|
pub fn type_from_token_kind(kind: TokenKind) -> Type {
|
||||||
use TokenKind::*;
|
use TokenKind::*;
|
||||||
|
@ -72,6 +72,34 @@ fn try_get_op_kind_from_token(kind: TokenKind) -> EvalResult<OpKind> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn op_to_name(op: OpKind) -> &'static str {
|
||||||
|
match op {
|
||||||
|
OpKind::Add => "__add__",
|
||||||
|
OpKind::Sub => "__sub__",
|
||||||
|
OpKind::Mul => "__mul__",
|
||||||
|
OpKind::Div => "__div__",
|
||||||
|
OpKind::Mod => "__mod__",
|
||||||
|
OpKind::Pow => "__pow__",
|
||||||
|
OpKind::Pos => "__pos__",
|
||||||
|
OpKind::Neg => "__neg__",
|
||||||
|
OpKind::Eq => "__eq__",
|
||||||
|
OpKind::Ne => "__ne__",
|
||||||
|
OpKind::Lt => "__lt__",
|
||||||
|
OpKind::Le => "__le__",
|
||||||
|
OpKind::Gt => "__gt__",
|
||||||
|
OpKind::Ge => "__ge__",
|
||||||
|
OpKind::And => "__and__",
|
||||||
|
OpKind::Or => "__or__",
|
||||||
|
OpKind::Invert => "__invert__",
|
||||||
|
OpKind::BitAnd => "__bitand__",
|
||||||
|
OpKind::BitOr => "__bitor__",
|
||||||
|
OpKind::BitXor => "__bitxor__",
|
||||||
|
OpKind::Shl => "__shl__",
|
||||||
|
OpKind::Shr => "__shr__",
|
||||||
|
OpKind::Mutate => "__mutate__",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) fn eval_lit(lit: &Literal) -> ValueObj {
|
pub(crate) fn eval_lit(lit: &Literal) -> ValueObj {
|
||||||
let t = type_from_token_kind(lit.token.kind);
|
let t = type_from_token_kind(lit.token.kind);
|
||||||
|
@ -104,7 +132,13 @@ impl SubstContext {
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map_or_else(|| Str::ever("_"), |n| n.inspect().clone())
|
.map_or_else(|| Str::ever("_"), |n| n.inspect().clone())
|
||||||
});
|
});
|
||||||
assert_eq!(param_names.len(), substituted.typarams().len());
|
if param_names.len() != substituted.typarams().len() {
|
||||||
|
let param_names = param_names.collect::<Vec<_>>();
|
||||||
|
panic!(
|
||||||
|
"{param_names:?} != {}",
|
||||||
|
erg_common::fmt_vec(&substituted.typarams())
|
||||||
|
);
|
||||||
|
}
|
||||||
// REVIEW: 順番は保証されるか? 引数がunnamed_paramsに入る可能性は?
|
// REVIEW: 順番は保証されるか? 引数がunnamed_paramsに入る可能性は?
|
||||||
SubstContext {
|
SubstContext {
|
||||||
bounds,
|
bounds,
|
||||||
|
@ -464,36 +498,20 @@ impl Context {
|
||||||
let tv_ctx = TyVarContext::new(self.level, bounds, self);
|
let tv_ctx = TyVarContext::new(self.level, bounds, self);
|
||||||
let mut non_default_params = Vec::with_capacity(lambda.sig.params.non_defaults.len());
|
let mut non_default_params = Vec::with_capacity(lambda.sig.params.non_defaults.len());
|
||||||
for sig in lambda.sig.params.non_defaults.iter() {
|
for sig in lambda.sig.params.non_defaults.iter() {
|
||||||
let t =
|
let pt =
|
||||||
self.instantiate_param_sig_t(sig, None, Some(&tv_ctx), RegistrationMode::Normal)?;
|
self.instantiate_param_ty(sig, None, Some(&tv_ctx), RegistrationMode::Normal)?;
|
||||||
let pt = if let Some(name) = sig.inspect() {
|
|
||||||
ParamTy::kw(name.clone(), t)
|
|
||||||
} else {
|
|
||||||
ParamTy::anonymous(t)
|
|
||||||
};
|
|
||||||
non_default_params.push(pt);
|
non_default_params.push(pt);
|
||||||
}
|
}
|
||||||
let var_params = if let Some(p) = lambda.sig.params.var_args.as_ref() {
|
let var_params = if let Some(p) = lambda.sig.params.var_args.as_ref() {
|
||||||
let t =
|
let pt = self.instantiate_param_ty(p, None, Some(&tv_ctx), RegistrationMode::Normal)?;
|
||||||
self.instantiate_param_sig_t(p, None, Some(&tv_ctx), RegistrationMode::Normal)?;
|
|
||||||
let pt = if let Some(name) = p.inspect() {
|
|
||||||
ParamTy::kw(name.clone(), t)
|
|
||||||
} else {
|
|
||||||
ParamTy::anonymous(t)
|
|
||||||
};
|
|
||||||
Some(pt)
|
Some(pt)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
let mut default_params = Vec::with_capacity(lambda.sig.params.defaults.len());
|
let mut default_params = Vec::with_capacity(lambda.sig.params.defaults.len());
|
||||||
for sig in lambda.sig.params.defaults.iter() {
|
for sig in lambda.sig.params.defaults.iter() {
|
||||||
let t =
|
let pt =
|
||||||
self.instantiate_param_sig_t(sig, None, Some(&tv_ctx), RegistrationMode::Normal)?;
|
self.instantiate_param_ty(sig, None, Some(&tv_ctx), RegistrationMode::Normal)?;
|
||||||
let pt = if let Some(name) = sig.inspect() {
|
|
||||||
ParamTy::kw(name.clone(), t)
|
|
||||||
} else {
|
|
||||||
ParamTy::anonymous(t)
|
|
||||||
};
|
|
||||||
default_params.push(pt);
|
default_params.push(pt);
|
||||||
}
|
}
|
||||||
// HACK: should avoid cloning
|
// HACK: should avoid cloning
|
||||||
|
@ -661,28 +679,10 @@ impl Context {
|
||||||
(TyParam::Value(lhs), TyParam::Value(rhs)) => self
|
(TyParam::Value(lhs), TyParam::Value(rhs)) => self
|
||||||
.eval_bin(op, lhs.clone(), rhs.clone())
|
.eval_bin(op, lhs.clone(), rhs.clone())
|
||||||
.map(TyParam::value),
|
.map(TyParam::value),
|
||||||
(TyParam::FreeVar(fv), r) => {
|
(TyParam::FreeVar(fv), r) if fv.is_linked() => self.eval_bin_tp(op, &*fv.crack(), r),
|
||||||
if fv.is_linked() {
|
(TyParam::FreeVar(_), _) => Ok(TyParam::bin(op, lhs.clone(), rhs.clone())),
|
||||||
self.eval_bin_tp(op, &*fv.crack(), r)
|
(l, TyParam::FreeVar(fv)) if fv.is_linked() => self.eval_bin_tp(op, l, &*fv.crack()),
|
||||||
} else {
|
(_, TyParam::FreeVar(_)) => Ok(TyParam::bin(op, lhs.clone(), rhs.clone())),
|
||||||
Err(EvalErrors::from(EvalError::unreachable(
|
|
||||||
self.cfg.input.clone(),
|
|
||||||
fn_name!(),
|
|
||||||
line!(),
|
|
||||||
)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(l, TyParam::FreeVar(fv)) => {
|
|
||||||
if fv.is_linked() {
|
|
||||||
self.eval_bin_tp(op, l, &*fv.crack())
|
|
||||||
} else {
|
|
||||||
Err(EvalErrors::from(EvalError::unreachable(
|
|
||||||
self.cfg.input.clone(),
|
|
||||||
fn_name!(),
|
|
||||||
line!(),
|
|
||||||
)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(e @ TyParam::Erased(_), _) | (_, e @ TyParam::Erased(_)) => Ok(e.clone()),
|
(e @ TyParam::Erased(_), _) | (_, e @ TyParam::Erased(_)) => Ok(e.clone()),
|
||||||
(l, r) => todo!("{l} {op} {r}"),
|
(l, r) => todo!("{l} {op} {r}"),
|
||||||
}
|
}
|
||||||
|
@ -845,6 +845,32 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if lhs.is_unbound_var() {
|
||||||
|
let (sub, sup) = enum_unwrap!(lhs.as_ref(), Type::FreeVar)
|
||||||
|
.get_bound_types()
|
||||||
|
.unwrap();
|
||||||
|
if self.is_trait(&sup) && !self.trait_impl_exists(&sub, &sup) {
|
||||||
|
return Err(EvalErrors::from(EvalError::no_trait_impl_error(
|
||||||
|
self.cfg.input.clone(),
|
||||||
|
line!() as usize,
|
||||||
|
&sub,
|
||||||
|
&sup,
|
||||||
|
t_loc,
|
||||||
|
self.caused_by(),
|
||||||
|
None,
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if the target can't be found in the supertype, the type will be dereferenced.
|
||||||
|
// In many cases, it is still better to determine the type variable than if the target is not found.
|
||||||
|
let coerced = self.deref_tyvar(*lhs.clone(), Variance::Covariant, t_loc)?;
|
||||||
|
if lhs.as_ref() != &coerced {
|
||||||
|
let proj = mono_proj(coerced, rhs);
|
||||||
|
self.eval_t_params(proj, level, t_loc).map(|t| {
|
||||||
|
self.coerce(&lhs);
|
||||||
|
t
|
||||||
|
})
|
||||||
|
} else {
|
||||||
let proj = mono_proj(*lhs, rhs);
|
let proj = mono_proj(*lhs, rhs);
|
||||||
Err(EvalErrors::from(EvalError::no_candidate_error(
|
Err(EvalErrors::from(EvalError::no_candidate_error(
|
||||||
self.cfg.input.clone(),
|
self.cfg.input.clone(),
|
||||||
|
@ -855,6 +881,7 @@ impl Context {
|
||||||
self.get_no_candidate_hint(&proj),
|
self.get_no_candidate_hint(&proj),
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Type::Ref(l) => Ok(ref_(self.eval_t_params(*l, level, t_loc)?)),
|
Type::Ref(l) => Ok(ref_(self.eval_t_params(*l, level, t_loc)?)),
|
||||||
Type::RefMut { before, after } => {
|
Type::RefMut { before, after } => {
|
||||||
let before = self.eval_t_params(*before, level, t_loc)?;
|
let before = self.eval_t_params(*before, level, t_loc)?;
|
||||||
|
@ -884,12 +911,12 @@ impl Context {
|
||||||
Type::And(l, r) => {
|
Type::And(l, r) => {
|
||||||
let l = self.eval_t_params(*l, level, t_loc)?;
|
let l = self.eval_t_params(*l, level, t_loc)?;
|
||||||
let r = self.eval_t_params(*r, level, t_loc)?;
|
let r = self.eval_t_params(*r, level, t_loc)?;
|
||||||
Ok(and(l, r))
|
Ok(self.intersection(&l, &r))
|
||||||
}
|
}
|
||||||
Type::Or(l, r) => {
|
Type::Or(l, r) => {
|
||||||
let l = self.eval_t_params(*l, level, t_loc)?;
|
let l = self.eval_t_params(*l, level, t_loc)?;
|
||||||
let r = self.eval_t_params(*r, level, t_loc)?;
|
let r = self.eval_t_params(*r, level, t_loc)?;
|
||||||
Ok(or(l, r))
|
Ok(self.union(&l, &r))
|
||||||
}
|
}
|
||||||
Type::Not(l, r) => {
|
Type::Not(l, r) => {
|
||||||
let l = self.eval_t_params(*l, level, t_loc)?;
|
let l = self.eval_t_params(*l, level, t_loc)?;
|
||||||
|
@ -971,6 +998,10 @@ impl Context {
|
||||||
OpKind::Mutate => Ok(self.get_tp_t(&val)?.mutate()),
|
OpKind::Mutate => Ok(self.get_tp_t(&val)?.mutate()),
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
},
|
},
|
||||||
|
TyParam::BinOp { op, lhs, rhs } => {
|
||||||
|
let op_name = op_to_name(op);
|
||||||
|
todo!("get type: {op_name}({lhs}, {rhs})")
|
||||||
|
}
|
||||||
other => todo!("{other}"),
|
other => todo!("{other}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,9 @@ use erg_parser::ast::VarName;
|
||||||
|
|
||||||
use crate::context::initialize::const_func::*;
|
use crate::context::initialize::const_func::*;
|
||||||
use crate::context::instantiate::{ConstTemplate, TyVarContext};
|
use crate::context::instantiate::{ConstTemplate, TyVarContext};
|
||||||
use crate::context::{ClassDefType, Context, ContextKind, DefaultInfo, ParamSpec, TraitInstance};
|
use crate::context::{
|
||||||
|
ClassDefType, Context, ContextKind, DefaultInfo, MethodType, ParamSpec, TraitInstance,
|
||||||
|
};
|
||||||
use crate::mod_cache::SharedModuleCache;
|
use crate::mod_cache::SharedModuleCache;
|
||||||
use crate::varinfo::{Mutability, VarInfo, VarKind};
|
use crate::varinfo::{Mutability, VarInfo, VarKind};
|
||||||
use DefaultInfo::*;
|
use DefaultInfo::*;
|
||||||
|
@ -77,6 +79,7 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// FIXME: トレイトの汎化型を指定するのにも使っているので、この名前は適当でない
|
||||||
pub(crate) fn register_superclass(&mut self, sup: Type, sup_ctx: &Context) {
|
pub(crate) fn register_superclass(&mut self, sup: Type, sup_ctx: &Context) {
|
||||||
self.super_classes.push(sup);
|
self.super_classes.push(sup);
|
||||||
self.super_classes.extend(sup_ctx.super_classes.clone());
|
self.super_classes.extend(sup_ctx.super_classes.clone());
|
||||||
|
@ -114,23 +117,33 @@ impl Context {
|
||||||
.insert(name.clone(), ValueObj::builtin_t(t.clone()));
|
.insert(name.clone(), ValueObj::builtin_t(t.clone()));
|
||||||
for impl_trait in ctx.super_traits.iter() {
|
for impl_trait in ctx.super_traits.iter() {
|
||||||
if let Some(impls) = self.trait_impls.get_mut(&impl_trait.name()) {
|
if let Some(impls) = self.trait_impls.get_mut(&impl_trait.name()) {
|
||||||
impls.push(TraitInstance::new(t.clone(), impl_trait.clone()));
|
impls.insert(TraitInstance::new(t.clone(), impl_trait.clone()));
|
||||||
} else {
|
} else {
|
||||||
self.trait_impls.insert(
|
self.trait_impls.insert(
|
||||||
impl_trait.name(),
|
impl_trait.name(),
|
||||||
vec![TraitInstance::new(t.clone(), impl_trait.clone())],
|
set![TraitInstance::new(t.clone(), impl_trait.clone())],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ctx.kind == ContextKind::Trait {
|
for (trait_method, vi) in ctx.decls.iter() {
|
||||||
for method in ctx.decls.keys() {
|
if let Some(types) = self.method_to_traits.get_mut(trait_method.inspect()) {
|
||||||
if let Some(traits) = self.method_traits.get_mut(method.inspect()) {
|
types.push(MethodType::new(t.clone(), vi.t.clone()));
|
||||||
traits.push(t.clone());
|
|
||||||
} else {
|
} else {
|
||||||
self.method_traits
|
self.method_to_traits.insert(
|
||||||
.insert(method.inspect().clone(), vec![t.clone()]);
|
trait_method.inspect().clone(),
|
||||||
|
vec![MethodType::new(t.clone(), vi.t.clone())],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (class_method, vi) in ctx.locals.iter() {
|
||||||
|
if let Some(types) = self.method_to_classes.get_mut(class_method.inspect()) {
|
||||||
|
types.push(MethodType::new(t.clone(), vi.t.clone()));
|
||||||
|
} else {
|
||||||
|
self.method_to_classes.insert(
|
||||||
|
class_method.inspect().clone(),
|
||||||
|
vec![MethodType::new(t.clone(), vi.t.clone())],
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self.mono_types.insert(name, (t, ctx));
|
self.mono_types.insert(name, (t, ctx));
|
||||||
}
|
}
|
||||||
|
@ -155,23 +168,33 @@ impl Context {
|
||||||
.insert(name.clone(), ValueObj::builtin_t(t.clone()));
|
.insert(name.clone(), ValueObj::builtin_t(t.clone()));
|
||||||
for impl_trait in ctx.super_traits.iter() {
|
for impl_trait in ctx.super_traits.iter() {
|
||||||
if let Some(impls) = self.trait_impls.get_mut(&impl_trait.name()) {
|
if let Some(impls) = self.trait_impls.get_mut(&impl_trait.name()) {
|
||||||
impls.push(TraitInstance::new(t.clone(), impl_trait.clone()));
|
impls.insert(TraitInstance::new(t.clone(), impl_trait.clone()));
|
||||||
} else {
|
} else {
|
||||||
self.trait_impls.insert(
|
self.trait_impls.insert(
|
||||||
impl_trait.name(),
|
impl_trait.name(),
|
||||||
vec![TraitInstance::new(t.clone(), impl_trait.clone())],
|
set![TraitInstance::new(t.clone(), impl_trait.clone())],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ctx.kind == ContextKind::Trait {
|
for (trait_method, vi) in ctx.decls.iter() {
|
||||||
for method in ctx.decls.keys() {
|
if let Some(traits) = self.method_to_traits.get_mut(trait_method.inspect()) {
|
||||||
if let Some(traits) = self.method_traits.get_mut(method.inspect()) {
|
traits.push(MethodType::new(t.clone(), vi.t.clone()));
|
||||||
traits.push(t.clone());
|
|
||||||
} else {
|
} else {
|
||||||
self.method_traits
|
self.method_to_traits.insert(
|
||||||
.insert(method.inspect().clone(), vec![t.clone()]);
|
trait_method.inspect().clone(),
|
||||||
|
vec![MethodType::new(t.clone(), vi.t.clone())],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (class_method, vi) in ctx.locals.iter() {
|
||||||
|
if let Some(types) = self.method_to_classes.get_mut(class_method.inspect()) {
|
||||||
|
types.push(MethodType::new(t.clone(), vi.t.clone()));
|
||||||
|
} else {
|
||||||
|
self.method_to_classes.insert(
|
||||||
|
class_method.inspect().clone(),
|
||||||
|
vec![MethodType::new(t.clone(), vi.t.clone())],
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self.poly_types.insert(name, (t, ctx));
|
self.poly_types.insert(name, (t, ctx));
|
||||||
}
|
}
|
||||||
|
@ -209,7 +232,7 @@ impl Context {
|
||||||
let named = Self::builtin_mono_trait("Named", 2);
|
let named = Self::builtin_mono_trait("Named", 2);
|
||||||
let mut mutable = Self::builtin_mono_trait("Mutable", 2);
|
let mut mutable = Self::builtin_mono_trait("Mutable", 2);
|
||||||
let proj = mono_proj(mono_q("Self"), "ImmutType");
|
let proj = mono_proj(mono_q("Self"), "ImmutType");
|
||||||
let f_t = func(vec![param_t("old", proj.clone())], None, vec![], proj);
|
let f_t = func(vec![kw("old", proj.clone())], None, vec![], proj);
|
||||||
let t = pr1_met(ref_mut(mono_q("Self"), None), f_t, NoneType);
|
let t = pr1_met(ref_mut(mono_q("Self"), None), f_t, NoneType);
|
||||||
let t = quant(
|
let t = quant(
|
||||||
t,
|
t,
|
||||||
|
@ -229,7 +252,7 @@ impl Context {
|
||||||
ref_mut(mono_q("Self"), None),
|
ref_mut(mono_q("Self"), None),
|
||||||
vec![],
|
vec![],
|
||||||
None,
|
None,
|
||||||
vec![param_t("n", Int)],
|
vec![kw("n", Int)],
|
||||||
Str,
|
Str,
|
||||||
);
|
);
|
||||||
let t_read = quant(
|
let t_read = quant(
|
||||||
|
@ -540,7 +563,6 @@ impl Context {
|
||||||
ratio.register_trait(Ratio, builtin_mono("Show"), ratio_show);
|
ratio.register_trait(Ratio, builtin_mono("Show"), ratio_show);
|
||||||
let mut int = Self::builtin_mono_class("Int", 2);
|
let mut int = Self::builtin_mono_class("Int", 2);
|
||||||
int.register_superclass(Float, &float); // TODO: Float -> Ratio
|
int.register_superclass(Float, &float); // TODO: Float -> Ratio
|
||||||
int.register_superclass(Obj, &obj);
|
|
||||||
int.register_marker_trait(builtin_mono("Num"));
|
int.register_marker_trait(builtin_mono("Num"));
|
||||||
int.register_marker_trait(builtin_mono("Ord"));
|
int.register_marker_trait(builtin_mono("Ord"));
|
||||||
int.register_marker_trait(builtin_poly("Eq", vec![ty_tp(Int)]));
|
int.register_marker_trait(builtin_poly("Eq", vec![ty_tp(Int)]));
|
||||||
|
@ -588,15 +610,13 @@ impl Context {
|
||||||
int.register_builtin_impl("Imag", Int, Const, Public);
|
int.register_builtin_impl("Imag", Int, Const, Public);
|
||||||
let mut nat = Self::builtin_mono_class("Nat", 10);
|
let mut nat = Self::builtin_mono_class("Nat", 10);
|
||||||
nat.register_superclass(Int, &int);
|
nat.register_superclass(Int, &int);
|
||||||
nat.register_superclass(Float, &float); // TODO: Float -> Ratio
|
|
||||||
nat.register_superclass(Obj, &obj);
|
|
||||||
// class("Rational"),
|
// class("Rational"),
|
||||||
// class("Integral"),
|
// class("Integral"),
|
||||||
nat.register_builtin_impl(
|
nat.register_builtin_impl(
|
||||||
"times!",
|
"times!",
|
||||||
pr_met(
|
pr_met(
|
||||||
Nat,
|
Nat,
|
||||||
vec![param_t("p", nd_proc(vec![], None, NoneType))],
|
vec![kw("p", nd_proc(vec![], None, NoneType))],
|
||||||
None,
|
None,
|
||||||
vec![],
|
vec![],
|
||||||
NoneType,
|
NoneType,
|
||||||
|
@ -638,9 +658,6 @@ impl Context {
|
||||||
nat.register_builtin_impl("Imag", Nat, Const, Public);
|
nat.register_builtin_impl("Imag", Nat, Const, Public);
|
||||||
let mut bool_ = Self::builtin_mono_class("Bool", 10);
|
let mut bool_ = Self::builtin_mono_class("Bool", 10);
|
||||||
bool_.register_superclass(Nat, &nat);
|
bool_.register_superclass(Nat, &nat);
|
||||||
bool_.register_superclass(Int, &int);
|
|
||||||
bool_.register_superclass(Float, &float); // TODO: Float -> Ratio
|
|
||||||
bool_.register_superclass(Obj, &obj);
|
|
||||||
// class("Rational"),
|
// class("Rational"),
|
||||||
// class("Integral"),
|
// class("Integral"),
|
||||||
// TODO: And, Or trait
|
// TODO: And, Or trait
|
||||||
|
@ -671,6 +688,9 @@ impl Context {
|
||||||
bool_mutizable
|
bool_mutizable
|
||||||
.register_builtin_const("MutType!", ValueObj::builtin_t(builtin_mono("Bool!")));
|
.register_builtin_const("MutType!", ValueObj::builtin_t(builtin_mono("Bool!")));
|
||||||
bool_.register_trait(Bool, builtin_mono("Mutizable"), bool_mutizable);
|
bool_.register_trait(Bool, builtin_mono("Mutizable"), bool_mutizable);
|
||||||
|
let mut bool_show = Self::builtin_methods("Show", 1);
|
||||||
|
bool_show.register_builtin_impl("to_str", fn0_met(Bool, Str), Immutable, Public);
|
||||||
|
bool_.register_trait(Bool, builtin_mono("Show"), bool_show);
|
||||||
let mut str_ = Self::builtin_mono_class("Str", 10);
|
let mut str_ = Self::builtin_mono_class("Str", 10);
|
||||||
str_.register_superclass(Obj, &obj);
|
str_.register_superclass(Obj, &obj);
|
||||||
str_.register_marker_trait(builtin_mono("Ord"));
|
str_.register_marker_trait(builtin_mono("Ord"));
|
||||||
|
@ -679,7 +699,7 @@ impl Context {
|
||||||
"replace",
|
"replace",
|
||||||
fn_met(
|
fn_met(
|
||||||
Str,
|
Str,
|
||||||
vec![param_t("pat", Str), param_t("into", Str)],
|
vec![kw("pat", Str), kw("into", Str)],
|
||||||
None,
|
None,
|
||||||
vec![],
|
vec![],
|
||||||
Str,
|
Str,
|
||||||
|
@ -693,7 +713,7 @@ impl Context {
|
||||||
Str,
|
Str,
|
||||||
vec![],
|
vec![],
|
||||||
None,
|
None,
|
||||||
vec![param_t("encoding", Str), param_t("errors", Str)],
|
vec![kw("encoding", Str), kw("errors", Str)],
|
||||||
builtin_mono("Bytes"),
|
builtin_mono("Bytes"),
|
||||||
),
|
),
|
||||||
Immutable,
|
Immutable,
|
||||||
|
@ -717,6 +737,9 @@ impl Context {
|
||||||
let mut str_mutizable = Self::builtin_methods("Mutizable", 2);
|
let mut str_mutizable = Self::builtin_methods("Mutizable", 2);
|
||||||
str_mutizable.register_builtin_const("MutType!", ValueObj::builtin_t(builtin_mono("Str!")));
|
str_mutizable.register_builtin_const("MutType!", ValueObj::builtin_t(builtin_mono("Str!")));
|
||||||
str_.register_trait(Str, builtin_mono("Mutizable"), str_mutizable);
|
str_.register_trait(Str, builtin_mono("Mutizable"), str_mutizable);
|
||||||
|
let mut str_show = Self::builtin_methods("Show", 1);
|
||||||
|
str_show.register_builtin_impl("to_str", fn0_met(Str, Str), Immutable, Public);
|
||||||
|
str_.register_trait(Str, builtin_mono("Show"), str_show);
|
||||||
let mut type_ = Self::builtin_mono_class("Type", 2);
|
let mut type_ = Self::builtin_mono_class("Type", 2);
|
||||||
type_.register_superclass(Obj, &obj);
|
type_.register_superclass(Obj, &obj);
|
||||||
type_.register_builtin_impl("mro", array(Type, TyParam::erased(Nat)), Immutable, Public);
|
type_.register_builtin_impl("mro", array(Type, TyParam::erased(Nat)), Immutable, Public);
|
||||||
|
@ -726,7 +749,6 @@ impl Context {
|
||||||
type_.register_trait(Type, builtin_poly("Eq", vec![ty_tp(Type)]), type_eq);
|
type_.register_trait(Type, builtin_poly("Eq", vec![ty_tp(Type)]), type_eq);
|
||||||
let mut class_type = Self::builtin_mono_class("ClassType", 2);
|
let mut class_type = Self::builtin_mono_class("ClassType", 2);
|
||||||
class_type.register_superclass(Type, &type_);
|
class_type.register_superclass(Type, &type_);
|
||||||
class_type.register_superclass(Obj, &obj);
|
|
||||||
class_type.register_marker_trait(builtin_mono("Named"));
|
class_type.register_marker_trait(builtin_mono("Named"));
|
||||||
let mut class_eq = Self::builtin_methods("Eq", 2);
|
let mut class_eq = Self::builtin_methods("Eq", 2);
|
||||||
class_eq.register_builtin_impl("__eq__", fn1_met(Class, Class, Bool), Const, Public);
|
class_eq.register_builtin_impl("__eq__", fn1_met(Class, Class, Bool), Const, Public);
|
||||||
|
@ -759,7 +781,7 @@ impl Context {
|
||||||
let array_t = array(mono_q("T"), n.clone());
|
let array_t = array(mono_q("T"), n.clone());
|
||||||
let t = fn_met(
|
let t = fn_met(
|
||||||
array_t.clone(),
|
array_t.clone(),
|
||||||
vec![param_t("rhs", array(mono_q("T"), m.clone()))],
|
vec![kw("rhs", array(mono_q("T"), m.clone()))],
|
||||||
None,
|
None,
|
||||||
vec![],
|
vec![],
|
||||||
array(mono_q("T"), n + m),
|
array(mono_q("T"), n + m),
|
||||||
|
@ -784,14 +806,22 @@ impl Context {
|
||||||
);
|
);
|
||||||
array_.register_trait(
|
array_.register_trait(
|
||||||
array_t.clone(),
|
array_t.clone(),
|
||||||
builtin_poly("Eq", vec![ty_tp(array_t)]),
|
builtin_poly("Eq", vec![ty_tp(array_t.clone())]),
|
||||||
array_eq,
|
array_eq,
|
||||||
);
|
);
|
||||||
array_.register_marker_trait(builtin_mono("Mutizable"));
|
array_.register_marker_trait(builtin_mono("Mutizable"));
|
||||||
array_.register_marker_trait(builtin_poly("Seq", vec![ty_tp(mono_q("T"))]));
|
array_.register_marker_trait(builtin_poly("Seq", vec![ty_tp(mono_q("T"))]));
|
||||||
|
let mut array_show = Self::builtin_methods("Show", 1);
|
||||||
|
array_show.register_builtin_impl(
|
||||||
|
"to_str",
|
||||||
|
fn0_met(array_t.clone(), Str),
|
||||||
|
Immutable,
|
||||||
|
Public,
|
||||||
|
);
|
||||||
|
array_.register_trait(array_t, builtin_mono("Show"), array_show);
|
||||||
let mut bytes = Self::builtin_mono_class("Bytes", 2);
|
let mut bytes = Self::builtin_mono_class("Bytes", 2);
|
||||||
bytes.register_superclass(Obj, &obj);
|
bytes.register_superclass(Obj, &obj);
|
||||||
// TODO: make Tuple6, Tuple7, ... etc.
|
// FIXME: replace to Tuple Ts (e.g. Tuple [Int, Str])
|
||||||
let mut tuple_ = Self::builtin_mono_class("Tuple", 2);
|
let mut tuple_ = Self::builtin_mono_class("Tuple", 2);
|
||||||
tuple_.register_superclass(Obj, &obj);
|
tuple_.register_superclass(Obj, &obj);
|
||||||
let mut tuple_eq = Self::builtin_methods("Eq", 2);
|
let mut tuple_eq = Self::builtin_methods("Eq", 2);
|
||||||
|
@ -808,7 +838,6 @@ impl Context {
|
||||||
);
|
);
|
||||||
let mut tuple1 = Self::builtin_poly_class("Tuple1", vec![PS::t_nd("A")], 2);
|
let mut tuple1 = Self::builtin_poly_class("Tuple1", vec![PS::t_nd("A")], 2);
|
||||||
tuple1.register_superclass(builtin_mono("Tuple"), &tuple_);
|
tuple1.register_superclass(builtin_mono("Tuple"), &tuple_);
|
||||||
tuple1.register_superclass(Obj, &obj);
|
|
||||||
let mut tuple1_eq = Self::builtin_methods("Eq", 2);
|
let mut tuple1_eq = Self::builtin_methods("Eq", 2);
|
||||||
tuple1_eq.register_builtin_impl(
|
tuple1_eq.register_builtin_impl(
|
||||||
"__eq__",
|
"__eq__",
|
||||||
|
@ -830,7 +859,6 @@ impl Context {
|
||||||
);
|
);
|
||||||
let mut tuple2 = Self::builtin_poly_class("Tuple2", vec![PS::t_nd("A"), PS::t_nd("B")], 2);
|
let mut tuple2 = Self::builtin_poly_class("Tuple2", vec![PS::t_nd("A"), PS::t_nd("B")], 2);
|
||||||
tuple2.register_superclass(builtin_mono("Tuple"), &tuple_);
|
tuple2.register_superclass(builtin_mono("Tuple"), &tuple_);
|
||||||
tuple2.register_superclass(Obj, &obj);
|
|
||||||
let mut tuple2_eq = Self::builtin_methods("Eq", 2);
|
let mut tuple2_eq = Self::builtin_methods("Eq", 2);
|
||||||
tuple2_eq.register_builtin_impl(
|
tuple2_eq.register_builtin_impl(
|
||||||
"__eq__",
|
"__eq__",
|
||||||
|
@ -859,7 +887,6 @@ impl Context {
|
||||||
2,
|
2,
|
||||||
);
|
);
|
||||||
tuple3.register_superclass(builtin_mono("Tuple"), &tuple_);
|
tuple3.register_superclass(builtin_mono("Tuple"), &tuple_);
|
||||||
tuple3.register_superclass(Obj, &obj);
|
|
||||||
let mut tuple3_eq = Self::builtin_methods("Eq", 2);
|
let mut tuple3_eq = Self::builtin_methods("Eq", 2);
|
||||||
tuple3_eq.register_builtin_impl(
|
tuple3_eq.register_builtin_impl(
|
||||||
"__eq__",
|
"__eq__",
|
||||||
|
@ -897,7 +924,6 @@ impl Context {
|
||||||
2,
|
2,
|
||||||
);
|
);
|
||||||
tuple4.register_superclass(builtin_mono("Tuple"), &tuple_);
|
tuple4.register_superclass(builtin_mono("Tuple"), &tuple_);
|
||||||
tuple4.register_superclass(Obj, &obj);
|
|
||||||
let mut tuple4_eq = Self::builtin_methods("Eq", 2);
|
let mut tuple4_eq = Self::builtin_methods("Eq", 2);
|
||||||
tuple4_eq.register_builtin_impl(
|
tuple4_eq.register_builtin_impl(
|
||||||
"__eq__",
|
"__eq__",
|
||||||
|
@ -961,7 +987,6 @@ impl Context {
|
||||||
2,
|
2,
|
||||||
);
|
);
|
||||||
tuple5.register_superclass(builtin_mono("Tuple"), &tuple_);
|
tuple5.register_superclass(builtin_mono("Tuple"), &tuple_);
|
||||||
tuple5.register_superclass(Obj, &obj);
|
|
||||||
let mut tuple5_eq = Self::builtin_methods("Eq", 2);
|
let mut tuple5_eq = Self::builtin_methods("Eq", 2);
|
||||||
tuple5_eq.register_builtin_impl(
|
tuple5_eq.register_builtin_impl(
|
||||||
"__eq__",
|
"__eq__",
|
||||||
|
@ -1030,7 +1055,6 @@ impl Context {
|
||||||
2,
|
2,
|
||||||
);
|
);
|
||||||
tuple6.register_superclass(builtin_mono("Tuple"), &tuple_);
|
tuple6.register_superclass(builtin_mono("Tuple"), &tuple_);
|
||||||
tuple6.register_superclass(Obj, &obj);
|
|
||||||
let mut tuple6_eq = Self::builtin_methods("Eq", 2);
|
let mut tuple6_eq = Self::builtin_methods("Eq", 2);
|
||||||
tuple6_eq.register_builtin_impl(
|
tuple6_eq.register_builtin_impl(
|
||||||
"__eq__",
|
"__eq__",
|
||||||
|
@ -1104,7 +1128,6 @@ impl Context {
|
||||||
2,
|
2,
|
||||||
);
|
);
|
||||||
tuple7.register_superclass(builtin_mono("Tuple"), &tuple_);
|
tuple7.register_superclass(builtin_mono("Tuple"), &tuple_);
|
||||||
tuple7.register_superclass(Obj, &obj);
|
|
||||||
let mut tuple7_eq = Self::builtin_methods("Eq", 2);
|
let mut tuple7_eq = Self::builtin_methods("Eq", 2);
|
||||||
tuple7_eq.register_builtin_impl(
|
tuple7_eq.register_builtin_impl(
|
||||||
"__eq__",
|
"__eq__",
|
||||||
|
@ -1183,7 +1206,6 @@ impl Context {
|
||||||
2,
|
2,
|
||||||
);
|
);
|
||||||
tuple8.register_superclass(builtin_mono("Tuple"), &tuple_);
|
tuple8.register_superclass(builtin_mono("Tuple"), &tuple_);
|
||||||
tuple8.register_superclass(Obj, &obj);
|
|
||||||
let mut tuple8_eq = Self::builtin_methods("Eq", 2);
|
let mut tuple8_eq = Self::builtin_methods("Eq", 2);
|
||||||
tuple8_eq.register_builtin_impl(
|
tuple8_eq.register_builtin_impl(
|
||||||
"__eq__",
|
"__eq__",
|
||||||
|
@ -1256,13 +1278,11 @@ impl Context {
|
||||||
let mut record_type = Self::builtin_mono_class("RecordType", 2);
|
let mut record_type = Self::builtin_mono_class("RecordType", 2);
|
||||||
record_type.register_superclass(builtin_mono("Record"), &record);
|
record_type.register_superclass(builtin_mono("Record"), &record);
|
||||||
record_type.register_superclass(builtin_mono("Type"), &type_);
|
record_type.register_superclass(builtin_mono("Type"), &type_);
|
||||||
record_type.register_superclass(Obj, &obj);
|
|
||||||
let mut float_mut = Self::builtin_mono_class("Float!", 2);
|
let mut float_mut = Self::builtin_mono_class("Float!", 2);
|
||||||
float_mut.register_superclass(Float, &float);
|
float_mut.register_superclass(Float, &float);
|
||||||
float_mut.register_superclass(Obj, &obj);
|
|
||||||
let mut float_mut_mutable = Self::builtin_methods("Mutable", 2);
|
let mut float_mut_mutable = Self::builtin_methods("Mutable", 2);
|
||||||
float_mut_mutable.register_builtin_const("ImmutType", ValueObj::builtin_t(Float));
|
float_mut_mutable.register_builtin_const("ImmutType", ValueObj::builtin_t(Float));
|
||||||
let f_t = param_t("f", func(vec![param_t("old", Float)], None, vec![], Float));
|
let f_t = kw("f", func(vec![kw("old", Float)], None, vec![], Float));
|
||||||
let t = pr_met(
|
let t = pr_met(
|
||||||
ref_mut(builtin_mono("Float!"), None),
|
ref_mut(builtin_mono("Float!"), None),
|
||||||
vec![f_t],
|
vec![f_t],
|
||||||
|
@ -1278,13 +1298,12 @@ impl Context {
|
||||||
);
|
);
|
||||||
let mut ratio_mut = Self::builtin_mono_class("Ratio!", 2);
|
let mut ratio_mut = Self::builtin_mono_class("Ratio!", 2);
|
||||||
ratio_mut.register_superclass(Ratio, &ratio);
|
ratio_mut.register_superclass(Ratio, &ratio);
|
||||||
ratio_mut.register_superclass(Obj, &obj);
|
|
||||||
let mut ratio_mut_mutable = Self::builtin_methods("Mutable", 2);
|
let mut ratio_mut_mutable = Self::builtin_methods("Mutable", 2);
|
||||||
ratio_mut_mutable.register_builtin_const("ImmutType", ValueObj::builtin_t(Ratio));
|
ratio_mut_mutable.register_builtin_const("ImmutType", ValueObj::builtin_t(Ratio));
|
||||||
let f_t = param_t(
|
let f_t = kw(
|
||||||
"f",
|
"f",
|
||||||
func(
|
func(
|
||||||
vec![param_t("old", builtin_mono("Ratio"))],
|
vec![kw("old", builtin_mono("Ratio"))],
|
||||||
None,
|
None,
|
||||||
vec![],
|
vec![],
|
||||||
builtin_mono("Ratio"),
|
builtin_mono("Ratio"),
|
||||||
|
@ -1306,10 +1325,9 @@ impl Context {
|
||||||
let mut int_mut = Self::builtin_mono_class("Int!", 2);
|
let mut int_mut = Self::builtin_mono_class("Int!", 2);
|
||||||
int_mut.register_superclass(Int, &int);
|
int_mut.register_superclass(Int, &int);
|
||||||
int_mut.register_superclass(builtin_mono("Float!"), &float_mut);
|
int_mut.register_superclass(builtin_mono("Float!"), &float_mut);
|
||||||
int_mut.register_superclass(Obj, &obj);
|
|
||||||
let mut int_mut_mutable = Self::builtin_methods("Mutable", 2);
|
let mut int_mut_mutable = Self::builtin_methods("Mutable", 2);
|
||||||
int_mut_mutable.register_builtin_const("ImmutType", ValueObj::builtin_t(Int));
|
int_mut_mutable.register_builtin_const("ImmutType", ValueObj::builtin_t(Int));
|
||||||
let f_t = param_t("f", func(vec![param_t("old", Int)], None, vec![], Int));
|
let f_t = kw("f", func(vec![kw("old", Int)], None, vec![], Int));
|
||||||
let t = pr_met(
|
let t = pr_met(
|
||||||
ref_mut(builtin_mono("Int!"), None),
|
ref_mut(builtin_mono("Int!"), None),
|
||||||
vec![f_t],
|
vec![f_t],
|
||||||
|
@ -1326,11 +1344,9 @@ impl Context {
|
||||||
let mut nat_mut = Self::builtin_mono_class("Nat!", 2);
|
let mut nat_mut = Self::builtin_mono_class("Nat!", 2);
|
||||||
nat_mut.register_superclass(Nat, &nat);
|
nat_mut.register_superclass(Nat, &nat);
|
||||||
nat_mut.register_superclass(builtin_mono("Int!"), &int_mut);
|
nat_mut.register_superclass(builtin_mono("Int!"), &int_mut);
|
||||||
nat_mut.register_superclass(builtin_mono("Float!"), &float_mut);
|
|
||||||
nat_mut.register_superclass(Obj, &obj);
|
|
||||||
let mut nat_mut_mutable = Self::builtin_methods("Mutable", 2);
|
let mut nat_mut_mutable = Self::builtin_methods("Mutable", 2);
|
||||||
nat_mut_mutable.register_builtin_const("ImmutType", ValueObj::builtin_t(Nat));
|
nat_mut_mutable.register_builtin_const("ImmutType", ValueObj::builtin_t(Nat));
|
||||||
let f_t = param_t("f", func(vec![param_t("old", Nat)], None, vec![], Nat));
|
let f_t = kw("f", func(vec![kw("old", Nat)], None, vec![], Nat));
|
||||||
let t = pr_met(
|
let t = pr_met(
|
||||||
ref_mut(builtin_mono("Nat!"), None),
|
ref_mut(builtin_mono("Nat!"), None),
|
||||||
vec![f_t],
|
vec![f_t],
|
||||||
|
@ -1347,12 +1363,9 @@ impl Context {
|
||||||
let mut bool_mut = Self::builtin_mono_class("Bool!", 2);
|
let mut bool_mut = Self::builtin_mono_class("Bool!", 2);
|
||||||
bool_mut.register_superclass(Bool, &bool_);
|
bool_mut.register_superclass(Bool, &bool_);
|
||||||
bool_mut.register_superclass(builtin_mono("Nat!"), &nat_mut);
|
bool_mut.register_superclass(builtin_mono("Nat!"), &nat_mut);
|
||||||
bool_mut.register_superclass(builtin_mono("Int!"), &int_mut);
|
|
||||||
bool_mut.register_superclass(builtin_mono("Float!"), &float_mut);
|
|
||||||
bool_mut.register_superclass(Obj, &obj);
|
|
||||||
let mut bool_mut_mutable = Self::builtin_methods("Mutable", 2);
|
let mut bool_mut_mutable = Self::builtin_methods("Mutable", 2);
|
||||||
bool_mut_mutable.register_builtin_const("ImmutType", ValueObj::builtin_t(Bool));
|
bool_mut_mutable.register_builtin_const("ImmutType", ValueObj::builtin_t(Bool));
|
||||||
let f_t = param_t("f", func(vec![param_t("old", Bool)], None, vec![], Bool));
|
let f_t = kw("f", func(vec![kw("old", Bool)], None, vec![], Bool));
|
||||||
let t = pr_met(
|
let t = pr_met(
|
||||||
ref_mut(builtin_mono("Bool!"), None),
|
ref_mut(builtin_mono("Bool!"), None),
|
||||||
vec![f_t],
|
vec![f_t],
|
||||||
|
@ -1368,10 +1381,9 @@ impl Context {
|
||||||
);
|
);
|
||||||
let mut str_mut = Self::builtin_mono_class("Str!", 2);
|
let mut str_mut = Self::builtin_mono_class("Str!", 2);
|
||||||
str_mut.register_superclass(Str, &str_);
|
str_mut.register_superclass(Str, &str_);
|
||||||
str_mut.register_superclass(Obj, &obj);
|
|
||||||
let mut str_mut_mutable = Self::builtin_methods("Mutable", 2);
|
let mut str_mut_mutable = Self::builtin_methods("Mutable", 2);
|
||||||
str_mut_mutable.register_builtin_const("ImmutType", ValueObj::builtin_t(Str));
|
str_mut_mutable.register_builtin_const("ImmutType", ValueObj::builtin_t(Str));
|
||||||
let f_t = param_t("f", func(vec![param_t("old", Str)], None, vec![], Str));
|
let f_t = kw("f", func(vec![kw("old", Str)], None, vec![], Str));
|
||||||
let t = pr_met(
|
let t = pr_met(
|
||||||
ref_mut(builtin_mono("Str!"), None),
|
ref_mut(builtin_mono("Str!"), None),
|
||||||
vec![f_t],
|
vec![f_t],
|
||||||
|
@ -1393,7 +1405,7 @@ impl Context {
|
||||||
ref_mut(builtin_mono("File!"), None),
|
ref_mut(builtin_mono("File!"), None),
|
||||||
vec![],
|
vec![],
|
||||||
None,
|
None,
|
||||||
vec![param_t("n", Int)],
|
vec![kw("n", Int)],
|
||||||
Str,
|
Str,
|
||||||
),
|
),
|
||||||
Immutable,
|
Immutable,
|
||||||
|
@ -1412,7 +1424,6 @@ impl Context {
|
||||||
2,
|
2,
|
||||||
);
|
);
|
||||||
array_mut_.register_superclass(array_t.clone(), &array_);
|
array_mut_.register_superclass(array_t.clone(), &array_);
|
||||||
array_mut_.register_superclass(Obj, &obj);
|
|
||||||
let t = pr_met(
|
let t = pr_met(
|
||||||
ref_mut(
|
ref_mut(
|
||||||
array_mut_t.clone(),
|
array_mut_t.clone(),
|
||||||
|
@ -1421,7 +1432,7 @@ impl Context {
|
||||||
vec![ty_tp(mono_q("T")), mono_q_tp("N") + value(1)],
|
vec![ty_tp(mono_q("T")), mono_q_tp("N") + value(1)],
|
||||||
)),
|
)),
|
||||||
),
|
),
|
||||||
vec![param_t("elem", mono_q("T"))],
|
vec![kw("elem", mono_q("T"))],
|
||||||
None,
|
None,
|
||||||
vec![],
|
vec![],
|
||||||
NoneType,
|
NoneType,
|
||||||
|
@ -1433,10 +1444,7 @@ impl Context {
|
||||||
array_mut_.register_builtin_impl("push!", t, Immutable, Public);
|
array_mut_.register_builtin_impl("push!", t, Immutable, Public);
|
||||||
let t = pr_met(
|
let t = pr_met(
|
||||||
array_mut_t.clone(),
|
array_mut_t.clone(),
|
||||||
vec![param_t(
|
vec![kw("f", nd_func(vec![anon(mono_q("T"))], None, mono_q("T")))],
|
||||||
"f",
|
|
||||||
nd_func(vec![anon(mono_q("T"))], None, mono_q("T")),
|
|
||||||
)],
|
|
||||||
None,
|
None,
|
||||||
vec![],
|
vec![],
|
||||||
NoneType,
|
NoneType,
|
||||||
|
@ -1446,10 +1454,10 @@ impl Context {
|
||||||
set! {static_instance("T", Type), static_instance("N", builtin_mono("Nat!"))},
|
set! {static_instance("T", Type), static_instance("N", builtin_mono("Nat!"))},
|
||||||
);
|
);
|
||||||
array_mut_.register_builtin_impl("strict_map!", t, Immutable, Public);
|
array_mut_.register_builtin_impl("strict_map!", t, Immutable, Public);
|
||||||
let f_t = param_t(
|
let f_t = kw(
|
||||||
"f",
|
"f",
|
||||||
func(
|
func(
|
||||||
vec![param_t("old", array_t.clone())],
|
vec![kw("old", array_t.clone())],
|
||||||
None,
|
None,
|
||||||
vec![],
|
vec![],
|
||||||
array_t.clone(),
|
array_t.clone(),
|
||||||
|
@ -1487,16 +1495,16 @@ impl Context {
|
||||||
);
|
);
|
||||||
let mut proc = Self::builtin_mono_class("Proc", 2);
|
let mut proc = Self::builtin_mono_class("Proc", 2);
|
||||||
proc.register_superclass(Obj, &obj);
|
proc.register_superclass(Obj, &obj);
|
||||||
// TODO: lambda
|
let mut named_proc = Self::builtin_mono_class("NamedProc", 2);
|
||||||
proc.register_marker_trait(builtin_mono("Named"));
|
named_proc.register_superclass(Obj, &obj);
|
||||||
|
named_proc.register_marker_trait(builtin_mono("Named"));
|
||||||
let mut func = Self::builtin_mono_class("Func", 2);
|
let mut func = Self::builtin_mono_class("Func", 2);
|
||||||
func.register_superclass(builtin_mono("Proc"), &proc);
|
func.register_superclass(builtin_mono("Proc"), &proc);
|
||||||
func.register_superclass(Obj, &obj);
|
let mut named_func = Self::builtin_mono_class("NamedFunc", 2);
|
||||||
// TODO: lambda
|
named_func.register_superclass(builtin_mono("Func"), &func);
|
||||||
func.register_marker_trait(builtin_mono("Named"));
|
named_func.register_marker_trait(builtin_mono("Named"));
|
||||||
let mut qfunc = Self::builtin_mono_class("QuantifiedFunc", 2);
|
let mut qfunc = Self::builtin_mono_class("QuantifiedFunc", 2);
|
||||||
qfunc.register_superclass(builtin_mono("Func"), &func);
|
qfunc.register_superclass(builtin_mono("Func"), &func);
|
||||||
qfunc.register_superclass(Obj, &obj);
|
|
||||||
self.register_builtin_type(Obj, obj, Const);
|
self.register_builtin_type(Obj, obj, Const);
|
||||||
// self.register_type(mono("Record"), vec![], record, Const);
|
// self.register_type(mono("Record"), vec![], record, Const);
|
||||||
self.register_builtin_type(Int, int, Const);
|
self.register_builtin_type(Int, int, Const);
|
||||||
|
@ -1586,42 +1594,50 @@ impl Context {
|
||||||
self.register_builtin_type(range_t, range, Const);
|
self.register_builtin_type(range_t, range, Const);
|
||||||
self.register_builtin_type(builtin_mono("Tuple"), tuple_, Const);
|
self.register_builtin_type(builtin_mono("Tuple"), tuple_, Const);
|
||||||
self.register_builtin_type(builtin_mono("Proc"), proc, Const);
|
self.register_builtin_type(builtin_mono("Proc"), proc, Const);
|
||||||
|
self.register_builtin_type(builtin_mono("NamedProc"), named_proc, Const);
|
||||||
self.register_builtin_type(builtin_mono("Func"), func, Const);
|
self.register_builtin_type(builtin_mono("Func"), func, Const);
|
||||||
|
self.register_builtin_type(builtin_mono("NamedFunc"), named_func, Const);
|
||||||
self.register_builtin_type(builtin_mono("QuantifiedFunc"), qfunc, Const);
|
self.register_builtin_type(builtin_mono("QuantifiedFunc"), qfunc, Const);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_builtin_funcs(&mut self) {
|
fn init_builtin_funcs(&mut self) {
|
||||||
let t_abs = nd_func(vec![param_t("n", builtin_mono("Num"))], None, Nat);
|
let t_abs = nd_func(vec![kw("n", builtin_mono("Num"))], None, Nat);
|
||||||
let t_assert = func(
|
let t_assert = func(
|
||||||
vec![param_t("condition", Bool)],
|
vec![kw("condition", Bool)],
|
||||||
None,
|
None,
|
||||||
vec![param_t("err_message", Str)],
|
vec![kw("err_message", Str)],
|
||||||
NoneType,
|
NoneType,
|
||||||
);
|
);
|
||||||
let t_classof = nd_func(vec![param_t("old", Obj)], None, Class);
|
let t_classof = nd_func(vec![kw("old", Obj)], None, Class);
|
||||||
let t_compile = nd_func(vec![param_t("src", Str)], None, Code);
|
let t_compile = nd_func(vec![kw("src", Str)], None, Code);
|
||||||
let t_cond = nd_func(
|
let t_cond = nd_func(
|
||||||
vec![
|
vec![
|
||||||
param_t("condition", Bool),
|
kw("condition", Bool),
|
||||||
param_t("then", mono_q("T")),
|
kw("then", mono_q("T")),
|
||||||
param_t("else", mono_q("T")),
|
kw("else", mono_q("T")),
|
||||||
],
|
],
|
||||||
None,
|
None,
|
||||||
mono_q("T"),
|
mono_q("T"),
|
||||||
);
|
);
|
||||||
let t_cond = quant(t_cond, set! {static_instance("T", Type)});
|
let t_cond = quant(t_cond, set! {static_instance("T", Type)});
|
||||||
let t_discard = nd_func(vec![param_t("old", Obj)], None, NoneType);
|
let t_discard = nd_func(vec![kw("obj", Obj)], None, NoneType);
|
||||||
// FIXME: quantify
|
|
||||||
let t_if = func(
|
let t_if = func(
|
||||||
vec![
|
vec![
|
||||||
param_t("cond", Bool),
|
kw("cond", Bool),
|
||||||
param_t("then", nd_func(vec![], None, mono_q("T"))),
|
kw("then", nd_func(vec![], None, mono_q("T"))),
|
||||||
],
|
],
|
||||||
None,
|
None,
|
||||||
vec![param_t("else", nd_func(vec![], None, mono_q("T")))],
|
vec![kw_default(
|
||||||
or(mono_q("T"), NoneType),
|
"else",
|
||||||
|
nd_func(vec![], None, mono_q("U")),
|
||||||
|
nd_func(vec![], None, NoneType),
|
||||||
|
)],
|
||||||
|
or(mono_q("T"), mono_q("U")),
|
||||||
|
);
|
||||||
|
let t_if = quant(
|
||||||
|
t_if,
|
||||||
|
set! {static_instance("T", Type), static_instance("U", Type)},
|
||||||
);
|
);
|
||||||
let t_if = quant(t_if, set! {static_instance("T", Type)});
|
|
||||||
let t_import = nd_func(
|
let t_import = nd_func(
|
||||||
vec![anon(tp_enum(Str, set! {mono_q_tp("Path")}))],
|
vec![anon(tp_enum(Str, set! {mono_q_tp("Path")}))],
|
||||||
None,
|
None,
|
||||||
|
@ -1630,12 +1646,12 @@ impl Context {
|
||||||
let t_import = quant(t_import, set! {static_instance("Path", Str)});
|
let t_import = quant(t_import, set! {static_instance("Path", Str)});
|
||||||
let t_log = func(
|
let t_log = func(
|
||||||
vec![],
|
vec![],
|
||||||
Some(param_t("objects", ref_(Obj))),
|
Some(kw("objects", ref_(Obj))),
|
||||||
vec![
|
vec![
|
||||||
param_t("sep", Str),
|
kw("sep", Str),
|
||||||
param_t("end", Str),
|
kw("end", Str),
|
||||||
param_t("file", builtin_mono("Write")),
|
kw("file", builtin_mono("Write")),
|
||||||
param_t("flush", Bool),
|
kw("flush", Bool),
|
||||||
],
|
],
|
||||||
NoneType,
|
NoneType,
|
||||||
);
|
);
|
||||||
|
@ -1644,9 +1660,9 @@ impl Context {
|
||||||
None,
|
None,
|
||||||
module(mono_q_tp("Path")),
|
module(mono_q_tp("Path")),
|
||||||
);
|
);
|
||||||
let t_panic = nd_func(vec![param_t("err_message", Str)], None, NoneType);
|
let t_panic = nd_func(vec![kw("err_message", Str)], None, NoneType);
|
||||||
let t_pyimport = quant(t_pyimport, set! {static_instance("Path", Str)});
|
let t_pyimport = quant(t_pyimport, set! {static_instance("Path", Str)});
|
||||||
let t_quit = func(vec![], None, vec![param_t("code", Int)], NoneType);
|
let t_quit = func(vec![], None, vec![kw("code", Int)], NoneType);
|
||||||
let t_exit = t_quit.clone();
|
let t_exit = t_quit.clone();
|
||||||
self.register_builtin_impl("abs", t_abs, Immutable, Private);
|
self.register_builtin_impl("abs", t_abs, Immutable, Private);
|
||||||
self.register_builtin_impl("assert", t_assert, Const, Private); // assert casting に悪影響が出る可能性があるため、Constとしておく
|
self.register_builtin_impl("assert", t_assert, Const, Private); // assert casting に悪影響が出る可能性があるため、Constとしておく
|
||||||
|
@ -1668,17 +1684,17 @@ impl Context {
|
||||||
|
|
||||||
fn init_builtin_const_funcs(&mut self) {
|
fn init_builtin_const_funcs(&mut self) {
|
||||||
let class_t = func(
|
let class_t = func(
|
||||||
vec![param_t("Requirement", Type)],
|
vec![kw("Requirement", Type)],
|
||||||
None,
|
None,
|
||||||
vec![param_t("Impl", Type)],
|
vec![kw("Impl", Type)],
|
||||||
Class,
|
Class,
|
||||||
);
|
);
|
||||||
let class = ConstSubr::Builtin(BuiltinConstSubr::new("Class", class_func, class_t, None));
|
let class = ConstSubr::Builtin(BuiltinConstSubr::new("Class", class_func, class_t, None));
|
||||||
self.register_builtin_const("Class", ValueObj::Subr(class));
|
self.register_builtin_const("Class", ValueObj::Subr(class));
|
||||||
let inherit_t = func(
|
let inherit_t = func(
|
||||||
vec![param_t("Super", Class)],
|
vec![kw("Super", Class)],
|
||||||
None,
|
None,
|
||||||
vec![param_t("Impl", Type), param_t("Additional", Type)],
|
vec![kw("Impl", Type), kw("Additional", Type)],
|
||||||
Class,
|
Class,
|
||||||
);
|
);
|
||||||
let inherit = ConstSubr::Builtin(BuiltinConstSubr::new(
|
let inherit = ConstSubr::Builtin(BuiltinConstSubr::new(
|
||||||
|
@ -1689,17 +1705,17 @@ impl Context {
|
||||||
));
|
));
|
||||||
self.register_builtin_const("Inherit", ValueObj::Subr(inherit));
|
self.register_builtin_const("Inherit", ValueObj::Subr(inherit));
|
||||||
let trait_t = func(
|
let trait_t = func(
|
||||||
vec![param_t("Requirement", Type)],
|
vec![kw("Requirement", Type)],
|
||||||
None,
|
None,
|
||||||
vec![param_t("Impl", Type)],
|
vec![kw("Impl", Type)],
|
||||||
Trait,
|
Trait,
|
||||||
);
|
);
|
||||||
let trait_ = ConstSubr::Builtin(BuiltinConstSubr::new("Trait", trait_func, trait_t, None));
|
let trait_ = ConstSubr::Builtin(BuiltinConstSubr::new("Trait", trait_func, trait_t, None));
|
||||||
self.register_builtin_const("Trait", ValueObj::Subr(trait_));
|
self.register_builtin_const("Trait", ValueObj::Subr(trait_));
|
||||||
let subsume_t = func(
|
let subsume_t = func(
|
||||||
vec![param_t("Super", Trait)],
|
vec![kw("Super", Trait)],
|
||||||
None,
|
None,
|
||||||
vec![param_t("Impl", Type), param_t("Additional", Type)],
|
vec![kw("Impl", Type), kw("Additional", Type)],
|
||||||
Trait,
|
Trait,
|
||||||
);
|
);
|
||||||
let subsume = ConstSubr::Builtin(BuiltinConstSubr::new(
|
let subsume = ConstSubr::Builtin(BuiltinConstSubr::new(
|
||||||
|
@ -1718,42 +1734,45 @@ impl Context {
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
self.register_builtin_const("Inheritable", ValueObj::Subr(inheritable));
|
self.register_builtin_const("Inheritable", ValueObj::Subr(inheritable));
|
||||||
|
// TODO: register Del function object
|
||||||
|
let t_del = nd_func(vec![kw("obj", Obj)], None, NoneType);
|
||||||
|
self.register_builtin_impl("Del", t_del, Immutable, Private);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_builtin_procs(&mut self) {
|
fn init_builtin_procs(&mut self) {
|
||||||
let t_dir = proc(
|
let t_dir = proc(
|
||||||
vec![param_t("obj", ref_(Obj))],
|
vec![kw("obj", ref_(Obj))],
|
||||||
None,
|
None,
|
||||||
vec![],
|
vec![],
|
||||||
array(Str, TyParam::erased(Nat)),
|
array(Str, TyParam::erased(Nat)),
|
||||||
);
|
);
|
||||||
let t_print = proc(
|
let t_print = proc(
|
||||||
vec![],
|
vec![],
|
||||||
Some(param_t("objects", ref_(Obj))),
|
Some(kw("objects", ref_(Obj))),
|
||||||
vec![
|
vec![
|
||||||
param_t("sep", Str),
|
kw("sep", Str),
|
||||||
param_t("end", Str),
|
kw("end", Str),
|
||||||
param_t("file", builtin_mono("Write")),
|
kw("file", builtin_mono("Write")),
|
||||||
param_t("flush", Bool),
|
kw("flush", Bool),
|
||||||
],
|
],
|
||||||
NoneType,
|
NoneType,
|
||||||
);
|
);
|
||||||
let t_id = nd_func(vec![param_t("old", Obj)], None, Nat);
|
let t_id = nd_func(vec![kw("old", Obj)], None, Nat);
|
||||||
let t_input = proc(vec![], None, vec![param_t("msg", Str)], Str);
|
let t_input = proc(vec![], None, vec![kw("msg", Str)], Str);
|
||||||
let t_if = proc(
|
let t_if = proc(
|
||||||
vec![
|
vec![
|
||||||
param_t("cond", Bool),
|
kw("cond", Bool),
|
||||||
param_t("then", nd_proc(vec![], None, mono_q("T"))),
|
kw("then", nd_proc(vec![], None, mono_q("T"))),
|
||||||
],
|
],
|
||||||
None,
|
None,
|
||||||
vec![param_t("else", nd_proc(vec![], None, mono_q("T")))],
|
vec![kw("else", nd_proc(vec![], None, mono_q("T")))],
|
||||||
or(mono_q("T"), NoneType),
|
or(mono_q("T"), NoneType),
|
||||||
);
|
);
|
||||||
let t_if = quant(t_if, set! {static_instance("T", Type)});
|
let t_if = quant(t_if, set! {static_instance("T", Type)});
|
||||||
let t_for = nd_proc(
|
let t_for = nd_proc(
|
||||||
vec![
|
vec![
|
||||||
param_t("iter", iter(mono_q("T"))),
|
kw("iter", iter(mono_q("T"))),
|
||||||
param_t("p", nd_proc(vec![anon(mono_q("T"))], None, NoneType)),
|
kw("p", nd_proc(vec![anon(mono_q("T"))], None, NoneType)),
|
||||||
],
|
],
|
||||||
None,
|
None,
|
||||||
NoneType,
|
NoneType,
|
||||||
|
@ -1761,22 +1780,22 @@ impl Context {
|
||||||
let t_for = quant(t_for, set! {static_instance("T", Type)});
|
let t_for = quant(t_for, set! {static_instance("T", Type)});
|
||||||
let t_while = nd_proc(
|
let t_while = nd_proc(
|
||||||
vec![
|
vec![
|
||||||
param_t("cond", builtin_mono("Bool!")),
|
kw("cond", builtin_mono("Bool!")),
|
||||||
param_t("p", nd_proc(vec![], None, NoneType)),
|
kw("p", nd_proc(vec![], None, NoneType)),
|
||||||
],
|
],
|
||||||
None,
|
None,
|
||||||
NoneType,
|
NoneType,
|
||||||
);
|
);
|
||||||
let t_open = proc(
|
let t_open = proc(
|
||||||
vec![param_t("file", mono_q("P"))],
|
vec![kw("file", mono_q("P"))],
|
||||||
None,
|
None,
|
||||||
vec![
|
vec![
|
||||||
param_t("mode", Str),
|
kw("mode", Str),
|
||||||
param_t("buffering", Int),
|
kw("buffering", Int),
|
||||||
param_t("encoding", or(Str, NoneType)),
|
kw("encoding", or(Str, NoneType)),
|
||||||
param_t("errors", or(Str, NoneType)),
|
kw("errors", or(Str, NoneType)),
|
||||||
param_t("newline", or(Str, NoneType)),
|
kw("newline", or(Str, NoneType)),
|
||||||
param_t("closefd", Bool),
|
kw("closefd", Bool),
|
||||||
// param_t("opener", option),
|
// param_t("opener", option),
|
||||||
],
|
],
|
||||||
builtin_mono("File!"),
|
builtin_mono("File!"),
|
||||||
|
@ -1788,8 +1807,8 @@ impl Context {
|
||||||
// TODO: T <: With
|
// TODO: T <: With
|
||||||
let t_with = nd_proc(
|
let t_with = nd_proc(
|
||||||
vec![
|
vec![
|
||||||
param_t("obj", mono_q("T")),
|
kw("obj", mono_q("T")),
|
||||||
param_t("p!", nd_proc(vec![anon(mono_q("T"))], None, mono_q("U"))),
|
kw("p!", nd_proc(vec![anon(mono_q("T"))], None, mono_q("U"))),
|
||||||
],
|
],
|
||||||
None,
|
None,
|
||||||
mono_q("U"),
|
mono_q("U"),
|
||||||
|
@ -1815,7 +1834,7 @@ impl Context {
|
||||||
let r = mono_q("R");
|
let r = mono_q("R");
|
||||||
let params = vec![ty_tp(mono_q("R"))];
|
let params = vec![ty_tp(mono_q("R"))];
|
||||||
let op_t = nd_func(
|
let op_t = nd_func(
|
||||||
vec![param_t("lhs", l.clone()), param_t("rhs", r.clone())],
|
vec![kw("lhs", l.clone()), kw("rhs", r.clone())],
|
||||||
None,
|
None,
|
||||||
mono_proj(mono_q("L"), "Output"),
|
mono_proj(mono_q("L"), "Output"),
|
||||||
);
|
);
|
||||||
|
|
|
@ -2,7 +2,7 @@ use erg_common::set;
|
||||||
use erg_common::vis::Visibility;
|
use erg_common::vis::Visibility;
|
||||||
|
|
||||||
use erg_type::constructors::{
|
use erg_type::constructors::{
|
||||||
builtin_mono, builtin_poly, mono_q, nd_proc, param_t, proc, quant, static_instance, ty_tp,
|
builtin_mono, builtin_poly, kw, mono_q, nd_proc, proc, quant, static_instance, ty_tp,
|
||||||
};
|
};
|
||||||
use erg_type::Type;
|
use erg_type::Type;
|
||||||
use Type::*;
|
use Type::*;
|
||||||
|
@ -21,8 +21,8 @@ impl Context {
|
||||||
vec![],
|
vec![],
|
||||||
None,
|
None,
|
||||||
vec![
|
vec![
|
||||||
param_t("a", builtin_mono("Num")), // TODO: NoneType, int, float, str, bytes, bytearray
|
kw("a", builtin_mono("Num")), // TODO: NoneType, int, float, str, bytes, bytearray
|
||||||
param_t("version", Int),
|
kw("version", Int),
|
||||||
],
|
],
|
||||||
NoneType,
|
NoneType,
|
||||||
),
|
),
|
||||||
|
@ -31,15 +31,12 @@ impl Context {
|
||||||
);
|
);
|
||||||
random.register_builtin_impl(
|
random.register_builtin_impl(
|
||||||
"randint!",
|
"randint!",
|
||||||
nd_proc(vec![param_t("a", Int), param_t("b", Int)], None, Int),
|
nd_proc(vec![kw("a", Int), kw("b", Int)], None, Int),
|
||||||
Immutable,
|
Immutable,
|
||||||
Public,
|
Public,
|
||||||
);
|
);
|
||||||
let t = nd_proc(
|
let t = nd_proc(
|
||||||
vec![param_t(
|
vec![kw("seq", builtin_poly("Seq", vec![ty_tp(mono_q("T"))]))],
|
||||||
"seq",
|
|
||||||
builtin_poly("Seq", vec![ty_tp(mono_q("T"))]),
|
|
||||||
)],
|
|
||||||
None,
|
None,
|
||||||
mono_q("T"),
|
mono_q("T"),
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use erg_common::vis::Visibility;
|
use erg_common::vis::Visibility;
|
||||||
|
|
||||||
use erg_type::constructors::{builtin_mono, func, or, param_t};
|
use erg_type::constructors::{builtin_mono, func, kw, or};
|
||||||
use erg_type::Type;
|
use erg_type::Type;
|
||||||
use Type::*;
|
use Type::*;
|
||||||
|
|
||||||
|
@ -21,10 +21,10 @@ impl Context {
|
||||||
vec![],
|
vec![],
|
||||||
None,
|
None,
|
||||||
vec![
|
vec![
|
||||||
param_t("family", Int),
|
kw("family", Int),
|
||||||
param_t("type", Int),
|
kw("type", Int),
|
||||||
param_t("proto", Int),
|
kw("proto", Int),
|
||||||
param_t("fileno", or(Int, NoneType)),
|
kw("fileno", or(Int, NoneType)),
|
||||||
],
|
],
|
||||||
builtin_mono("Socket!"),
|
builtin_mono("Socket!"),
|
||||||
),
|
),
|
||||||
|
|
|
@ -2,7 +2,7 @@ use std::path::PathBuf;
|
||||||
|
|
||||||
use erg_common::vis::Visibility;
|
use erg_common::vis::Visibility;
|
||||||
|
|
||||||
use erg_type::constructors::{builtin_mono, module_from_path, mono, or, param_t, proc};
|
use erg_type::constructors::{builtin_mono, kw, module_from_path, mono, or, proc};
|
||||||
use erg_type::Type;
|
use erg_type::Type;
|
||||||
use Type::*;
|
use Type::*;
|
||||||
|
|
||||||
|
@ -22,11 +22,11 @@ impl Context {
|
||||||
urllib.register_builtin_impl("request", module_from_path("request"), Immutable, Public);
|
urllib.register_builtin_impl("request", module_from_path("request"), Immutable, Public);
|
||||||
let mut request = Context::builtin_module("urllib.request", 15);
|
let mut request = Context::builtin_module("urllib.request", 15);
|
||||||
let t = proc(
|
let t = proc(
|
||||||
vec![param_t("url", or(Str, mono("urllib.request", "Request")))],
|
vec![kw("url", or(Str, mono("urllib.request", "Request")))],
|
||||||
None,
|
None,
|
||||||
vec![
|
vec![
|
||||||
param_t("data", or(builtin_mono("Bytes"), NoneType)),
|
kw("data", or(builtin_mono("Bytes"), NoneType)),
|
||||||
param_t("timeout", or(Nat, NoneType)),
|
kw("timeout", or(Nat, NoneType)),
|
||||||
],
|
],
|
||||||
mono("http.client", "HTTPResponse"),
|
mono("http.client", "HTTPResponse"),
|
||||||
);
|
);
|
||||||
|
|
|
@ -16,7 +16,10 @@ use ast::VarName;
|
||||||
use erg_parser::ast::{self, Identifier};
|
use erg_parser::ast::{self, Identifier};
|
||||||
use erg_parser::token::Token;
|
use erg_parser::token::Token;
|
||||||
|
|
||||||
use erg_type::constructors::{builtin_mono, func, module, mono, mono_proj, v_enum};
|
use erg_type::constructors::{
|
||||||
|
anon, builtin_mono, free_var, func, module, mono, mono_proj, subr_t, v_enum,
|
||||||
|
};
|
||||||
|
use erg_type::free::Constraint;
|
||||||
use erg_type::typaram::TyParam;
|
use erg_type::typaram::TyParam;
|
||||||
use erg_type::value::{GenTypeObj, TypeObj, ValueObj};
|
use erg_type::value::{GenTypeObj, TypeObj, ValueObj};
|
||||||
use erg_type::{HasType, ParamTy, SubrKind, SubrType, TyBound, Type};
|
use erg_type::{HasType, ParamTy, SubrKind, SubrType, TyBound, Type};
|
||||||
|
@ -32,6 +35,8 @@ use crate::varinfo::VarInfo;
|
||||||
use RegistrationMode::*;
|
use RegistrationMode::*;
|
||||||
use Visibility::*;
|
use Visibility::*;
|
||||||
|
|
||||||
|
use super::MethodType;
|
||||||
|
|
||||||
impl Context {
|
impl Context {
|
||||||
pub(crate) fn validate_var_sig_t(
|
pub(crate) fn validate_var_sig_t(
|
||||||
&self,
|
&self,
|
||||||
|
@ -93,7 +98,7 @@ impl Context {
|
||||||
) -> SingleTyCheckResult<&Context> {
|
) -> SingleTyCheckResult<&Context> {
|
||||||
match obj {
|
match obj {
|
||||||
hir::Expr::Accessor(hir::Accessor::Ident(ident)) => {
|
hir::Expr::Accessor(hir::Accessor::Ident(ident)) => {
|
||||||
self.get_singular_ctx_from_ident(&ident.clone().downcast(), namespace)
|
self.get_singular_ctx_by_ident(&ident.clone().downcast(), namespace)
|
||||||
}
|
}
|
||||||
hir::Expr::Accessor(hir::Accessor::Attr(attr)) => {
|
hir::Expr::Accessor(hir::Accessor::Attr(attr)) => {
|
||||||
// REVIEW: 両方singularとは限らない?
|
// REVIEW: 両方singularとは限らない?
|
||||||
|
@ -113,12 +118,12 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_singular_ctx_from_ident(
|
pub fn get_singular_ctx_by_ident(
|
||||||
&self,
|
&self,
|
||||||
ident: &ast::Identifier,
|
ident: &ast::Identifier,
|
||||||
namespace: &Str,
|
namespace: &Str,
|
||||||
) -> SingleTyCheckResult<&Context> {
|
) -> SingleTyCheckResult<&Context> {
|
||||||
self.get_mod(ident)
|
self.get_mod(ident.inspect())
|
||||||
.or_else(|| self.rec_get_type(ident.inspect()).map(|(_, ctx)| ctx))
|
.or_else(|| self.rec_get_type(ident.inspect()).map(|(_, ctx)| ctx))
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
TyCheckError::no_var_error(
|
TyCheckError::no_var_error(
|
||||||
|
@ -132,7 +137,7 @@ impl Context {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_mut_singular_ctx_from_ident(
|
pub fn get_mut_singular_ctx_by_ident(
|
||||||
&mut self,
|
&mut self,
|
||||||
ident: &ast::Identifier,
|
ident: &ast::Identifier,
|
||||||
namespace: &Str,
|
namespace: &Str,
|
||||||
|
@ -157,7 +162,7 @@ impl Context {
|
||||||
) -> SingleTyCheckResult<&mut Context> {
|
) -> SingleTyCheckResult<&mut Context> {
|
||||||
match obj {
|
match obj {
|
||||||
ast::Expr::Accessor(ast::Accessor::Ident(ident)) => {
|
ast::Expr::Accessor(ast::Accessor::Ident(ident)) => {
|
||||||
self.get_mut_singular_ctx_from_ident(ident, namespace)
|
self.get_mut_singular_ctx_by_ident(ident, namespace)
|
||||||
}
|
}
|
||||||
ast::Expr::Accessor(ast::Accessor::Attr(attr)) => {
|
ast::Expr::Accessor(ast::Accessor::Attr(attr)) => {
|
||||||
// REVIEW: 両方singularとは限らない?
|
// REVIEW: 両方singularとは限らない?
|
||||||
|
@ -335,6 +340,30 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn rec_get_decl_t(
|
||||||
|
&self,
|
||||||
|
ident: &Identifier,
|
||||||
|
input: &Input,
|
||||||
|
namespace: &Str,
|
||||||
|
) -> SingleTyCheckResult<Type> {
|
||||||
|
if let Some(vi) = self.decls.get(&ident.inspect()[..]) {
|
||||||
|
self.validate_visibility(ident, vi, input, namespace)?;
|
||||||
|
Ok(vi.t())
|
||||||
|
} else {
|
||||||
|
if let Some(parent) = self.get_outer().or_else(|| self.get_builtins()) {
|
||||||
|
return parent.rec_get_decl_t(ident, input, namespace);
|
||||||
|
}
|
||||||
|
Err(TyCheckError::no_var_error(
|
||||||
|
input.clone(),
|
||||||
|
line!() as usize,
|
||||||
|
ident.loc(),
|
||||||
|
namespace.into(),
|
||||||
|
ident.inspect(),
|
||||||
|
self.get_similar_name(ident.inspect()),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn rec_get_attr_t(
|
pub(crate) fn rec_get_attr_t(
|
||||||
&self,
|
&self,
|
||||||
obj: &hir::Expr,
|
obj: &hir::Expr,
|
||||||
|
@ -540,10 +569,12 @@ impl Context {
|
||||||
self.get_similar_attr_from_singular(obj, method_name.inspect()),
|
self.get_similar_attr_from_singular(obj, method_name.inspect()),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
match self.rec_get_method_traits(method_name) {
|
match self.get_method_type_by_name(method_name) {
|
||||||
Ok(trait_) => {
|
Ok(t) => {
|
||||||
let (_, ctx) = self.get_nominal_type_ctx(trait_).unwrap();
|
self.sub_unify(obj.ref_t(), &t.definition_type, obj.loc(), None)
|
||||||
return ctx.rec_get_var_t(method_name, input, namespace);
|
// HACK: change this func's return type to TyCheckResult<Type>
|
||||||
|
.map_err(|mut errs| errs.remove(0))?;
|
||||||
|
return Ok(t.method_type.clone());
|
||||||
}
|
}
|
||||||
Err(err) if err.core.kind == ErrorKind::TypeError => {
|
Err(err) if err.core.kind == ErrorKind::TypeError => {
|
||||||
return Err(err);
|
return Err(err);
|
||||||
|
@ -700,6 +731,7 @@ impl Context {
|
||||||
/// substitute_call(instance: ((?T, Int) -> ?T), [Int, Nat], []) => instance: (Int, Int) -> Str
|
/// substitute_call(instance: ((?T, Int) -> ?T), [Int, Nat], []) => instance: (Int, Int) -> Str
|
||||||
/// substitute_call(instance: ((?M(: Nat)..?N(: Nat)) -> ?M+?N), [1..2], []) => instance: (1..2) -> {3}
|
/// substitute_call(instance: ((?M(: Nat)..?N(: Nat)) -> ?M+?N), [1..2], []) => instance: (1..2) -> {3}
|
||||||
/// substitute_call(instance: ((?L(: Add(?R, ?O)), ?R) -> ?O), [1, 2], []) => instance: (Nat, Nat) -> Nat
|
/// substitute_call(instance: ((?L(: Add(?R, ?O)), ?R) -> ?O), [1, 2], []) => instance: (Nat, Nat) -> Nat
|
||||||
|
/// substitute_call(instance: ?T, [Int, Str], []) => instance: (Int, Str) -> Int
|
||||||
/// ```
|
/// ```
|
||||||
fn substitute_call(
|
fn substitute_call(
|
||||||
&self,
|
&self,
|
||||||
|
@ -713,6 +745,26 @@ impl Context {
|
||||||
Type::FreeVar(fv) if fv.is_linked() => {
|
Type::FreeVar(fv) if fv.is_linked() => {
|
||||||
self.substitute_call(obj, method_name, &fv.crack(), pos_args, kw_args)
|
self.substitute_call(obj, method_name, &fv.crack(), pos_args, kw_args)
|
||||||
}
|
}
|
||||||
|
Type::FreeVar(fv) => {
|
||||||
|
if let Some(_method_name) = method_name {
|
||||||
|
todo!()
|
||||||
|
} else {
|
||||||
|
let is_procedural = obj
|
||||||
|
.show_acc()
|
||||||
|
.map(|acc| acc.ends_with('!'))
|
||||||
|
.unwrap_or(false);
|
||||||
|
let kind = if is_procedural {
|
||||||
|
SubrKind::Proc
|
||||||
|
} else {
|
||||||
|
SubrKind::Func
|
||||||
|
};
|
||||||
|
let ret_t = free_var(self.level, Constraint::new_type_of(Type));
|
||||||
|
let non_default_params = pos_args.iter().map(|a| anon(a.expr.t())).collect();
|
||||||
|
let subr_t = subr_t(kind, non_default_params, None, vec![], ret_t);
|
||||||
|
fv.link(&subr_t);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
Type::Refinement(refine) => {
|
Type::Refinement(refine) => {
|
||||||
self.substitute_call(obj, method_name, &refine.t, pos_args, kw_args)
|
self.substitute_call(obj, method_name, &refine.t, pos_args, kw_args)
|
||||||
}
|
}
|
||||||
|
@ -788,6 +840,15 @@ impl Context {
|
||||||
&mut passed_params,
|
&mut passed_params,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
for not_passed in subr
|
||||||
|
.default_params
|
||||||
|
.iter()
|
||||||
|
.filter(|pt| !passed_params.contains(pt.name().unwrap()))
|
||||||
|
{
|
||||||
|
if let ParamTy::KwWithDefault { ty, default, .. } = not_passed {
|
||||||
|
self.sub_unify(default, ty, obj.loc(), not_passed.name())?;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
let missing_len = subr.non_default_params.len() - pos_args.len();
|
let missing_len = subr.non_default_params.len() - pos_args.len();
|
||||||
let missing_params = subr
|
let missing_params = subr
|
||||||
|
@ -1152,13 +1213,19 @@ impl Context {
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(opt_name, _)| {
|
.map(|(opt_name, _)| {
|
||||||
if let Some(name) = opt_name {
|
if let Some(name) = opt_name {
|
||||||
if let Some(t) = self.super_traits.iter().find(|t| {
|
// トレイトの変性を調べるときはsuper_classesも見る必要がある
|
||||||
|
if let Some(t) = self
|
||||||
|
.super_traits
|
||||||
|
.iter()
|
||||||
|
.chain(self.super_classes.iter())
|
||||||
|
.find(|t| {
|
||||||
(&t.name()[..] == "Input" || &t.name()[..] == "Output")
|
(&t.name()[..] == "Input" || &t.name()[..] == "Output")
|
||||||
&& t.inner_ts()
|
&& t.inner_ts()
|
||||||
.first()
|
.first()
|
||||||
.map(|t| &t.name() == name.inspect())
|
.map(|t| &t.name() == name.inspect())
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
}) {
|
})
|
||||||
|
{
|
||||||
match &t.name()[..] {
|
match &t.name()[..] {
|
||||||
"Output" => Variance::Covariant,
|
"Output" => Variance::Covariant,
|
||||||
"Input" => Variance::Contravariant,
|
"Input" => Variance::Contravariant,
|
||||||
|
@ -1280,7 +1347,17 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO
|
// TODO
|
||||||
Type::Or(_l, _r) => None,
|
Type::Or(l, r) => match (l.as_ref(), r.as_ref()) {
|
||||||
|
(Type::FreeVar(l), Type::FreeVar(r)) if l.is_unbound() && r.is_unbound() => {
|
||||||
|
let (_lsub, lsup) = l.get_bound_types().unwrap();
|
||||||
|
let (_rsub, rsup) = r.get_bound_types().unwrap();
|
||||||
|
self.get_nominal_super_type_ctxs(&self.union(&lsup, &rsup))
|
||||||
|
}
|
||||||
|
(Type::Refinement(l), Type::Refinement(r)) if l.t == r.t => {
|
||||||
|
self.get_nominal_super_type_ctxs(&l.t)
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
},
|
||||||
_ => self
|
_ => self
|
||||||
.get_simple_nominal_super_type_ctxs(t)
|
.get_simple_nominal_super_type_ctxs(t)
|
||||||
.map(|ctxs| ctxs.collect()),
|
.map(|ctxs| ctxs.collect()),
|
||||||
|
@ -1417,6 +1494,17 @@ impl Context {
|
||||||
return Some(res);
|
return Some(res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Type::Or(l, r) => {
|
||||||
|
let (lt, lctx) = self.get_nominal_type_ctx(l)?;
|
||||||
|
let (rt, rctx) = self.get_nominal_type_ctx(r)?;
|
||||||
|
// use smaller context
|
||||||
|
return match (self.supertype_of(lt, rt), self.supertype_of(rt, lt)) {
|
||||||
|
(true, true) => Some((rt, lctx)),
|
||||||
|
(true, false) => Some((rt, lctx)),
|
||||||
|
(false, true) => Some((lt, rctx)),
|
||||||
|
(false, false) => None,
|
||||||
|
};
|
||||||
|
}
|
||||||
// FIXME: `F()`などの場合、実際は引数が省略されていてもmonomorphicになる
|
// FIXME: `F()`などの場合、実際は引数が省略されていてもmonomorphicになる
|
||||||
other if other.is_monomorphic() => {
|
other if other.is_monomorphic() => {
|
||||||
if let Some((t, ctx)) = self.rec_get_mono_type(&other.name()) {
|
if let Some((t, ctx)) = self.rec_get_mono_type(&other.name()) {
|
||||||
|
@ -1491,14 +1579,43 @@ impl Context {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn rec_get_trait_impls(&self, name: &Str) -> Vec<TraitInstance> {
|
pub(crate) fn get_trait_impls(&self, t: &Type) -> Set<TraitInstance> {
|
||||||
let current = if let Some(impls) = self.trait_impls.get(name) {
|
match t {
|
||||||
|
// And(Add, Sub) == intersection({Int <: Add(Int), Bool <: Add(Bool) ...}, {Int <: Sub(Int), ...})
|
||||||
|
// == {Int <: Add(Int) and Sub(Int), ...}
|
||||||
|
Type::And(l, r) => {
|
||||||
|
let l_impls = self.get_trait_impls(l);
|
||||||
|
let l_base = Set::from_iter(l_impls.iter().map(|ti| &ti.sub_type));
|
||||||
|
let r_impls = self.get_trait_impls(r);
|
||||||
|
let r_base = Set::from_iter(r_impls.iter().map(|ti| &ti.sub_type));
|
||||||
|
let bases = l_base.intersection(&r_base);
|
||||||
|
let mut isec = set! {};
|
||||||
|
for base in bases.into_iter() {
|
||||||
|
let lti = l_impls.iter().find(|ti| &ti.sub_type == base).unwrap();
|
||||||
|
let rti = r_impls.iter().find(|ti| &ti.sub_type == base).unwrap();
|
||||||
|
let sup_trait = self.intersection(<i.sup_trait, &rti.sup_trait);
|
||||||
|
isec.insert(TraitInstance::new(lti.sub_type.clone(), sup_trait));
|
||||||
|
}
|
||||||
|
isec
|
||||||
|
}
|
||||||
|
Type::Or(l, r) => {
|
||||||
|
let l_impls = self.get_trait_impls(l);
|
||||||
|
let r_impls = self.get_trait_impls(r);
|
||||||
|
// FIXME:
|
||||||
|
l_impls.union(&r_impls)
|
||||||
|
}
|
||||||
|
_ => self.get_simple_trait_impls(t),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn get_simple_trait_impls(&self, t: &Type) -> Set<TraitInstance> {
|
||||||
|
let current = if let Some(impls) = self.trait_impls.get(&t.name()) {
|
||||||
impls.clone()
|
impls.clone()
|
||||||
} else {
|
} else {
|
||||||
vec![]
|
set! {}
|
||||||
};
|
};
|
||||||
if let Some(outer) = self.get_outer().or_else(|| self.get_builtins()) {
|
if let Some(outer) = self.get_outer().or_else(|| self.get_builtins()) {
|
||||||
[current, outer.rec_get_trait_impls(name)].concat()
|
current.union(&outer.get_simple_trait_impls(t))
|
||||||
} else {
|
} else {
|
||||||
current
|
current
|
||||||
}
|
}
|
||||||
|
@ -1515,10 +1632,8 @@ impl Context {
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: 現在の実装だとimportしたモジュールはどこからでも見れる
|
// FIXME: 現在の実装だとimportしたモジュールはどこからでも見れる
|
||||||
fn get_mod(&self, ident: &ast::Identifier) -> Option<&Context> {
|
pub(crate) fn get_mod(&self, name: &str) -> Option<&Context> {
|
||||||
let t = self
|
let t = self.get_var_info(name).map(|(_, vi)| vi.t.clone()).ok()?;
|
||||||
.rec_get_var_t(ident, &self.cfg.input, &self.name)
|
|
||||||
.ok()?;
|
|
||||||
match t {
|
match t {
|
||||||
Type::BuiltinPoly { name, mut params } if &name[..] == "Module" => {
|
Type::BuiltinPoly { name, mut params } if &name[..] == "Module" => {
|
||||||
let path =
|
let path =
|
||||||
|
@ -1624,7 +1739,7 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rec_get_type(&self, name: &str) -> Option<(&Type, &Context)> {
|
pub(crate) fn rec_get_type(&self, name: &str) -> Option<(&Type, &Context)> {
|
||||||
if let Some((t, ctx)) = self.mono_types.get(name) {
|
if let Some((t, ctx)) = self.mono_types.get(name) {
|
||||||
Some((t, ctx))
|
Some((t, ctx))
|
||||||
} else if let Some((t, ctx)) = self.poly_types.get(name) {
|
} else if let Some((t, ctx)) = self.poly_types.get(name) {
|
||||||
|
@ -1646,22 +1761,52 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rec_get_method_traits(&self, name: &Identifier) -> SingleTyCheckResult<&Type> {
|
fn get_method_type_by_name(&self, name: &Identifier) -> SingleTyCheckResult<&MethodType> {
|
||||||
if let Some(candidates) = self.method_traits.get(name.inspect()) {
|
// TODO: min_by
|
||||||
let first_t = candidates.first().unwrap();
|
if let Some(candidates) = self.method_to_traits.get(name.inspect()) {
|
||||||
if candidates.iter().skip(1).all(|t| t == first_t) {
|
let first_method_type = &candidates.first().unwrap().method_type;
|
||||||
Ok(&candidates[0])
|
if candidates
|
||||||
|
.iter()
|
||||||
|
.skip(1)
|
||||||
|
.all(|t| &t.method_type == first_method_type)
|
||||||
|
{
|
||||||
|
return Ok(&candidates[0]);
|
||||||
} else {
|
} else {
|
||||||
Err(TyCheckError::ambiguous_type_error(
|
return Err(TyCheckError::ambiguous_type_error(
|
||||||
self.cfg.input.clone(),
|
self.cfg.input.clone(),
|
||||||
line!() as usize,
|
line!() as usize,
|
||||||
name,
|
name,
|
||||||
candidates,
|
&candidates
|
||||||
|
.iter()
|
||||||
|
.map(|t| t.definition_type.clone())
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
self.caused_by(),
|
self.caused_by(),
|
||||||
))
|
));
|
||||||
}
|
}
|
||||||
} else if let Some(outer) = self.get_outer().or_else(|| self.get_builtins()) {
|
}
|
||||||
outer.rec_get_method_traits(name)
|
if let Some(candidates) = self.method_to_classes.get(name.inspect()) {
|
||||||
|
let first_method_type = &candidates.first().unwrap().method_type;
|
||||||
|
if candidates
|
||||||
|
.iter()
|
||||||
|
.skip(1)
|
||||||
|
.all(|t| &t.method_type == first_method_type)
|
||||||
|
{
|
||||||
|
return Ok(&candidates[0]);
|
||||||
|
} else {
|
||||||
|
return Err(TyCheckError::ambiguous_type_error(
|
||||||
|
self.cfg.input.clone(),
|
||||||
|
line!() as usize,
|
||||||
|
name,
|
||||||
|
&candidates
|
||||||
|
.iter()
|
||||||
|
.map(|t| t.definition_type.clone())
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
self.caused_by(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(outer) = self.get_outer().or_else(|| self.get_builtins()) {
|
||||||
|
outer.get_method_type_by_name(name)
|
||||||
} else {
|
} else {
|
||||||
Err(TyCheckError::no_attr_error(
|
Err(TyCheckError::no_attr_error(
|
||||||
self.cfg.input.clone(),
|
self.cfg.input.clone(),
|
||||||
|
@ -1731,7 +1876,7 @@ impl Context {
|
||||||
match lhs {
|
match lhs {
|
||||||
Type::FreeVar(fv) => {
|
Type::FreeVar(fv) => {
|
||||||
if let Some(sup) = fv.get_sup() {
|
if let Some(sup) = fv.get_sup() {
|
||||||
let insts = self.rec_get_trait_impls(&sup.name());
|
let insts = self.get_trait_impls(&sup);
|
||||||
let candidates = insts.into_iter().filter_map(move |inst| {
|
let candidates = insts.into_iter().filter_map(move |inst| {
|
||||||
if self.supertype_of(&inst.sup_trait, &sup) {
|
if self.supertype_of(&inst.sup_trait, &sup) {
|
||||||
self.eval_t_params(
|
self.eval_t_params(
|
||||||
|
|
|
@ -168,6 +168,62 @@ impl TyVarContext {
|
||||||
};
|
};
|
||||||
mono_proj(lhs, rhs)
|
mono_proj(lhs, rhs)
|
||||||
}
|
}
|
||||||
|
Type::Ref(t) if t.has_qvar() => ref_(self.instantiate_qvar(*t)),
|
||||||
|
Type::RefMut { before, after } => {
|
||||||
|
let before = if before.has_qvar() {
|
||||||
|
self.instantiate_qvar(*before)
|
||||||
|
} else {
|
||||||
|
*before
|
||||||
|
};
|
||||||
|
let after = after.map(|t| {
|
||||||
|
if t.has_qvar() {
|
||||||
|
self.instantiate_qvar(*t)
|
||||||
|
} else {
|
||||||
|
*t
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ref_mut(before, after)
|
||||||
|
}
|
||||||
|
Type::And(l, r) => {
|
||||||
|
let l = if l.has_qvar() {
|
||||||
|
self.instantiate_qvar(*l)
|
||||||
|
} else {
|
||||||
|
*l
|
||||||
|
};
|
||||||
|
let r = if r.has_qvar() {
|
||||||
|
self.instantiate_qvar(*r)
|
||||||
|
} else {
|
||||||
|
*r
|
||||||
|
};
|
||||||
|
and(l, r)
|
||||||
|
}
|
||||||
|
Type::Or(l, r) => {
|
||||||
|
let l = if l.has_qvar() {
|
||||||
|
self.instantiate_qvar(*l)
|
||||||
|
} else {
|
||||||
|
*l
|
||||||
|
};
|
||||||
|
let r = if r.has_qvar() {
|
||||||
|
self.instantiate_qvar(*r)
|
||||||
|
} else {
|
||||||
|
*r
|
||||||
|
};
|
||||||
|
or(l, r)
|
||||||
|
}
|
||||||
|
Type::Not(l, r) => {
|
||||||
|
let l = if l.has_qvar() {
|
||||||
|
self.instantiate_qvar(*l)
|
||||||
|
} else {
|
||||||
|
*l
|
||||||
|
};
|
||||||
|
let r = if r.has_qvar() {
|
||||||
|
self.instantiate_qvar(*r)
|
||||||
|
} else {
|
||||||
|
*r
|
||||||
|
};
|
||||||
|
not(l, r)
|
||||||
|
}
|
||||||
|
Type::MonoQVar(_) => self.instantiate_qvar(sub_or_sup),
|
||||||
other => other,
|
other => other,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -461,7 +517,7 @@ impl Context {
|
||||||
) -> TyCheckResult<Type> {
|
) -> TyCheckResult<Type> {
|
||||||
// -> Result<Type, (Type, TyCheckErrors)> {
|
// -> Result<Type, (Type, TyCheckErrors)> {
|
||||||
let opt_decl_sig_t = self
|
let opt_decl_sig_t = self
|
||||||
.rec_get_var_t(&sig.ident, &self.cfg.input, &self.name)
|
.rec_get_decl_t(&sig.ident, &self.cfg.input, &self.name)
|
||||||
.ok()
|
.ok()
|
||||||
.map(|t| enum_unwrap!(t, Type::Subr));
|
.map(|t| enum_unwrap!(t, Type::Subr));
|
||||||
let bounds = self.instantiate_ty_bounds(&sig.bounds, PreRegister)?;
|
let bounds = self.instantiate_ty_bounds(&sig.bounds, PreRegister)?;
|
||||||
|
@ -471,17 +527,13 @@ impl Context {
|
||||||
let opt_decl_t = opt_decl_sig_t
|
let opt_decl_t = opt_decl_sig_t
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|subr| subr.non_default_params.get(n));
|
.and_then(|subr| subr.non_default_params.get(n));
|
||||||
non_defaults.push(ParamTy::pos(
|
non_defaults.push(self.instantiate_param_ty(p, opt_decl_t, Some(&tv_ctx), mode)?);
|
||||||
p.inspect().cloned(),
|
|
||||||
self.instantiate_param_sig_t(p, opt_decl_t, Some(&tv_ctx), mode)?,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
let var_args = if let Some(var_args) = sig.params.var_args.as_ref() {
|
let var_args = if let Some(var_args) = sig.params.var_args.as_ref() {
|
||||||
let opt_decl_t = opt_decl_sig_t
|
let opt_decl_t = opt_decl_sig_t
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|subr| subr.var_params.as_ref().map(|v| v.as_ref()));
|
.and_then(|subr| subr.var_params.as_ref().map(|v| v.as_ref()));
|
||||||
let va_t = self.instantiate_param_sig_t(var_args, opt_decl_t, Some(&tv_ctx), mode)?;
|
Some(self.instantiate_param_ty(var_args, opt_decl_t, Some(&tv_ctx), mode)?)
|
||||||
Some(ParamTy::pos(var_args.inspect().cloned(), va_t))
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
@ -490,10 +542,7 @@ impl Context {
|
||||||
let opt_decl_t = opt_decl_sig_t
|
let opt_decl_t = opt_decl_sig_t
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|subr| subr.default_params.get(n));
|
.and_then(|subr| subr.default_params.get(n));
|
||||||
defaults.push(ParamTy::kw(
|
defaults.push(self.instantiate_param_ty(p, opt_decl_t, Some(&tv_ctx), mode)?);
|
||||||
p.inspect().unwrap().clone(),
|
|
||||||
self.instantiate_param_sig_t(p, opt_decl_t, Some(&tv_ctx), mode)?,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
let spec_return_t = if let Some(s) = sig.return_t_spec.as_ref() {
|
let spec_return_t = if let Some(s) = sig.return_t_spec.as_ref() {
|
||||||
let opt_decl_t = opt_decl_sig_t
|
let opt_decl_t = opt_decl_sig_t
|
||||||
|
@ -554,6 +603,29 @@ impl Context {
|
||||||
Ok(spec_t)
|
Ok(spec_t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn instantiate_param_ty(
|
||||||
|
&self,
|
||||||
|
sig: &ParamSignature,
|
||||||
|
opt_decl_t: Option<&ParamTy>,
|
||||||
|
tmp_tv_ctx: Option<&TyVarContext>,
|
||||||
|
mode: RegistrationMode,
|
||||||
|
) -> TyCheckResult<ParamTy> {
|
||||||
|
let t = self.instantiate_param_sig_t(sig, opt_decl_t, tmp_tv_ctx, mode)?;
|
||||||
|
match (sig.inspect(), &sig.opt_default_val) {
|
||||||
|
(Some(name), Some(default)) => {
|
||||||
|
let default = self.instantiate_const_expr(default);
|
||||||
|
Ok(ParamTy::kw_default(
|
||||||
|
name.clone(),
|
||||||
|
t,
|
||||||
|
self.get_tp_t(&default)?,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
(Some(name), None) => Ok(ParamTy::kw(name.clone(), t)),
|
||||||
|
(None, None) => Ok(ParamTy::anonymous(t)),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn instantiate_predecl_t(
|
pub(crate) fn instantiate_predecl_t(
|
||||||
&self,
|
&self,
|
||||||
predecl: &PreDeclTypeSpec,
|
predecl: &PreDeclTypeSpec,
|
||||||
|
@ -695,19 +767,18 @@ impl Context {
|
||||||
TypeSpec::PreDeclTy(predecl) => {
|
TypeSpec::PreDeclTy(predecl) => {
|
||||||
Ok(self.instantiate_predecl_t(predecl, opt_decl_t, tmp_tv_ctx)?)
|
Ok(self.instantiate_predecl_t(predecl, opt_decl_t, tmp_tv_ctx)?)
|
||||||
}
|
}
|
||||||
// TODO: Flatten
|
TypeSpec::And(lhs, rhs) => Ok(self.union(
|
||||||
TypeSpec::And(lhs, rhs) => Ok(and(
|
&self.instantiate_typespec(lhs, opt_decl_t, tmp_tv_ctx, mode)?,
|
||||||
self.instantiate_typespec(lhs, opt_decl_t, tmp_tv_ctx, mode)?,
|
&self.instantiate_typespec(rhs, opt_decl_t, tmp_tv_ctx, mode)?,
|
||||||
self.instantiate_typespec(rhs, opt_decl_t, tmp_tv_ctx, mode)?,
|
)),
|
||||||
|
TypeSpec::Or(lhs, rhs) => Ok(self.intersection(
|
||||||
|
&self.instantiate_typespec(lhs, opt_decl_t, tmp_tv_ctx, mode)?,
|
||||||
|
&self.instantiate_typespec(rhs, opt_decl_t, tmp_tv_ctx, mode)?,
|
||||||
)),
|
)),
|
||||||
TypeSpec::Not(lhs, rhs) => Ok(not(
|
TypeSpec::Not(lhs, rhs) => Ok(not(
|
||||||
self.instantiate_typespec(lhs, opt_decl_t, tmp_tv_ctx, mode)?,
|
self.instantiate_typespec(lhs, opt_decl_t, tmp_tv_ctx, mode)?,
|
||||||
self.instantiate_typespec(rhs, opt_decl_t, tmp_tv_ctx, mode)?,
|
self.instantiate_typespec(rhs, opt_decl_t, tmp_tv_ctx, mode)?,
|
||||||
)),
|
)),
|
||||||
TypeSpec::Or(lhs, rhs) => Ok(or(
|
|
||||||
self.instantiate_typespec(lhs, opt_decl_t, tmp_tv_ctx, mode)?,
|
|
||||||
self.instantiate_typespec(rhs, opt_decl_t, tmp_tv_ctx, mode)?,
|
|
||||||
)),
|
|
||||||
TypeSpec::Array(arr) => {
|
TypeSpec::Array(arr) => {
|
||||||
let elem_t = self.instantiate_typespec(&arr.ty, opt_decl_t, tmp_tv_ctx, mode)?;
|
let elem_t = self.instantiate_typespec(&arr.ty, opt_decl_t, tmp_tv_ctx, mode)?;
|
||||||
let len = self.instantiate_const_expr(&arr.len);
|
let len = self.instantiate_const_expr(&arr.len);
|
||||||
|
@ -945,13 +1016,14 @@ impl Context {
|
||||||
*pt.typ_mut() = self.instantiate_t(mem::take(pt.typ_mut()), tmp_tv_ctx, loc)?;
|
*pt.typ_mut() = self.instantiate_t(mem::take(pt.typ_mut()), tmp_tv_ctx, loc)?;
|
||||||
}
|
}
|
||||||
let return_t = self.instantiate_t(*subr.return_t, tmp_tv_ctx, loc)?;
|
let return_t = self.instantiate_t(*subr.return_t, tmp_tv_ctx, loc)?;
|
||||||
Ok(subr_t(
|
let res = subr_t(
|
||||||
subr.kind,
|
subr.kind,
|
||||||
subr.non_default_params,
|
subr.non_default_params,
|
||||||
subr.var_params.map(|p| *p),
|
subr.var_params.map(|p| *p),
|
||||||
subr.default_params,
|
subr.default_params,
|
||||||
return_t,
|
return_t,
|
||||||
))
|
);
|
||||||
|
Ok(res)
|
||||||
}
|
}
|
||||||
Record(mut dict) => {
|
Record(mut dict) => {
|
||||||
for v in dict.values_mut() {
|
for v in dict.values_mut() {
|
||||||
|
@ -1007,12 +1079,12 @@ impl Context {
|
||||||
And(l, r) => {
|
And(l, r) => {
|
||||||
let l = self.instantiate_t(*l, tmp_tv_ctx, loc)?;
|
let l = self.instantiate_t(*l, tmp_tv_ctx, loc)?;
|
||||||
let r = self.instantiate_t(*r, tmp_tv_ctx, loc)?;
|
let r = self.instantiate_t(*r, tmp_tv_ctx, loc)?;
|
||||||
Ok(and(l, r))
|
Ok(self.intersection(&l, &r))
|
||||||
}
|
}
|
||||||
Or(l, r) => {
|
Or(l, r) => {
|
||||||
let l = self.instantiate_t(*l, tmp_tv_ctx, loc)?;
|
let l = self.instantiate_t(*l, tmp_tv_ctx, loc)?;
|
||||||
let r = self.instantiate_t(*r, tmp_tv_ctx, loc)?;
|
let r = self.instantiate_t(*r, tmp_tv_ctx, loc)?;
|
||||||
Ok(or(l, r))
|
Ok(self.union(&l, &r))
|
||||||
}
|
}
|
||||||
Not(l, r) => {
|
Not(l, r) => {
|
||||||
let l = self.instantiate_t(*l, tmp_tv_ctx, loc)?;
|
let l = self.instantiate_t(*l, tmp_tv_ctx, loc)?;
|
||||||
|
|
|
@ -23,6 +23,7 @@ use erg_common::config::ErgConfig;
|
||||||
use erg_common::dict::Dict;
|
use erg_common::dict::Dict;
|
||||||
use erg_common::error::Location;
|
use erg_common::error::Location;
|
||||||
use erg_common::impl_display_from_debug;
|
use erg_common::impl_display_from_debug;
|
||||||
|
use erg_common::set::Set;
|
||||||
use erg_common::traits::{Locational, Stream};
|
use erg_common::traits::{Locational, Stream};
|
||||||
use erg_common::vis::Visibility;
|
use erg_common::vis::Visibility;
|
||||||
use erg_common::Str;
|
use erg_common::Str;
|
||||||
|
@ -274,15 +275,17 @@ pub enum RegistrationMode {
|
||||||
Normal,
|
Normal,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Some Erg functions require additional operation by the compiler.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum ImportKind {
|
pub enum OperationKind {
|
||||||
ErgImport,
|
Import,
|
||||||
PyImport,
|
PyImport,
|
||||||
|
Del,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ImportKind {
|
impl OperationKind {
|
||||||
pub const fn is_erg_import(&self) -> bool {
|
pub const fn is_erg_import(&self) -> bool {
|
||||||
matches!(self, Self::ErgImport)
|
matches!(self, Self::Import)
|
||||||
}
|
}
|
||||||
pub const fn is_py_import(&self) -> bool {
|
pub const fn is_py_import(&self) -> bool {
|
||||||
matches!(self, Self::PyImport)
|
matches!(self, Self::PyImport)
|
||||||
|
@ -294,6 +297,31 @@ pub struct ContextInfo {
|
||||||
mod_id: usize,
|
mod_id: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub struct MethodType {
|
||||||
|
definition_type: Type,
|
||||||
|
method_type: Type,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for MethodType {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{{ def: {} t: {} }}",
|
||||||
|
self.definition_type, self.method_type
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MethodType {
|
||||||
|
pub const fn new(definition_type: Type, method_type: Type) -> Self {
|
||||||
|
Self {
|
||||||
|
definition_type,
|
||||||
|
method_type,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Represents the context of the current scope
|
/// Represents the context of the current scope
|
||||||
///
|
///
|
||||||
/// Recursive functions/methods are highlighted with the prefix `rec_`, as performance may be significantly degraded.
|
/// Recursive functions/methods are highlighted with the prefix `rec_`, as performance may be significantly degraded.
|
||||||
|
@ -317,8 +345,10 @@ pub struct Context {
|
||||||
// method definitions, if the context is a type
|
// method definitions, if the context is a type
|
||||||
// specializations are included and needs to be separated out
|
// specializations are included and needs to be separated out
|
||||||
pub(crate) methods_list: Vec<(ClassDefType, Context)>,
|
pub(crate) methods_list: Vec<(ClassDefType, Context)>,
|
||||||
// K: method name, V: trait defines the method
|
// K: method name, V: types defines the method
|
||||||
pub(crate) method_traits: Dict<Str, Vec<Type>>,
|
// If it is declared in a trait, it takes precedence over the class.
|
||||||
|
pub(crate) method_to_traits: Dict<Str, Vec<MethodType>>,
|
||||||
|
pub(crate) method_to_classes: Dict<Str, Vec<MethodType>>,
|
||||||
/// K: method name, V: impl patch
|
/// K: method name, V: impl patch
|
||||||
/// Provided methods can switch implementations on a scope-by-scope basis
|
/// Provided methods can switch implementations on a scope-by-scope basis
|
||||||
/// K: メソッド名, V: それを実装するパッチたち
|
/// K: メソッド名, V: それを実装するパッチたち
|
||||||
|
@ -327,7 +357,7 @@ pub struct Context {
|
||||||
/// K: name of a trait, V: (type, monomorphised trait that the type implements)
|
/// K: name of a trait, V: (type, monomorphised trait that the type implements)
|
||||||
/// K: トレイトの名前, V: (型, その型が実装する単相化トレイト)
|
/// K: トレイトの名前, V: (型, その型が実装する単相化トレイト)
|
||||||
/// e.g. { "Named": [(Type, Named), (Func, Named), ...], "Add": [(Nat, Add(Nat)), (Int, Add(Int)), ...], ... }
|
/// e.g. { "Named": [(Type, Named), (Func, Named), ...], "Add": [(Nat, Add(Nat)), (Int, Add(Int)), ...], ... }
|
||||||
pub(crate) trait_impls: Dict<Str, Vec<TraitInstance>>,
|
pub(crate) trait_impls: Dict<Str, Set<TraitInstance>>,
|
||||||
/// stores declared names (not initialized)
|
/// stores declared names (not initialized)
|
||||||
pub(crate) decls: Dict<VarName, VarInfo>,
|
pub(crate) decls: Dict<VarName, VarInfo>,
|
||||||
// stores defined names
|
// stores defined names
|
||||||
|
@ -456,7 +486,8 @@ impl Context {
|
||||||
super_traits: vec![],
|
super_traits: vec![],
|
||||||
methods_list: vec![],
|
methods_list: vec![],
|
||||||
const_param_defaults: Dict::default(),
|
const_param_defaults: Dict::default(),
|
||||||
method_traits: Dict::default(),
|
method_to_traits: Dict::default(),
|
||||||
|
method_to_classes: Dict::default(),
|
||||||
method_impl_patches: Dict::default(),
|
method_impl_patches: Dict::default(),
|
||||||
trait_impls: Dict::default(),
|
trait_impls: Dict::default(),
|
||||||
params: params_,
|
params: params_,
|
||||||
|
@ -871,15 +902,28 @@ impl Context {
|
||||||
/// for language server
|
/// for language server
|
||||||
impl Context {
|
impl Context {
|
||||||
pub fn dir(&self) -> Vec<(&VarName, &VarInfo)> {
|
pub fn dir(&self) -> Vec<(&VarName, &VarInfo)> {
|
||||||
let mut vars: Vec<_> = self.locals.iter().collect();
|
let mut vars: Vec<_> = self
|
||||||
|
.locals
|
||||||
|
.iter()
|
||||||
|
.chain(self.methods_list.iter().flat_map(|(_, ctx)| ctx.dir()))
|
||||||
|
.collect();
|
||||||
if let Some(outer) = self.get_outer() {
|
if let Some(outer) = self.get_outer() {
|
||||||
vars.extend(outer.dir());
|
vars.extend(outer.dir());
|
||||||
} else {
|
} else if let Some(builtins) = self.get_builtins() {
|
||||||
vars.extend(self.get_builtins().unwrap().locals.iter());
|
vars.extend(builtins.locals.iter());
|
||||||
}
|
}
|
||||||
vars
|
vars
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_receiver_ctx(&self, receiver_name: &str) -> Option<&Context> {
|
||||||
|
self.get_mod(receiver_name)
|
||||||
|
.or_else(|| {
|
||||||
|
let (_, vi) = self.get_var_info(receiver_name).ok()?;
|
||||||
|
self.get_nominal_type_ctx(&vi.t).map(|(_, ctx)| ctx)
|
||||||
|
})
|
||||||
|
.or_else(|| self.rec_get_type(receiver_name).map(|(_, ctx)| ctx))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_var_info(&self, name: &str) -> SingleTyCheckResult<(&VarName, &VarInfo)> {
|
pub fn get_var_info(&self, name: &str) -> SingleTyCheckResult<(&VarName, &VarInfo)> {
|
||||||
if let Some(info) = self.get_local_kv(name) {
|
if let Some(info) = self.get_local_kv(name) {
|
||||||
Ok(info)
|
Ok(info)
|
||||||
|
|
|
@ -15,16 +15,17 @@ use erg_parser::ast;
|
||||||
|
|
||||||
use erg_type::constructors::{func, func1, proc, ref_, ref_mut, v_enum};
|
use erg_type::constructors::{func, func1, proc, ref_, ref_mut, v_enum};
|
||||||
use erg_type::value::{GenTypeObj, TypeKind, TypeObj, ValueObj};
|
use erg_type::value::{GenTypeObj, TypeKind, TypeObj, ValueObj};
|
||||||
use erg_type::{ParamTy, SubrType, TyBound, Type};
|
use erg_type::{ParamTy, SubrType, Type};
|
||||||
|
|
||||||
use crate::build_hir::HIRBuilder;
|
use crate::build_hir::HIRBuilder;
|
||||||
use crate::context::{
|
use crate::context::{
|
||||||
ClassDefType, Context, ContextKind, DefaultInfo, RegistrationMode, TraitInstance,
|
ClassDefType, Context, ContextKind, DefaultInfo, MethodType, RegistrationMode, TraitInstance,
|
||||||
};
|
};
|
||||||
use crate::error::readable_name;
|
use crate::error::readable_name;
|
||||||
use crate::error::{
|
use crate::error::{
|
||||||
CompileResult, SingleTyCheckResult, TyCheckError, TyCheckErrors, TyCheckResult,
|
CompileResult, SingleTyCheckResult, TyCheckError, TyCheckErrors, TyCheckResult,
|
||||||
};
|
};
|
||||||
|
use crate::hir;
|
||||||
use crate::hir::Literal;
|
use crate::hir::Literal;
|
||||||
use crate::mod_cache::SharedModuleCache;
|
use crate::mod_cache::SharedModuleCache;
|
||||||
use crate::varinfo::{Mutability, ParamIdx, VarInfo, VarKind};
|
use crate::varinfo::{Mutability, ParamIdx, VarInfo, VarKind};
|
||||||
|
@ -33,7 +34,7 @@ use RegistrationMode::*;
|
||||||
use Visibility::*;
|
use Visibility::*;
|
||||||
|
|
||||||
use super::instantiate::TyVarContext;
|
use super::instantiate::TyVarContext;
|
||||||
use super::ImportKind;
|
use super::OperationKind;
|
||||||
|
|
||||||
impl Context {
|
impl Context {
|
||||||
/// If it is a constant that is defined, there must be no variable of the same name defined across all scopes
|
/// If it is a constant that is defined, there must be no variable of the same name defined across all scopes
|
||||||
|
@ -347,12 +348,13 @@ impl Context {
|
||||||
sig: &ast::SubrSignature,
|
sig: &ast::SubrSignature,
|
||||||
id: DefId,
|
id: DefId,
|
||||||
body_t: &Type,
|
body_t: &Type,
|
||||||
) -> TyCheckResult<()> {
|
) -> TyCheckResult<Type> {
|
||||||
// already defined as const
|
// already defined as const
|
||||||
if sig.is_const() {
|
if sig.is_const() {
|
||||||
let vi = self.decls.remove(sig.ident.inspect()).unwrap();
|
let vi = self.decls.remove(sig.ident.inspect()).unwrap();
|
||||||
|
let t = vi.t.clone();
|
||||||
self.locals.insert(sig.ident.name.clone(), vi);
|
self.locals.insert(sig.ident.name.clone(), vi);
|
||||||
return Ok(());
|
return Ok(t);
|
||||||
}
|
}
|
||||||
let muty = if sig.ident.is_const() {
|
let muty = if sig.ident.is_const() {
|
||||||
Mutability::Const
|
Mutability::Const
|
||||||
|
@ -442,9 +444,10 @@ impl Context {
|
||||||
VarKind::Defined(id),
|
VarKind::Defined(id),
|
||||||
Some(comptime_decos),
|
Some(comptime_decos),
|
||||||
);
|
);
|
||||||
log!(info "Registered {}::{name}: {}", self.name, &vi.t);
|
let t = vi.t.clone();
|
||||||
|
log!(info "Registered {}::{name}: {}", self.name, t);
|
||||||
self.locals.insert(name.clone(), vi);
|
self.locals.insert(name.clone(), vi);
|
||||||
Ok(())
|
Ok(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn fake_subr_assign(&mut self, sig: &ast::SubrSignature, failure_t: Type) {
|
pub(crate) fn fake_subr_assign(&mut self, sig: &ast::SubrSignature, failure_t: Type) {
|
||||||
|
@ -632,10 +635,12 @@ impl Context {
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
match obj {
|
match obj {
|
||||||
ValueObj::Type(t) => {
|
ValueObj::Type(t) => match t {
|
||||||
let gen = enum_unwrap!(t, TypeObj::Generated);
|
TypeObj::Generated(gen) => {
|
||||||
self.register_gen_type(ident, gen);
|
self.register_gen_type(ident, gen);
|
||||||
}
|
}
|
||||||
|
TypeObj::Builtin(_t) => panic!("aliasing bug"),
|
||||||
|
},
|
||||||
// TODO: not all value objects are comparable
|
// TODO: not all value objects are comparable
|
||||||
other => {
|
other => {
|
||||||
let id = DefId(get_hash(ident));
|
let id = DefId(get_hash(ident));
|
||||||
|
@ -834,20 +839,32 @@ impl Context {
|
||||||
.insert(name.clone(), ValueObj::Type(TypeObj::Generated(gen)));
|
.insert(name.clone(), ValueObj::Type(TypeObj::Generated(gen)));
|
||||||
for impl_trait in ctx.super_traits.iter() {
|
for impl_trait in ctx.super_traits.iter() {
|
||||||
if let Some(impls) = self.trait_impls.get_mut(&impl_trait.name()) {
|
if let Some(impls) = self.trait_impls.get_mut(&impl_trait.name()) {
|
||||||
impls.push(TraitInstance::new(t.clone(), impl_trait.clone()));
|
impls.insert(TraitInstance::new(t.clone(), impl_trait.clone()));
|
||||||
} else {
|
} else {
|
||||||
self.trait_impls.insert(
|
self.trait_impls.insert(
|
||||||
impl_trait.name(),
|
impl_trait.name(),
|
||||||
vec![TraitInstance::new(t.clone(), impl_trait.clone())],
|
set![TraitInstance::new(t.clone(), impl_trait.clone())],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for method in ctx.decls.keys() {
|
for (trait_method, vi) in ctx.decls.iter() {
|
||||||
if let Some(impls) = self.method_traits.get_mut(method.inspect()) {
|
if let Some(types) = self.method_to_traits.get_mut(trait_method.inspect()) {
|
||||||
impls.push(t.clone());
|
types.push(MethodType::new(t.clone(), vi.t.clone()));
|
||||||
} else {
|
} else {
|
||||||
self.method_traits
|
self.method_to_traits.insert(
|
||||||
.insert(method.inspect().clone(), vec![t.clone()]);
|
trait_method.inspect().clone(),
|
||||||
|
vec![MethodType::new(t.clone(), vi.t.clone())],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (class_method, vi) in ctx.locals.iter() {
|
||||||
|
if let Some(types) = self.method_to_classes.get_mut(class_method.inspect()) {
|
||||||
|
types.push(MethodType::new(t.clone(), vi.t.clone()));
|
||||||
|
} else {
|
||||||
|
self.method_to_classes.insert(
|
||||||
|
class_method.inspect().clone(),
|
||||||
|
vec![MethodType::new(t.clone(), vi.t.clone())],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.mono_types.insert(name.clone(), (t, ctx));
|
self.mono_types.insert(name.clone(), (t, ctx));
|
||||||
|
@ -856,7 +873,7 @@ impl Context {
|
||||||
|
|
||||||
pub(crate) fn import_mod(
|
pub(crate) fn import_mod(
|
||||||
&mut self,
|
&mut self,
|
||||||
kind: ImportKind,
|
kind: OperationKind,
|
||||||
mod_name: &Literal,
|
mod_name: &Literal,
|
||||||
) -> CompileResult<PathBuf> {
|
) -> CompileResult<PathBuf> {
|
||||||
if kind.is_erg_import() {
|
if kind.is_erg_import() {
|
||||||
|
@ -1031,11 +1048,32 @@ impl Context {
|
||||||
Ok(path)
|
Ok(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn _push_subtype_bound(&mut self, sub: Type, sup: Type) {
|
pub fn del(&mut self, ident: &hir::Identifier) -> CompileResult<()> {
|
||||||
self.bounds.push(TyBound::subtype_of(sub, sup));
|
if self.rec_get_const_obj(ident.inspect()).is_some()
|
||||||
}
|
|| self
|
||||||
|
.get_builtins()
|
||||||
pub(crate) fn _push_instance_bound(&mut self, name: Str, t: Type) {
|
.unwrap()
|
||||||
self.bounds.push(TyBound::instance(name, t));
|
.get_local_kv(ident.inspect())
|
||||||
|
.is_some()
|
||||||
|
{
|
||||||
|
Err(TyCheckErrors::from(TyCheckError::del_error(
|
||||||
|
self.cfg.input.clone(),
|
||||||
|
line!() as usize,
|
||||||
|
ident,
|
||||||
|
self.caused_by(),
|
||||||
|
)))
|
||||||
|
} else if self.locals.get(ident.inspect()).is_some() {
|
||||||
|
self.locals.remove(ident.inspect());
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(TyCheckErrors::from(TyCheckError::no_var_error(
|
||||||
|
self.cfg.input.clone(),
|
||||||
|
line!() as usize,
|
||||||
|
ident.loc(),
|
||||||
|
self.caused_by(),
|
||||||
|
ident.inspect(),
|
||||||
|
self.get_similar_name(ident.inspect()),
|
||||||
|
)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,9 +32,9 @@ impl Context {
|
||||||
pub fn test_resolve_trait_inner1(&self) -> Result<(), ()> {
|
pub fn test_resolve_trait_inner1(&self) -> Result<(), ()> {
|
||||||
let name = Str::ever("Add");
|
let name = Str::ever("Add");
|
||||||
let params = vec![TyParam::t(Nat)];
|
let params = vec![TyParam::t(Nat)];
|
||||||
let maybe_trait = builtin_poly(name.clone(), params);
|
let maybe_trait = builtin_poly(name, params);
|
||||||
let mut min = Type::Obj;
|
let mut min = Type::Obj;
|
||||||
for pair in self.rec_get_trait_impls(&name) {
|
for pair in self.get_trait_impls(&maybe_trait) {
|
||||||
if self.supertype_of(&pair.sup_trait, &maybe_trait) {
|
if self.supertype_of(&pair.sup_trait, &maybe_trait) {
|
||||||
min = self.min(&min, &pair.sub_type).unwrap_or(&min).clone();
|
min = self.min(&min, &pair.sub_type).unwrap_or(&min).clone();
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,16 +120,32 @@ impl Context {
|
||||||
// TODO: Polymorphic generalization
|
// TODO: Polymorphic generalization
|
||||||
FreeVar(fv) if fv.level().unwrap() > self.level => match &*fv.borrow() {
|
FreeVar(fv) if fv.level().unwrap() > self.level => match &*fv.borrow() {
|
||||||
FreeKind::Unbound { id, constraint, .. } => {
|
FreeKind::Unbound { id, constraint, .. } => {
|
||||||
|
// |Int <: T <: Int| T -> T ==> Int -> Int
|
||||||
|
let (l, r) = constraint.get_sub_sup().unwrap();
|
||||||
|
if l == r {
|
||||||
|
fv.forced_link(&l.clone());
|
||||||
|
FreeVar(fv.clone())
|
||||||
|
} else if r != &Obj && self.is_class(r) {
|
||||||
|
// x: T <: Bool ==> x: Bool
|
||||||
|
r.clone()
|
||||||
|
} else {
|
||||||
let name = format!("%{id}");
|
let name = format!("%{id}");
|
||||||
self.generalize_constraint(&name, constraint, bounds, lazy_inits);
|
self.generalize_constraint(&name, constraint, bounds, lazy_inits);
|
||||||
mono_q(name)
|
mono_q(name)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
FreeKind::NamedUnbound {
|
FreeKind::NamedUnbound {
|
||||||
name, constraint, ..
|
name, constraint, ..
|
||||||
} => {
|
} => {
|
||||||
|
let (l, r) = constraint.get_sub_sup().unwrap();
|
||||||
|
if l == r {
|
||||||
|
fv.forced_link(l);
|
||||||
|
FreeVar(fv.clone())
|
||||||
|
} else {
|
||||||
self.generalize_constraint(name, constraint, bounds, lazy_inits);
|
self.generalize_constraint(name, constraint, bounds, lazy_inits);
|
||||||
mono_q(name)
|
mono_q(name)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
_ => assume_unreachable!(),
|
_ => assume_unreachable!(),
|
||||||
},
|
},
|
||||||
Subr(mut subr) => {
|
Subr(mut subr) => {
|
||||||
|
@ -182,6 +198,23 @@ impl Context {
|
||||||
let lhs = self.generalize_t_inner(*lhs, bounds, lazy_inits);
|
let lhs = self.generalize_t_inner(*lhs, bounds, lazy_inits);
|
||||||
mono_proj(lhs, rhs)
|
mono_proj(lhs, rhs)
|
||||||
}
|
}
|
||||||
|
And(l, r) => {
|
||||||
|
let l = self.generalize_t_inner(*l, bounds, lazy_inits);
|
||||||
|
let r = self.generalize_t_inner(*r, bounds, lazy_inits);
|
||||||
|
// not `self.intersection` because types are generalized
|
||||||
|
and(l, r)
|
||||||
|
}
|
||||||
|
Or(l, r) => {
|
||||||
|
let l = self.generalize_t_inner(*l, bounds, lazy_inits);
|
||||||
|
let r = self.generalize_t_inner(*r, bounds, lazy_inits);
|
||||||
|
// not `self.union` because types are generalized
|
||||||
|
or(l, r)
|
||||||
|
}
|
||||||
|
Not(l, r) => {
|
||||||
|
let l = self.generalize_t_inner(*l, bounds, lazy_inits);
|
||||||
|
let r = self.generalize_t_inner(*r, bounds, lazy_inits);
|
||||||
|
not(l, r)
|
||||||
|
}
|
||||||
// REVIEW: その他何でもそのまま通していいのか?
|
// REVIEW: その他何でもそのまま通していいのか?
|
||||||
other => other,
|
other => other,
|
||||||
}
|
}
|
||||||
|
@ -312,6 +345,12 @@ impl Context {
|
||||||
let constraint = fv.crack_constraint();
|
let constraint = fv.crack_constraint();
|
||||||
let (sub_t, super_t) = constraint.get_sub_sup().unwrap();
|
let (sub_t, super_t) = constraint.get_sub_sup().unwrap();
|
||||||
if self.level <= fv.level().unwrap() {
|
if self.level <= fv.level().unwrap() {
|
||||||
|
/*if self.is_trait(sub_t) {
|
||||||
|
self.check_trait_exists(sub_t, loc)?;
|
||||||
|
}*/
|
||||||
|
if self.is_trait(super_t) {
|
||||||
|
self.check_trait_impl(sub_t, super_t, loc)?;
|
||||||
|
}
|
||||||
// REVIEW: Even if type constraints can be satisfied, implementation may not exist
|
// REVIEW: Even if type constraints can be satisfied, implementation may not exist
|
||||||
if self.subtype_of(sub_t, super_t) {
|
if self.subtype_of(sub_t, super_t) {
|
||||||
match variance {
|
match variance {
|
||||||
|
@ -472,6 +511,58 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn trait_impl_exists(&self, class: &Type, trait_: &Type) -> bool {
|
||||||
|
let mut super_exists = false;
|
||||||
|
for inst in self.get_trait_impls(trait_).into_iter() {
|
||||||
|
if self.supertype_of(&inst.sub_type, class)
|
||||||
|
&& self.supertype_of(&inst.sup_trait, trait_)
|
||||||
|
{
|
||||||
|
super_exists = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super_exists
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_trait_impl(
|
||||||
|
&self,
|
||||||
|
class: &Type,
|
||||||
|
trait_: &Type,
|
||||||
|
loc: Location,
|
||||||
|
) -> SingleTyCheckResult<()> {
|
||||||
|
if !self.trait_impl_exists(class, trait_) {
|
||||||
|
Err(TyCheckError::no_trait_impl_error(
|
||||||
|
self.cfg.input.clone(),
|
||||||
|
line!() as usize,
|
||||||
|
class,
|
||||||
|
trait_,
|
||||||
|
loc,
|
||||||
|
self.caused_by(),
|
||||||
|
None,
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fix type variables at their lower bound
|
||||||
|
pub(crate) fn coerce(&self, t: &Type) {
|
||||||
|
match t {
|
||||||
|
Type::FreeVar(fv) if fv.is_linked() => {
|
||||||
|
self.coerce(&fv.crack());
|
||||||
|
}
|
||||||
|
Type::FreeVar(fv) if fv.is_unbound() => {
|
||||||
|
let (sub, _sup) = fv.get_bound_types().unwrap();
|
||||||
|
fv.link(&sub);
|
||||||
|
}
|
||||||
|
Type::And(l, r) | Type::Or(l, r) | Type::Not(l, r) => {
|
||||||
|
self.coerce(l);
|
||||||
|
self.coerce(r);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Check if all types are resolvable (if traits, check if an implementation exists)
|
/// Check if all types are resolvable (if traits, check if an implementation exists)
|
||||||
/// And replace them if resolvable
|
/// And replace them if resolvable
|
||||||
pub(crate) fn resolve(
|
pub(crate) fn resolve(
|
||||||
|
@ -602,17 +693,23 @@ impl Context {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
hir::Expr::Def(def) => {
|
hir::Expr::Def(def) => {
|
||||||
|
// It is not possible to further dereference the quantified type.
|
||||||
|
// TODO: However, it is possible that there are external type variables within the quantified type.
|
||||||
|
if !def.sig.ref_t().is_quantified() {
|
||||||
match &mut def.sig {
|
match &mut def.sig {
|
||||||
hir::Signature::Var(var) => {
|
hir::Signature::Var(var) => {
|
||||||
var.t = self.deref_tyvar(mem::take(&mut var.t), Covariant, var.loc())?;
|
var.t =
|
||||||
|
self.deref_tyvar(mem::take(&mut var.t), Covariant, var.loc())?;
|
||||||
}
|
}
|
||||||
hir::Signature::Subr(subr) => {
|
hir::Signature::Subr(subr) => {
|
||||||
subr.t = self.deref_tyvar(mem::take(&mut subr.t), Covariant, subr.loc())?;
|
subr.t =
|
||||||
|
self.deref_tyvar(mem::take(&mut subr.t), Covariant, subr.loc())?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for chunk in def.body.block.iter_mut() {
|
for chunk in def.body.block.iter_mut() {
|
||||||
self.resolve_expr_t(chunk)?;
|
self.resolve_expr_t(chunk)?;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
hir::Expr::Lambda(lambda) => {
|
hir::Expr::Lambda(lambda) => {
|
||||||
|
@ -1158,29 +1255,15 @@ impl Context {
|
||||||
// * sub_unify(Str, ?T(:> Int, <: Obj)): (?T(:> Str or Int, <: Obj))
|
// * sub_unify(Str, ?T(:> Int, <: Obj)): (?T(:> Str or Int, <: Obj))
|
||||||
// * sub_unify({0}, ?T(:> {1}, <: Nat)): (?T(:> {0, 1}, <: Nat))
|
// * sub_unify({0}, ?T(:> {1}, <: Nat)): (?T(:> {0, 1}, <: Nat))
|
||||||
Constraint::Sandwiched { sub, sup, cyclicity } => {
|
Constraint::Sandwiched { sub, sup, cyclicity } => {
|
||||||
/*let judge = match cyclicity {
|
/*if let Some(new_sub) = self.max(maybe_sub, sub) {
|
||||||
Cyclicity::Super => self.cyclic_supertype_of(rfv, maybe_sub),
|
|
||||||
Cyclicity::Not => self.supertype_of(sup, maybe_sub),
|
|
||||||
_ => todo!(),
|
|
||||||
};
|
|
||||||
if !judge {
|
|
||||||
return Err(TyCheckErrors::from(TyCheckError::subtyping_error(
|
|
||||||
self.cfg.input.clone(),
|
|
||||||
line!() as usize,
|
|
||||||
maybe_sub,
|
|
||||||
sup, // TODO: this?
|
|
||||||
sub_loc,
|
|
||||||
sup_loc,
|
|
||||||
self.caused_by(),
|
|
||||||
)));
|
|
||||||
}*/
|
|
||||||
if let Some(new_sub) = self.max(maybe_sub, sub) {
|
|
||||||
*constraint =
|
*constraint =
|
||||||
Constraint::new_sandwiched(new_sub.clone(), mem::take(sup), *cyclicity);
|
Constraint::new_sandwiched(new_sub.clone(), mem::take(sup), *cyclicity);
|
||||||
} else {
|
} else {*/
|
||||||
|
erg_common::log!(err "{maybe_sub}, {sub}");
|
||||||
let new_sub = self.union(maybe_sub, sub);
|
let new_sub = self.union(maybe_sub, sub);
|
||||||
|
erg_common::log!(err "{new_sub}");
|
||||||
*constraint = Constraint::new_sandwiched(new_sub, mem::take(sup), *cyclicity);
|
*constraint = Constraint::new_sandwiched(new_sub, mem::take(sup), *cyclicity);
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
// sub_unify(Nat, ?T(: Type)): (/* ?T(:> Nat) */)
|
// sub_unify(Nat, ?T(: Type)): (/* ?T(:> Nat) */)
|
||||||
Constraint::TypeOf(ty) => {
|
Constraint::TypeOf(ty) => {
|
||||||
|
@ -1212,18 +1295,7 @@ impl Context {
|
||||||
// sup = union(sup, r) if min does not exist
|
// sup = union(sup, r) if min does not exist
|
||||||
// * sub_unify(?T(:> Never, <: {1}), {0}): (?T(:> Never, <: {0, 1}))
|
// * sub_unify(?T(:> Never, <: {1}), {0}): (?T(:> Never, <: {0, 1}))
|
||||||
Constraint::Sandwiched { sub, sup, cyclicity } => {
|
Constraint::Sandwiched { sub, sup, cyclicity } => {
|
||||||
// maybe_sup: Ref(Obj), sub: Never, sup: Show and Obj
|
// REVIEW: correct?
|
||||||
/*if !self.subtype_of(sub, maybe_sup) || !self.supertype_of(sup, maybe_sup) {
|
|
||||||
return Err(TyCheckErrors::from(TyCheckError::subtyping_error(
|
|
||||||
self.cfg.input.clone(),
|
|
||||||
line!() as usize,
|
|
||||||
sub,
|
|
||||||
maybe_sup,
|
|
||||||
sub_loc,
|
|
||||||
sup_loc,
|
|
||||||
self.caused_by(),
|
|
||||||
)));
|
|
||||||
}*/
|
|
||||||
if let Some(new_sup) = self.min(sup, maybe_sup) {
|
if let Some(new_sup) = self.min(sup, maybe_sup) {
|
||||||
*constraint =
|
*constraint =
|
||||||
Constraint::new_sandwiched(mem::take(sub), new_sup.clone(), *cyclicity);
|
Constraint::new_sandwiched(mem::take(sub), new_sup.clone(), *cyclicity);
|
||||||
|
@ -1331,6 +1403,20 @@ impl Context {
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
(Type::And(l, r), _)
|
||||||
|
| (Type::Or(l, r), _)
|
||||||
|
| (Type::Not(l, r), _) => {
|
||||||
|
self.sub_unify(l, maybe_sup, loc, param_name)?;
|
||||||
|
self.sub_unify(r, maybe_sup, loc, param_name)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
(_, Type::And(l, r))
|
||||||
|
| (_, Type::Or(l, r))
|
||||||
|
| (_, Type::Not(l, r)) => {
|
||||||
|
self.sub_unify(maybe_sub, l, loc, param_name)?;
|
||||||
|
self.sub_unify(maybe_sub, r, loc, param_name)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
(_, Type::Ref(t)) => {
|
(_, Type::Ref(t)) => {
|
||||||
self.sub_unify(maybe_sub, t, loc, param_name)?;
|
self.sub_unify(maybe_sub, t, loc, param_name)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -9,8 +9,10 @@ use erg_common::vis::Visibility;
|
||||||
use erg_common::Str;
|
use erg_common::Str;
|
||||||
use Visibility::*;
|
use Visibility::*;
|
||||||
|
|
||||||
|
use erg_type::HasType;
|
||||||
|
|
||||||
use crate::error::{EffectError, EffectErrors};
|
use crate::error::{EffectError, EffectErrors};
|
||||||
use crate::hir::{Accessor, Array, Def, Expr, Signature, Tuple, HIR};
|
use crate::hir::{Array, Def, Expr, Signature, Tuple, HIR};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
enum BlockKind {
|
enum BlockKind {
|
||||||
|
@ -208,8 +210,22 @@ impl SideEffectChecker {
|
||||||
self.block_stack.push(ConstInstant);
|
self.block_stack.push(ConstInstant);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for chunk in def.body.block.iter() {
|
let last_idx = def.body.block.len() - 1;
|
||||||
|
for (i, chunk) in def.body.block.iter().enumerate() {
|
||||||
self.check_expr(chunk);
|
self.check_expr(chunk);
|
||||||
|
// e.g. `echo = print!`
|
||||||
|
if i == last_idx
|
||||||
|
&& self.block_stack.last().unwrap() == &Instant
|
||||||
|
&& !def.sig.is_procedural()
|
||||||
|
&& chunk.t().is_procedural()
|
||||||
|
{
|
||||||
|
self.errs.push(EffectError::proc_assign_error(
|
||||||
|
self.cfg.input.clone(),
|
||||||
|
line!() as usize,
|
||||||
|
&def.sig,
|
||||||
|
self.full_path(),
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self.path_stack.pop();
|
self.path_stack.pop();
|
||||||
self.block_stack.pop();
|
self.block_stack.pop();
|
||||||
|
@ -290,7 +306,7 @@ impl SideEffectChecker {
|
||||||
},
|
},
|
||||||
// 引数がproceduralでも関数呼び出しなら副作用なし
|
// 引数がproceduralでも関数呼び出しなら副作用なし
|
||||||
Expr::Call(call) => {
|
Expr::Call(call) => {
|
||||||
if (self.is_procedural(&call.obj)
|
if (call.obj.t().is_procedural()
|
||||||
|| call
|
|| call
|
||||||
.method_name
|
.method_name
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
@ -340,19 +356,4 @@ impl SideEffectChecker {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_procedural(&self, expr: &Expr) -> bool {
|
|
||||||
match expr {
|
|
||||||
Expr::Lambda(lambda) => lambda.is_procedural(),
|
|
||||||
// 引数がproceduralでも関数呼び出しなら副作用なし
|
|
||||||
Expr::Call(call) => self.is_procedural(&call.obj),
|
|
||||||
Expr::Accessor(Accessor::Ident(ident)) => ident.name.is_procedural(),
|
|
||||||
// procedural: x.y! (e.g. Array.sample!)
|
|
||||||
// !procedural: !x.y
|
|
||||||
Expr::Accessor(Accessor::Attr(attr)) => attr.ident.is_procedural(),
|
|
||||||
Expr::Accessor(_) => todo!(),
|
|
||||||
Expr::TypeAsc(tasc) => self.is_procedural(&tasc.expr),
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ use erg_parser::error::{ParserRunnerError, ParserRunnerErrors};
|
||||||
|
|
||||||
use erg_type::{Predicate, Type};
|
use erg_type::{Predicate, Type};
|
||||||
|
|
||||||
use crate::hir::Expr;
|
use crate::hir::{Expr, Identifier, Signature};
|
||||||
|
|
||||||
/// dname is for "double under name"
|
/// dname is for "double under name"
|
||||||
pub fn binop_to_dname(op: &str) -> &str {
|
pub fn binop_to_dname(op: &str) -> &str {
|
||||||
|
@ -755,6 +755,33 @@ passed keyword args: {RED}{kw_args_len}{RESET}"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn no_trait_impl_error(
|
||||||
|
input: Input,
|
||||||
|
errno: usize,
|
||||||
|
class: &Type,
|
||||||
|
trait_: &Type,
|
||||||
|
loc: Location,
|
||||||
|
caused_by: AtomicStr,
|
||||||
|
hint: Option<AtomicStr>,
|
||||||
|
) -> Self {
|
||||||
|
Self::new(
|
||||||
|
ErrorCore::new(
|
||||||
|
errno,
|
||||||
|
TypeError,
|
||||||
|
loc,
|
||||||
|
switch_lang!(
|
||||||
|
"japanese" => format!("{class}は{trait_}を実装していません"),
|
||||||
|
"simplified_chinese" => format!("{class}没有实现{trait_}"),
|
||||||
|
"traditional_chinese" => format!("{class}沒有實現{trait_}"),
|
||||||
|
"english" => format!("{class} does not implement {trait_}"),
|
||||||
|
),
|
||||||
|
hint,
|
||||||
|
),
|
||||||
|
input,
|
||||||
|
caused_by,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn method_definition_error(
|
pub fn method_definition_error(
|
||||||
input: Input,
|
input: Input,
|
||||||
errno: usize,
|
errno: usize,
|
||||||
|
@ -992,6 +1019,38 @@ impl EffectError {
|
||||||
caused_by.into(),
|
caused_by.into(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn proc_assign_error<S: Into<AtomicStr>>(
|
||||||
|
input: Input,
|
||||||
|
errno: usize,
|
||||||
|
sig: &Signature,
|
||||||
|
caused_by: S,
|
||||||
|
) -> Self {
|
||||||
|
Self::new(
|
||||||
|
ErrorCore::new(
|
||||||
|
errno,
|
||||||
|
HasEffect,
|
||||||
|
sig.loc(),
|
||||||
|
switch_lang!(
|
||||||
|
"japanese" => "プロシージャを通常の変数に代入することはできません",
|
||||||
|
"simplified_chinese" => "不能将过程赋值给普通变量",
|
||||||
|
"traditional_chinese" => "不能將過程賦值給普通變量",
|
||||||
|
"english" => "cannot assign a procedure to a normal variable",
|
||||||
|
),
|
||||||
|
Some(
|
||||||
|
switch_lang!(
|
||||||
|
"japanese" => "変数の末尾に`!`をつけてください",
|
||||||
|
"simplified_chinese" => "请在变量名后加上`!`",
|
||||||
|
"traditional_chinese" => "請在變量名後加上`!`",
|
||||||
|
"english" => "add `!` to the end of the variable name",
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
input,
|
||||||
|
caused_by.into(),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type OwnershipError = TyCheckError;
|
pub type OwnershipError = TyCheckError;
|
||||||
|
@ -1305,6 +1364,26 @@ impl LowerError {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn del_error(input: Input, errno: usize, ident: &Identifier, caused_by: AtomicStr) -> Self {
|
||||||
|
let name = readable_name(ident.inspect());
|
||||||
|
Self::new(
|
||||||
|
ErrorCore::new(
|
||||||
|
errno,
|
||||||
|
NameError,
|
||||||
|
ident.loc(),
|
||||||
|
switch_lang!(
|
||||||
|
"japanese" => format!("{YELLOW}{name}{RESET}は削除できません"),
|
||||||
|
"simplified_chinese" => format!("{YELLOW}{name}{RESET}不能删除"),
|
||||||
|
"traditional_chinese" => format!("{YELLOW}{name}{RESET}不能刪除"),
|
||||||
|
"english" => format!("{YELLOW}{name}{RESET} cannot be deleted"),
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
input,
|
||||||
|
caused_by,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn visibility_error(
|
pub fn visibility_error(
|
||||||
input: Input,
|
input: Input,
|
||||||
errno: usize,
|
errno: usize,
|
||||||
|
|
|
@ -20,7 +20,7 @@ use erg_type::value::{TypeKind, ValueObj};
|
||||||
use erg_type::{impl_t, impl_t_for_enum, HasType, Type};
|
use erg_type::{impl_t, impl_t_for_enum, HasType, Type};
|
||||||
|
|
||||||
use crate::context::eval::type_from_token_kind;
|
use crate::context::eval::type_from_token_kind;
|
||||||
use crate::context::ImportKind;
|
use crate::context::OperationKind;
|
||||||
use crate::error::readable_name;
|
use crate::error::readable_name;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
@ -1085,10 +1085,11 @@ impl Call {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn import_kind(&self) -> Option<ImportKind> {
|
pub fn additional_operation(&self) -> Option<OperationKind> {
|
||||||
self.obj.show_acc().and_then(|s| match &s[..] {
|
self.obj.show_acc().and_then(|s| match &s[..] {
|
||||||
"import" => Some(ImportKind::ErgImport),
|
"import" => Some(OperationKind::Import),
|
||||||
"pyimport" | "py" => Some(ImportKind::PyImport),
|
"pyimport" | "py" => Some(OperationKind::PyImport),
|
||||||
|
"Del" => Some(OperationKind::Del),
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ use erg_type::typaram::TyParam;
|
||||||
use erg_type::value::ValueObj;
|
use erg_type::value::ValueObj;
|
||||||
use erg_type::{HasType, Type};
|
use erg_type::{HasType, Type};
|
||||||
|
|
||||||
use crate::context::ImportKind;
|
use crate::context::OperationKind;
|
||||||
use crate::hir::*;
|
use crate::hir::*;
|
||||||
use crate::mod_cache::SharedModuleCache;
|
use crate::mod_cache::SharedModuleCache;
|
||||||
|
|
||||||
|
@ -94,14 +94,14 @@ impl<'a> Linker<'a> {
|
||||||
Expr::UnaryOp(unaryop) => {
|
Expr::UnaryOp(unaryop) => {
|
||||||
self.replace_import(&mut unaryop.expr);
|
self.replace_import(&mut unaryop.expr);
|
||||||
}
|
}
|
||||||
Expr::Call(call) => match call.import_kind() {
|
Expr::Call(call) => match call.additional_operation() {
|
||||||
Some(ImportKind::ErgImport) => {
|
Some(OperationKind::Import) => {
|
||||||
self.replace_erg_import(expr);
|
self.replace_erg_import(expr);
|
||||||
}
|
}
|
||||||
Some(ImportKind::PyImport) => {
|
Some(OperationKind::PyImport) => {
|
||||||
self.replace_py_import(expr);
|
self.replace_py_import(expr);
|
||||||
}
|
}
|
||||||
None => {
|
_ => {
|
||||||
for arg in call.args.pos_args.iter_mut() {
|
for arg in call.args.pos_args.iter_mut() {
|
||||||
self.replace_import(&mut arg.expr);
|
self.replace_import(&mut arg.expr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
use erg_common::astr::AtomicStr;
|
use erg_common::astr::AtomicStr;
|
||||||
use erg_common::config::ErgConfig;
|
use erg_common::config::ErgConfig;
|
||||||
use erg_common::error::{Location, MultiErrorDisplay};
|
use erg_common::error::{Location, MultiErrorDisplay};
|
||||||
|
use erg_common::set;
|
||||||
use erg_common::set::Set;
|
use erg_common::set::Set;
|
||||||
use erg_common::traits::{Locational, Runnable, Stream};
|
use erg_common::traits::{Locational, Runnable, Stream};
|
||||||
use erg_common::vis::Visibility;
|
use erg_common::vis::Visibility;
|
||||||
|
@ -24,7 +25,9 @@ use erg_type::value::{GenTypeObj, TypeKind, TypeObj, ValueObj};
|
||||||
use erg_type::{HasType, ParamTy, Type};
|
use erg_type::{HasType, ParamTy, Type};
|
||||||
|
|
||||||
use crate::context::instantiate::TyVarContext;
|
use crate::context::instantiate::TyVarContext;
|
||||||
use crate::context::{ClassDefType, Context, ContextKind, RegistrationMode};
|
use crate::context::{
|
||||||
|
ClassDefType, Context, ContextKind, OperationKind, RegistrationMode, TraitInstance,
|
||||||
|
};
|
||||||
use crate::error::{
|
use crate::error::{
|
||||||
CompileError, CompileErrors, LowerError, LowerErrors, LowerResult, LowerWarning, LowerWarnings,
|
CompileError, CompileErrors, LowerError, LowerErrors, LowerResult, LowerWarning, LowerWarnings,
|
||||||
SingleLowerResult,
|
SingleLowerResult,
|
||||||
|
@ -252,7 +255,7 @@ impl ASTLowerer {
|
||||||
let maybe_len = self.ctx.eval_const_expr(len, None);
|
let maybe_len = self.ctx.eval_const_expr(len, None);
|
||||||
match maybe_len {
|
match maybe_len {
|
||||||
Ok(v @ ValueObj::Nat(_)) => {
|
Ok(v @ ValueObj::Nat(_)) => {
|
||||||
if elem.ref_t().is_mut() {
|
if elem.ref_t().is_mut_type() {
|
||||||
builtin_poly(
|
builtin_poly(
|
||||||
"ArrayWithMutType!",
|
"ArrayWithMutType!",
|
||||||
vec![TyParam::t(elem.t()), TyParam::Value(v)],
|
vec![TyParam::t(elem.t()), TyParam::Value(v)],
|
||||||
|
@ -262,7 +265,7 @@ impl ASTLowerer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(v @ ValueObj::Mut(_)) if v.class() == builtin_mono("Nat!") => {
|
Ok(v @ ValueObj::Mut(_)) if v.class() == builtin_mono("Nat!") => {
|
||||||
if elem.ref_t().is_mut() {
|
if elem.ref_t().is_mut_type() {
|
||||||
builtin_poly(
|
builtin_poly(
|
||||||
"ArrayWithMutTypeAndLength!",
|
"ArrayWithMutTypeAndLength!",
|
||||||
vec![TyParam::t(elem.t()), TyParam::Value(v)],
|
vec![TyParam::t(elem.t()), TyParam::Value(v)],
|
||||||
|
@ -274,7 +277,7 @@ impl ASTLowerer {
|
||||||
Ok(other) => todo!("{other} is not a Nat object"),
|
Ok(other) => todo!("{other} is not a Nat object"),
|
||||||
// REVIEW: is it ok to ignore the error?
|
// REVIEW: is it ok to ignore the error?
|
||||||
Err(_e) => {
|
Err(_e) => {
|
||||||
if elem.ref_t().is_mut() {
|
if elem.ref_t().is_mut_type() {
|
||||||
builtin_poly(
|
builtin_poly(
|
||||||
"ArrayWithMutType!",
|
"ArrayWithMutType!",
|
||||||
vec![TyParam::t(elem.t()), TyParam::erased(Type::Nat)],
|
vec![TyParam::t(elem.t()), TyParam::erased(Type::Nat)],
|
||||||
|
@ -508,7 +511,7 @@ impl ASTLowerer {
|
||||||
self.ctx
|
self.ctx
|
||||||
.rec_get_var_t(&ident, &self.cfg.input, &self.ctx.name)?,
|
.rec_get_var_t(&ident, &self.cfg.input, &self.ctx.name)?,
|
||||||
self.ctx
|
self.ctx
|
||||||
.get_singular_ctx_from_ident(&ident, &self.ctx.name)
|
.get_singular_ctx_by_ident(&ident, &self.ctx.name)
|
||||||
.ok()
|
.ok()
|
||||||
.map(|ctx| ctx.name.clone()),
|
.map(|ctx| ctx.name.clone()),
|
||||||
)
|
)
|
||||||
|
@ -581,12 +584,31 @@ impl ASTLowerer {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
let call = hir::Call::new(obj, method_name, hir_args, sig_t);
|
let call = hir::Call::new(obj, method_name, hir_args, sig_t);
|
||||||
if let Some(kind) = call.import_kind() {
|
match call.additional_operation() {
|
||||||
let mod_name = enum_unwrap!(call.args.get_left_or_key("Path").unwrap(), hir::Expr::Lit);
|
Some(kind @ (OperationKind::Import | OperationKind::PyImport)) => {
|
||||||
|
let mod_name =
|
||||||
|
enum_unwrap!(call.args.get_left_or_key("Path").unwrap(), hir::Expr::Lit);
|
||||||
if let Err(errs) = self.ctx.import_mod(kind, mod_name) {
|
if let Err(errs) = self.ctx.import_mod(kind, mod_name) {
|
||||||
self.errs.extend(errs.into_iter());
|
self.errs.extend(errs.into_iter());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Some(OperationKind::Del) => match call.args.get_left_or_key("obj").unwrap() {
|
||||||
|
hir::Expr::Accessor(hir::Accessor::Ident(ident)) => {
|
||||||
|
self.ctx.del(ident)?;
|
||||||
|
}
|
||||||
|
other => {
|
||||||
|
return Err(LowerErrors::from(LowerError::syntax_error(
|
||||||
|
self.input().clone(),
|
||||||
|
line!() as usize,
|
||||||
|
other.loc(),
|
||||||
|
self.ctx.caused_by(),
|
||||||
|
"",
|
||||||
|
None,
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
Ok(call)
|
Ok(call)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -824,13 +846,14 @@ impl ASTLowerer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let id = body.id;
|
let id = body.id;
|
||||||
self.ctx
|
let t = self
|
||||||
|
.ctx
|
||||||
.outer
|
.outer
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.assign_subr(&sig, id, found_body_t)?;
|
.assign_subr(&sig, id, found_body_t)?;
|
||||||
let ident = hir::Identifier::bare(sig.ident.dot, sig.ident.name);
|
let ident = hir::Identifier::bare(sig.ident.dot, sig.ident.name);
|
||||||
let sig = hir::SubrSignature::new(ident, sig.params, Type::Subr(t));
|
let sig = hir::SubrSignature::new(ident, sig.params, t);
|
||||||
let body = hir::DefBody::new(body.op, block, body.id);
|
let body = hir::DefBody::new(body.op, block, body.id);
|
||||||
Ok(hir::Def::new(hir::Signature::Subr(sig), body))
|
Ok(hir::Def::new(hir::Signature::Subr(sig), body))
|
||||||
}
|
}
|
||||||
|
@ -939,6 +962,9 @@ impl ASTLowerer {
|
||||||
match self.ctx.check_decls_and_pop() {
|
match self.ctx.check_decls_and_pop() {
|
||||||
Ok(methods) => {
|
Ok(methods) => {
|
||||||
self.check_override(&class, &methods);
|
self.check_override(&class, &methods);
|
||||||
|
if let Some((trait_, _)) = &impl_trait {
|
||||||
|
self.register_trait_impl(&class, trait_);
|
||||||
|
}
|
||||||
self.check_trait_impl(impl_trait, &class, &methods)?;
|
self.check_trait_impl(impl_trait, &class, &methods)?;
|
||||||
self.push_methods(class, methods);
|
self.push_methods(class, methods);
|
||||||
}
|
}
|
||||||
|
@ -1033,6 +1059,8 @@ impl ASTLowerer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Inspect the Trait implementation for correctness,
|
||||||
|
/// i.e., check that all required attributes are defined and that no extra attributes are defined
|
||||||
fn check_trait_impl(
|
fn check_trait_impl(
|
||||||
&mut self,
|
&mut self,
|
||||||
impl_trait: Option<(Type, Location)>,
|
impl_trait: Option<(Type, Location)>,
|
||||||
|
@ -1127,6 +1155,18 @@ impl ASTLowerer {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn register_trait_impl(&mut self, class: &Type, trait_: &Type) {
|
||||||
|
// TODO: polymorphic trait
|
||||||
|
if let Some(impls) = self.ctx.trait_impls.get_mut(&trait_.name()) {
|
||||||
|
impls.insert(TraitInstance::new(class.clone(), trait_.clone()));
|
||||||
|
} else {
|
||||||
|
self.ctx.trait_impls.insert(
|
||||||
|
trait_.name(),
|
||||||
|
set! {TraitInstance::new(class.clone(), trait_.clone())},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn push_methods(&mut self, class: Type, methods: Context) {
|
fn push_methods(&mut self, class: Type, methods: Context) {
|
||||||
let (_, class_root) = self.ctx.get_mut_nominal_type_ctx(&class).unwrap();
|
let (_, class_root) = self.ctx.get_mut_nominal_type_ctx(&class).unwrap();
|
||||||
for (newly_defined_name, _vi) in methods.locals.iter() {
|
for (newly_defined_name, _vi) in methods.locals.iter() {
|
||||||
|
|
|
@ -212,7 +212,7 @@ impl OwnershipChecker {
|
||||||
self.errs.push(e);
|
self.errs.push(e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if acc.ref_t().is_mut() && ownership.is_owned() && !chunk {
|
if acc.ref_t().is_mut_type() && ownership.is_owned() && !chunk {
|
||||||
self.drop(ident);
|
self.drop(ident);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "erg_parser"
|
name = "erg_parser"
|
||||||
version = "0.5.6"
|
version = "0.5.7-nightly.1"
|
||||||
description = "The Erg parser"
|
description = "The Erg parser"
|
||||||
authors = ["erg-lang team <moderation.erglang@gmail.com>"]
|
authors = ["erg-lang team <moderation.erglang@gmail.com>"]
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
|
@ -16,7 +16,7 @@ simplified_chinese = [ "erg_common/simplified_chinese" ]
|
||||||
traditional_chinese = [ "erg_common/traditional_chinese" ]
|
traditional_chinese = [ "erg_common/traditional_chinese" ]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
erg_common = { version = "0.5.6", path = "../erg_common" }
|
erg_common = { version = "0.5.7-nightly.1", path = "../erg_common" }
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
path = "lib.rs"
|
path = "lib.rs"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "erg_type"
|
name = "erg_type"
|
||||||
version = "0.5.6"
|
version = "0.5.7-nightly.1"
|
||||||
description = "APIs for Erg types"
|
description = "APIs for Erg types"
|
||||||
authors = ["erg-lang team <moderation.erglang@gmail.com>"]
|
authors = ["erg-lang team <moderation.erglang@gmail.com>"]
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
|
@ -18,8 +18,8 @@ simplified_chinese = [ "erg_common/simplified_chinese" ]
|
||||||
traditional_chinese = [ "erg_common/traditional_chinese" ]
|
traditional_chinese = [ "erg_common/traditional_chinese" ]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
erg_common = { version = "0.5.6", path = "../erg_common" }
|
erg_common = { version = "0.5.7-nightly.1", path = "../erg_common" }
|
||||||
erg_parser = { version = "0.5.6", path = "../erg_parser" }
|
erg_parser = { version = "0.5.7-nightly.1", path = "../erg_parser" }
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
path = "lib.rs"
|
path = "lib.rs"
|
||||||
|
|
|
@ -3,10 +3,15 @@ use std::convert::TryInto;
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn param_t(name: &'static str, ty: Type) -> ParamTy {
|
pub const fn kw(name: &'static str, ty: Type) -> ParamTy {
|
||||||
ParamTy::kw(Str::ever(name), ty)
|
ParamTy::kw(Str::ever(name), ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub const fn kw_default(name: &'static str, ty: Type, default: Type) -> ParamTy {
|
||||||
|
ParamTy::kw_default(Str::ever(name), ty, default)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn anon(ty: Type) -> ParamTy {
|
pub const fn anon(ty: Type) -> ParamTy {
|
||||||
ParamTy::anonymous(ty)
|
ParamTy::anonymous(ty)
|
||||||
|
|
|
@ -436,6 +436,16 @@ impl<T: Clone + HasLevel> Free<T> {
|
||||||
*self.borrow_mut() = FreeKind::Linked(to.clone());
|
*self.borrow_mut() = FreeKind::Linked(to.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn forced_link(&self, to: &T) {
|
||||||
|
// prevent linking to self
|
||||||
|
if self.is_linked() && addr_eq!(*self.crack(), *to) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
*self.as_ptr() = FreeKind::Linked(to.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn undoable_link(&self, to: &T) {
|
pub fn undoable_link(&self, to: &T) {
|
||||||
if self.is_linked() && addr_eq!(*self.crack(), *to) {
|
if self.is_linked() && addr_eq!(*self.crack(), *to) {
|
||||||
panic!("link to self");
|
panic!("link to self");
|
||||||
|
|
|
@ -724,6 +724,7 @@ impl Predicate {
|
||||||
pub enum ParamTy {
|
pub enum ParamTy {
|
||||||
Pos { name: Option<Str>, ty: Type },
|
Pos { name: Option<Str>, ty: Type },
|
||||||
Kw { name: Str, ty: Type },
|
Kw { name: Str, ty: Type },
|
||||||
|
KwWithDefault { name: Str, ty: Type, default: Type },
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for ParamTy {
|
impl fmt::Display for ParamTy {
|
||||||
|
@ -736,6 +737,9 @@ impl fmt::Display for ParamTy {
|
||||||
write!(f, ": {}", ty)
|
write!(f, ": {}", ty)
|
||||||
}
|
}
|
||||||
Self::Kw { name, ty } => write!(f, "{}: {}", name, ty),
|
Self::Kw { name, ty } => write!(f, "{}: {}", name, ty),
|
||||||
|
Self::KwWithDefault { name, ty, default } => {
|
||||||
|
write!(f, "{}: {} := {}", name, ty, default)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -749,6 +753,10 @@ impl ParamTy {
|
||||||
Self::Kw { name, ty }
|
Self::Kw { name, ty }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const fn kw_default(name: Str, ty: Type, default: Type) -> Self {
|
||||||
|
Self::KwWithDefault { name, ty, default }
|
||||||
|
}
|
||||||
|
|
||||||
pub const fn anonymous(ty: Type) -> Self {
|
pub const fn anonymous(ty: Type) -> Self {
|
||||||
Self::pos(None, ty)
|
Self::pos(None, ty)
|
||||||
}
|
}
|
||||||
|
@ -756,26 +764,27 @@ impl ParamTy {
|
||||||
pub fn name(&self) -> Option<&Str> {
|
pub fn name(&self) -> Option<&Str> {
|
||||||
match self {
|
match self {
|
||||||
Self::Pos { name, .. } => name.as_ref(),
|
Self::Pos { name, .. } => name.as_ref(),
|
||||||
Self::Kw { name, .. } => Some(name),
|
Self::Kw { name, .. } | Self::KwWithDefault { name, .. } => Some(name),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn typ(&self) -> &Type {
|
pub const fn typ(&self) -> &Type {
|
||||||
match self {
|
match self {
|
||||||
Self::Pos { ty, .. } | Self::Kw { ty, .. } => ty,
|
Self::Pos { ty, .. } | Self::Kw { ty, .. } | Self::KwWithDefault { ty, .. } => ty,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn typ_mut(&mut self) -> &mut Type {
|
pub fn typ_mut(&mut self) -> &mut Type {
|
||||||
match self {
|
match self {
|
||||||
Self::Pos { ty, .. } | Self::Kw { ty, .. } => ty,
|
Self::Pos { ty, .. } | Self::Kw { ty, .. } | Self::KwWithDefault { ty, .. } => ty,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deconstruct(self) -> (Option<Str>, Type) {
|
pub fn deconstruct(self) -> (Option<Str>, Type, Option<Type>) {
|
||||||
match self {
|
match self {
|
||||||
Self::Pos { name, ty } => (name, ty),
|
Self::Pos { name, ty } => (name, ty, None),
|
||||||
Self::Kw { name, ty } => (Some(name), ty),
|
Self::Kw { name, ty } => (Some(name), ty, None),
|
||||||
|
Self::KwWithDefault { name, ty, default } => (Some(name), ty, Some(default)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -931,11 +940,12 @@ impl LimitedDisplay for RefinementType {
|
||||||
return write!(f, "...");
|
return write!(f, "...");
|
||||||
}
|
}
|
||||||
let first_subj = self.preds.iter().next().and_then(|p| p.subject());
|
let first_subj = self.preds.iter().next().and_then(|p| p.subject());
|
||||||
if self
|
let is_simple_type = self.t.is_simple_class();
|
||||||
|
let is_simple_preds = self
|
||||||
.preds
|
.preds
|
||||||
.iter()
|
.iter()
|
||||||
.all(|p| p.is_equal() && p.subject() == first_subj)
|
.all(|p| p.is_equal() && p.subject() == first_subj);
|
||||||
{
|
if is_simple_type && is_simple_preds {
|
||||||
write!(f, "{{")?;
|
write!(f, "{{")?;
|
||||||
for pred in self.preds.iter() {
|
for pred in self.preds.iter() {
|
||||||
let (_, rhs) = enum_unwrap!(pred, Predicate::Equal { lhs, rhs });
|
let (_, rhs) = enum_unwrap!(pred, Predicate::Equal { lhs, rhs });
|
||||||
|
@ -1684,11 +1694,25 @@ impl Type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_mut(&self) -> bool {
|
/// Procedure or MutType?
|
||||||
|
pub fn is_procedural(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_procedural(),
|
||||||
|
Self::Callable { .. } => true,
|
||||||
|
Self::Subr(subr) if subr.kind == SubrKind::Proc => true,
|
||||||
|
Self::Refinement(refine) =>
|
||||||
|
refine.t.is_procedural() || refine.preds.iter().any(|pred|
|
||||||
|
matches!(pred, Predicate::Equal{ rhs, .. } if pred.mentions(&refine.var) && rhs.name().map(|n| n.ends_with('!')).unwrap_or(false))
|
||||||
|
),
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_mut_type(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Self::FreeVar(fv) => {
|
Self::FreeVar(fv) => {
|
||||||
if fv.is_linked() {
|
if fv.is_linked() {
|
||||||
fv.crack().is_mut()
|
fv.crack().is_mut_type()
|
||||||
} else {
|
} else {
|
||||||
fv.unbound_name().unwrap().ends_with('!')
|
fv.unbound_name().unwrap().ends_with('!')
|
||||||
}
|
}
|
||||||
|
@ -1700,7 +1724,7 @@ impl Type {
|
||||||
| Self::BuiltinPoly { name, .. }
|
| Self::BuiltinPoly { name, .. }
|
||||||
| Self::PolyQVar { name, .. }
|
| Self::PolyQVar { name, .. }
|
||||||
| Self::MonoProj { rhs: name, .. } => name.ends_with('!'),
|
| Self::MonoProj { rhs: name, .. } => name.ends_with('!'),
|
||||||
Self::Refinement(refine) => refine.t.is_mut(),
|
Self::Refinement(refine) => refine.t.is_mut_type(),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1730,6 +1754,14 @@ impl Type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_quantified(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_quantified(),
|
||||||
|
Self::Quantified(_) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn contains_tvar(&self, name: &str) -> bool {
|
pub fn contains_tvar(&self, name: &str) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Self::FreeVar(fv) if fv.is_linked() => fv.crack().contains_tvar(name),
|
Self::FreeVar(fv) if fv.is_linked() => fv.crack().contains_tvar(name),
|
||||||
|
|
|
@ -9,6 +9,9 @@
|
||||||
|
|
||||||
* [pre-commit](https://pre-commit.com/)
|
* [pre-commit](https://pre-commit.com/)
|
||||||
|
|
||||||
|
We use pre-commit to have clippy check and test automatically.
|
||||||
|
The checks may fail on the first run even if there are no bugs, in which case you should try committing again.
|
||||||
|
|
||||||
* Python3 interpreter
|
* Python3 interpreter
|
||||||
|
|
||||||
## Recommendation
|
## Recommendation
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# 開発環境
|
# 開発環境
|
||||||
|
|
||||||
[](https://gezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com/default/source_up_to_date?owner=erg-lang&repos=erg&ref=main&path=doc/EN/dev_guide/env.md&commit_hash=61d72afbbfdba8c2ca994499c7ec9f8fc01440cb)
|
[](https://gezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com/default/source_up_to_date?owner=erg-lang&repos=erg&ref=main&path=doc/EN/dev_guide/env.md&commit_hash=735c840e681ad106795654212680696a2be29eee)
|
||||||
|
|
||||||
## インストールが必要なもの
|
## インストールが必要なもの
|
||||||
|
|
||||||
|
@ -11,6 +11,9 @@
|
||||||
|
|
||||||
* [pre-commit](https://pre-commit.com/)
|
* [pre-commit](https://pre-commit.com/)
|
||||||
|
|
||||||
|
pre-commitを使ってclippyのチェックやテストを自動で行わせています。
|
||||||
|
バグがなくても最初の実行でチェックが失敗する場合があります。その場合はもう一度コミットを試みてください。
|
||||||
|
|
||||||
* Python3インタープリタ
|
* Python3インタープリタ
|
||||||
|
|
||||||
## 推奨
|
## 推奨
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
Dictはキーと値のペアを持つコレクションです。
|
Dictはキーと値のペアを持つコレクションです。
|
||||||
|
|
||||||
```python
|
```python
|
||||||
ids = {"Alice": 145, "Bob": 214, "Charlie": 301}
|
ids = {"Alice" >: 145, "Bob": 214, "Charlie": 301}
|
||||||
assert ids["Alice"] == 145
|
assert ids["Alice"] == 145
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -28,3 +28,12 @@ assert fold(g, [1, 2, 3]) == 8
|
||||||
|
|
||||||
1番目は、デフォルト引数のある関数は、ない関数と同一視できる、という意味である。
|
1番目は、デフォルト引数のある関数は、ない関数と同一視できる、という意味である。
|
||||||
2番目は、任意のデフォルト引数は省略できる、という意味である。
|
2番目は、任意のデフォルト引数は省略できる、という意味である。
|
||||||
|
|
||||||
|
デフォルト引数の型は、引数を渡した場合と渡さなかった場合で変えることができる。
|
||||||
|
具体的には、`if`関数の型などが良い例である。
|
||||||
|
|
||||||
|
```python
|
||||||
|
if: |T: Type, U: Type|(then: () -> T, else: () -> U := () -> NoneType) -> T or U
|
||||||
|
```
|
||||||
|
|
||||||
|
`if`関数は、`else`引数が与えられなければ`T or NoneType`を返す。
|
||||||
|
|
|
@ -7,3 +7,8 @@ if True, do:
|
||||||
|
|
||||||
f x: Int = log x
|
f x: Int = log x
|
||||||
g x: Int = print! x # this should cause an effect error
|
g x: Int = print! x # this should cause an effect error
|
||||||
|
|
||||||
|
echo = print! # this should be an effect error
|
||||||
|
_echo = # this is OK
|
||||||
|
print! 1
|
||||||
|
log
|
||||||
|
|
82
library/std/_prelude.er
Normal file
82
library/std/_prelude.er
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
@Attach NeImpl
|
||||||
|
Eq(R := Self) = Trait {
|
||||||
|
.`==` = (self: Self, R) -> Bool
|
||||||
|
}
|
||||||
|
|
||||||
|
NeImpl R = Patch Eq R
|
||||||
|
NeImpl(R).
|
||||||
|
`!=`(self, other: R): Bool = not(self == other)
|
||||||
|
|
||||||
|
@Attach EqImpl, LeImpl, LtImpl, GeImpl, GtImpl
|
||||||
|
PartialOrd(R := Self) = Trait {
|
||||||
|
.cmp = (self: Self, R) -> Option Ordering
|
||||||
|
}
|
||||||
|
Ord = Subsume PartialOrd()
|
||||||
|
|
||||||
|
EqForOrd R = Patch Ord, Impl := Eq()
|
||||||
|
EqForOrd(R).
|
||||||
|
`==`(self, other: R): Bool = self.cmp(other) == Ordering.Equal
|
||||||
|
|
||||||
|
LeForOrd = Patch Ord
|
||||||
|
LeForOrd.
|
||||||
|
`<=`(self, other: Self): Bool = self.cmp(other) == Ordering.Less or self == other
|
||||||
|
LtForOrd = Patch Ord
|
||||||
|
LtForOrd.
|
||||||
|
`<`(self, other: Self): Bool = self.cmp(other) == Ordering.Less
|
||||||
|
GeForOrd = Patch Ord
|
||||||
|
GeForOrd.
|
||||||
|
`>=`(self, other: Self): Bool = self.cmp(other) == Ordering.Greater or self == other
|
||||||
|
GtForOrd = Patch Ord
|
||||||
|
GtForOrd.
|
||||||
|
`>`(self, other: Self): Bool = self.cmp(other) == Ordering.Greater
|
||||||
|
|
||||||
|
Add(R := Self) = Trait {
|
||||||
|
.Output = Type
|
||||||
|
.`_+_` = (self: Self, R) -> Self.Output
|
||||||
|
}
|
||||||
|
Sub(R := Self) = Trait {
|
||||||
|
.Output = Type
|
||||||
|
.`_-_` = (self: Self, R) -> Self.Output
|
||||||
|
}
|
||||||
|
Mul(R := Self()) = Trait {
|
||||||
|
.Output = Type
|
||||||
|
.`*` = (self: Self, R) -> Self.Output
|
||||||
|
}
|
||||||
|
Div(R := Self) = Trait {
|
||||||
|
.Output = Type
|
||||||
|
.`/` = (self: Self, R) -> Self.Output or Panic
|
||||||
|
}
|
||||||
|
Num: (R := Type) -> Type
|
||||||
|
Num = Add and Sub and Mul
|
||||||
|
|
||||||
|
Seq T = Trait {
|
||||||
|
.__len__ = (self: Ref(Self)) -> Nat
|
||||||
|
.get = (self: Ref(Self), Nat) -> T
|
||||||
|
}
|
||||||
|
|
||||||
|
`_+_`: |R: Type, A <: Add(R)| (A, R) -> A.AddO
|
||||||
|
`_-_`: |R: Type, S <: Add(R)| (S, R) -> S.SubO
|
||||||
|
`*`: |R, O: Type, M <: Add(R)| (M, R) -> M.MulO
|
||||||
|
`/`: |R, O: Type, D <: Add(R)| (D, R) -> D.DivO
|
||||||
|
|
||||||
|
AddForInt = Patch Int, Impl := Add()
|
||||||
|
AddForInt.AddO = Int
|
||||||
|
AddForInt.
|
||||||
|
`_+_`: (self: Self, other: Int) -> Int = magic("Add.`_+_`")
|
||||||
|
|
||||||
|
# TODO: Mul and Div
|
||||||
|
NumForInterval M, N, O, P: Int =
|
||||||
|
Patch M..N, Impl := Add(R := O..P) and Sub(R := O..P)
|
||||||
|
NumForInterval(M, N, O, P).
|
||||||
|
`_+_`: (self: Self, other: O..P) -> M+O..N+P = magic("NumForInterval.`_+_`")
|
||||||
|
`_-_`: (self: Self, other: O..P) -> M-P..N-O = magic("NumForInterval.`_-_`")
|
||||||
|
|
||||||
|
Read = Trait {
|
||||||
|
.read = (self: Ref(Self)) -> Str
|
||||||
|
}
|
||||||
|
Read! = Trait {
|
||||||
|
.read! = (self: Ref!(Self)) => Str
|
||||||
|
}
|
||||||
|
Write! = Trait {
|
||||||
|
.write! = (self: Ref!(Self), Str) => ()
|
||||||
|
}
|
|
@ -1,82 +1,12 @@
|
||||||
@Attach NeImpl
|
discard _x = None
|
||||||
Eq(R := Self) = Trait {
|
|
||||||
.`==` = (self: Self, R) -> Bool
|
|
||||||
}
|
|
||||||
|
|
||||||
NeImpl R = Patch Eq R
|
discard 1
|
||||||
NeImpl(R).
|
|
||||||
`!=`(self, other: R): Bool = not(self == other)
|
|
||||||
|
|
||||||
@Attach EqImpl, LeImpl, LtImpl, GeImpl, GtImpl
|
cond c, then, else =
|
||||||
PartialOrd(R := Self) = Trait {
|
if c:
|
||||||
.cmp = (self: Self, R) -> Option Ordering
|
do then
|
||||||
}
|
do else
|
||||||
Ord = Subsume PartialOrd()
|
|
||||||
|
|
||||||
EqForOrd R = Patch Ord, Impl := Eq()
|
assert cond(False, 1, 2) == 2
|
||||||
EqForOrd(R).
|
# assert cond(True, 1, 3) == "a"
|
||||||
`==`(self, other: R): Bool = self.cmp(other) == Ordering.Equal
|
# assert "a" == cond(True, 1, 3)
|
||||||
|
|
||||||
LeForOrd = Patch Ord
|
|
||||||
LeForOrd.
|
|
||||||
`<=`(self, other: Self): Bool = self.cmp(other) == Ordering.Less or self == other
|
|
||||||
LtForOrd = Patch Ord
|
|
||||||
LtForOrd.
|
|
||||||
`<`(self, other: Self): Bool = self.cmp(other) == Ordering.Less
|
|
||||||
GeForOrd = Patch Ord
|
|
||||||
GeForOrd.
|
|
||||||
`>=`(self, other: Self): Bool = self.cmp(other) == Ordering.Greater or self == other
|
|
||||||
GtForOrd = Patch Ord
|
|
||||||
GtForOrd.
|
|
||||||
`>`(self, other: Self): Bool = self.cmp(other) == Ordering.Greater
|
|
||||||
|
|
||||||
Add(R := Self) = Trait {
|
|
||||||
.Output = Type
|
|
||||||
.`_+_` = (self: Self, R) -> Self.Output
|
|
||||||
}
|
|
||||||
Sub(R := Self) = Trait {
|
|
||||||
.Output = Type
|
|
||||||
.`_-_` = (self: Self, R) -> Self.Output
|
|
||||||
}
|
|
||||||
Mul(R := Self()) = Trait {
|
|
||||||
.Output = Type
|
|
||||||
.`*` = (self: Self, R) -> Self.Output
|
|
||||||
}
|
|
||||||
Div(R := Self) = Trait {
|
|
||||||
.Output = Type
|
|
||||||
.`/` = (self: Self, R) -> Self.Output or Panic
|
|
||||||
}
|
|
||||||
Num: (R := Type) -> Type
|
|
||||||
Num = Add and Sub and Mul
|
|
||||||
|
|
||||||
Seq T = Trait {
|
|
||||||
.__len__ = (self: Ref(Self)) -> Nat
|
|
||||||
.get = (self: Ref(Self), Nat) -> T
|
|
||||||
}
|
|
||||||
|
|
||||||
`_+_`: |R: Type, A <: Add(R)| (A, R) -> A.AddO
|
|
||||||
`_-_`: |R: Type, S <: Add(R)| (S, R) -> S.SubO
|
|
||||||
`*`: |R, O: Type, M <: Add(R)| (M, R) -> M.MulO
|
|
||||||
`/`: |R, O: Type, D <: Add(R)| (D, R) -> D.DivO
|
|
||||||
|
|
||||||
AddForInt = Patch Int, Impl := Add()
|
|
||||||
AddForInt.AddO = Int
|
|
||||||
AddForInt.
|
|
||||||
`_+_`: (self: Self, other: Int) -> Int = magic("Add.`_+_`")
|
|
||||||
|
|
||||||
# TODO: Mul and Div
|
|
||||||
NumForInterval M, N, O, P: Int =
|
|
||||||
Patch M..N, Impl := Add(R := O..P) and Sub(R := O..P)
|
|
||||||
NumForInterval(M, N, O, P).
|
|
||||||
`_+_`: (self: Self, other: O..P) -> M+O..N+P = magic("NumForInterval.`_+_`")
|
|
||||||
`_-_`: (self: Self, other: O..P) -> M-P..N-O = magic("NumForInterval.`_-_`")
|
|
||||||
|
|
||||||
Read = Trait {
|
|
||||||
.read = (self: Ref(Self)) -> Str
|
|
||||||
}
|
|
||||||
Read! = Trait {
|
|
||||||
.read! = (self: Ref!(Self)) => Str
|
|
||||||
}
|
|
||||||
Write! = Trait {
|
|
||||||
.write! = (self: Ref!(Self), Str) => ()
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
add x, y =
|
|
||||||
x + y
|
|
||||||
|
|
||||||
print! 1 + 1
|
|
||||||
print! 1.0 + 1
|
|
7
tests/addition.er
Normal file
7
tests/addition.er
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
add x, y =
|
||||||
|
x + y
|
||||||
|
|
||||||
|
print! add(1, 1)
|
||||||
|
print! add(1.0, 1)
|
||||||
|
print! add("a", "b")
|
||||||
|
print! add("a", 1) # this will be an error
|
|
@ -1,6 +1,6 @@
|
||||||
for! 1..100, i =>
|
for! 1..<100, i =>
|
||||||
match (i % 3, i % 5):
|
match (i % 3, i % 5):
|
||||||
0, 0 => print! "FizzBuzz"
|
(0, 0) => print! "FizzBuzz"
|
||||||
0, _ => print! "Fizz"
|
(0, _) => print! "Fizz"
|
||||||
_, 0 => print! "Buzz"
|
(_, 0) => print! "Buzz"
|
||||||
_ => print! i
|
(_, _) => print! i
|
||||||
|
|
14
tests/infer_class.er
Normal file
14
tests/infer_class.er
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
_abs x =
|
||||||
|
x.abs() # currently this method only implemented for integers
|
||||||
|
|
||||||
|
assert _abs(-1) == 1
|
||||||
|
|
||||||
|
#[
|
||||||
|
push! a, elem =
|
||||||
|
a.push!(elem)
|
||||||
|
a
|
||||||
|
|
||||||
|
a = ![]
|
||||||
|
b = push! a, 1
|
||||||
|
print! b
|
||||||
|
]#
|
6
tests/infer_trait.er
Normal file
6
tests/infer_trait.er
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
show s =
|
||||||
|
s.to_str()
|
||||||
|
|
||||||
|
assert show(1) == "1"
|
||||||
|
assert show(True) == "True"
|
||||||
|
# discard show((x,) -> x)
|
|
@ -1,5 +1,5 @@
|
||||||
v = ![]
|
v = ![]
|
||||||
for! 0..10, i =>
|
for! 0..<10, i =>
|
||||||
v.push! i
|
v.push! i
|
||||||
|
|
||||||
log v.sum()
|
log v.sum()
|
||||||
|
|
10
tests/rec.er
Normal file
10
tests/rec.er
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
stop_or_call n, f: (Nat -> Nat), g: (Nat -> Nat) =
|
||||||
|
cond n <= 0:
|
||||||
|
1
|
||||||
|
g (f (n - 1))
|
||||||
|
|
||||||
|
fact(n: Nat): Nat =
|
||||||
|
stop_or_call n, fact, (r, ) -> r * n
|
||||||
|
|
||||||
|
print! fact
|
||||||
|
print! fact 5
|
6
tests/subtyping.er
Normal file
6
tests/subtyping.er
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
f(x: Nat): Int = x
|
||||||
|
y: Ratio = f 1
|
||||||
|
# Erg's type checking does not necessarily enlarge the type. So this is OK.
|
||||||
|
z: Int = y
|
||||||
|
# But this is invalid.
|
||||||
|
invalid: 10..<20 = z
|
|
@ -6,6 +6,11 @@ use erg_common::traits::Runnable;
|
||||||
|
|
||||||
use erg::dummy::DummyVM;
|
use erg::dummy::DummyVM;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn exec_addition() -> Result<(), ()> {
|
||||||
|
expect_failure("tests/addition.er")
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn exec_class() -> Result<(), ()> {
|
fn exec_class() -> Result<(), ()> {
|
||||||
expect_success("examples/class.er")
|
expect_success("examples/class.er")
|
||||||
|
@ -31,6 +36,16 @@ fn exec_import() -> Result<(), ()> {
|
||||||
expect_success("examples/import.er")
|
expect_success("examples/import.er")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn exec_infer_class() -> Result<(), ()> {
|
||||||
|
expect_success("tests/infer_class.er")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn exec_infer_trait() -> Result<(), ()> {
|
||||||
|
expect_success("tests/infer_trait.er")
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn exec_move_check() -> Result<(), ()> {
|
fn exec_move_check() -> Result<(), ()> {
|
||||||
expect_failure("examples/move_check.er")
|
expect_failure("examples/move_check.er")
|
||||||
|
@ -41,6 +56,12 @@ fn exec_quantified() -> Result<(), ()> {
|
||||||
expect_success("examples/quantified.er")
|
expect_success("examples/quantified.er")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn exec_rec() -> Result<(), ()> {
|
||||||
|
// this script is valid but the current code generating process has a bug.
|
||||||
|
expect_end_with("tests/rec.er", 1)
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn exec_record() -> Result<(), ()> {
|
fn exec_record() -> Result<(), ()> {
|
||||||
expect_success("examples/record.er")
|
expect_success("examples/record.er")
|
||||||
|
@ -51,6 +72,11 @@ fn exec_side_effect() -> Result<(), ()> {
|
||||||
expect_failure("examples/side_effect.er")
|
expect_failure("examples/side_effect.er")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn exec_subtyping() -> Result<(), ()> {
|
||||||
|
expect_failure("tests/subtyping.er")
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn exec_trait() -> Result<(), ()> {
|
fn exec_trait() -> Result<(), ()> {
|
||||||
expect_success("examples/trait.er")
|
expect_success("examples/trait.er")
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue