feat: add restricted visibility syntax

This commit is contained in:
Shunsuke Shibayama 2023-03-05 02:19:18 +09:00
parent 309bb06db8
commit d92f5284c8
44 changed files with 3803 additions and 2358 deletions

View file

@ -200,9 +200,9 @@ impl<'a> HIRVisitor<'a> {
token: &Token,
) -> Option<&Expr> {
match acc {
Accessor::Ident(ident) => self.return_expr_if_same(expr, ident.name.token(), token),
Accessor::Ident(ident) => self.return_expr_if_same(expr, ident.raw.name.token(), token),
Accessor::Attr(attr) => self
.return_expr_if_same(expr, attr.ident.name.token(), token)
.return_expr_if_same(expr, attr.ident.raw.name.token(), token)
.or_else(|| self.get_expr(&attr.obj, token)),
}
}
@ -234,7 +234,7 @@ impl<'a> HIRVisitor<'a> {
.or_else(|| {
call.attr_name
.as_ref()
.and_then(|attr| self.return_expr_if_same(expr, attr.name.token(), token))
.and_then(|attr| self.return_expr_if_same(expr, attr.raw.name.token(), token))
})
.or_else(|| self.get_expr(&call.obj, token))
.or_else(|| self.get_expr_from_args(&call.args, token))
@ -266,7 +266,7 @@ impl<'a> HIRVisitor<'a> {
def: &'e Def,
token: &Token,
) -> Option<&Expr> {
self.return_expr_if_same(expr, def.sig.ident().name.token(), token)
self.return_expr_if_same(expr, def.sig.ident().raw.name.token(), token)
.or_else(|| self.get_expr_from_block(&def.body.block, token))
.or_else(|| def.loc().contains(token.loc()).then_some(expr))
}
@ -319,7 +319,7 @@ impl<'a> HIRVisitor<'a> {
patch_def: &'e PatchDef,
token: &Token,
) -> Option<&Expr> {
self.return_expr_if_same(expr, patch_def.sig.ident().name.token(), token)
self.return_expr_if_same(expr, patch_def.sig.name().token(), token)
.or_else(|| self.get_expr(&patch_def.base, token))
.or_else(|| self.get_expr_from_block(&patch_def.methods, token))
.or_else(|| patch_def.loc().contains(token.loc()).then_some(expr))
@ -489,10 +489,10 @@ impl<'a> HIRVisitor<'a> {
fn get_acc_info(&self, acc: &Accessor, token: &Token) -> Option<VarInfo> {
match acc {
Accessor::Ident(ident) => {
self.return_var_info_if_same(ident, ident.name.token(), token)
self.return_var_info_if_same(ident, ident.raw.name.token(), token)
}
Accessor::Attr(attr) => self
.return_var_info_if_same(&attr.ident, attr.ident.name.token(), token)
.return_var_info_if_same(&attr.ident, attr.ident.raw.name.token(), token)
.or_else(|| self.get_expr_info(&attr.obj, token)),
}
}
@ -504,7 +504,7 @@ impl<'a> HIRVisitor<'a> {
fn get_call_info(&self, call: &Call, token: &Token) -> Option<VarInfo> {
if let Some(attr) = &call.attr_name {
if let Some(t) = self.return_var_info_if_same(attr, attr.name.token(), token) {
if let Some(t) = self.return_var_info_if_same(attr, attr.raw.name.token(), token) {
return Some(t);
}
}
@ -534,10 +534,10 @@ impl<'a> HIRVisitor<'a> {
fn get_sig_info(&self, sig: &Signature, token: &Token) -> Option<VarInfo> {
match sig {
Signature::Var(var) => {
self.return_var_info_if_same(&var.ident, var.ident.name.token(), token)
self.return_var_info_if_same(&var.ident, var.name().token(), token)
}
Signature::Subr(subr) => self
.return_var_info_if_same(&subr.ident, subr.ident.name.token(), token)
.return_var_info_if_same(&subr.ident, subr.name().token(), token)
.or_else(|| self.get_params_info(&subr.params, token)),
}
}

View file

@ -526,7 +526,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
ctxs.extend(type_ctxs);
if let Ok(singular_ctx) = module
.context
.get_singular_ctx_by_hir_expr(expr, &"".into())
.get_singular_ctx_by_hir_expr(expr, &module.context)
{
ctxs.push(singular_ctx);
}

View file

@ -40,14 +40,17 @@ pub fn levenshtein(a: &str, b: &str, limit: usize) -> Option<usize> {
(dcol[m] <= limit).then_some(dcol[m])
}
pub fn get_similar_name<'a, I: Iterator<Item = &'a str> + Clone>(
pub fn get_similar_name<'a, S: ?Sized, I: Iterator<Item = &'a S> + Clone>(
candidates: I,
name: &str,
) -> Option<&'a str> {
let limit = (name.len() as f64).sqrt() as usize;
) -> Option<&'a S>
where
S: std::borrow::Borrow<str>,
{
let limit = (name.len() as f64).sqrt().round() as usize;
let most_similar_name =
candidates.min_by_key(|v| levenshtein(v, name, limit).unwrap_or(usize::MAX))?;
let dist = levenshtein(most_similar_name, name, limit);
candidates.min_by_key(|v| levenshtein(v.borrow(), name, limit).unwrap_or(usize::MAX))?;
let dist = levenshtein(most_similar_name.borrow(), name, limit);
if dist.is_none() || dist.unwrap() >= limit {
None
} else {
@ -55,6 +58,24 @@ pub fn get_similar_name<'a, I: Iterator<Item = &'a str> + Clone>(
}
}
pub fn get_similar_name_and_some<'a, S: ?Sized, T, I: Iterator<Item = (&'a T, &'a S)> + Clone>(
candidates: I,
name: &str,
) -> Option<(&'a T, &'a S)>
where
S: std::borrow::Borrow<str>,
{
let limit = (name.len() as f64).sqrt().round() as usize;
let most_similar_name_and_some = candidates
.min_by_key(|(_, v)| levenshtein(v.borrow(), name, limit).unwrap_or(usize::MAX))?;
let dist = levenshtein(most_similar_name_and_some.1.borrow(), name, limit);
if dist.is_none() || dist.unwrap() >= limit {
None
} else {
Some(most_similar_name_and_some)
}
}
#[cfg(test)]
mod tests {
use crate::levenshtein::get_similar_name;

View file

@ -31,9 +31,9 @@ pub mod stdin;
pub mod str;
pub mod style;
pub mod traits;
pub mod triple;
pub mod tsort;
pub mod tty;
pub mod vis;
use crate::set::Set;
pub use crate::str::Str;

View file

@ -199,6 +199,30 @@ impl Str {
ret
}
/// ```
/// use erg_common::str::Str;
/// let s = Str::rc("a.b.c");
/// assert_eq!(s.rpartition_with(&[".", "/"]), ("a.b", "c"));
/// let s = Str::rc("a::b.c");
/// assert_eq!(s.rpartition_with(&["/", "::"]), ("a", "b.c"));
/// ```
pub fn rpartition_with(&self, seps: &[&str]) -> (&str, &str) {
let mut i = self.len();
while i > 0 {
for sep in seps {
if self[i..].starts_with(sep) {
return (&self[..i], &self[i + sep.len()..]);
}
}
i -= 1;
}
(&self[..], "")
}
pub fn reversed(&self) -> Str {
Str::rc(&self.chars().rev().collect::<String>())
}
pub fn multi_replace(&self, paths: &[(&str, &str)]) -> Self {
let mut self_ = self.to_string();
for (from, to) in paths {
@ -237,11 +261,6 @@ impl Str {
mod tests {
use super::*;
use crate::dict;
// use crate::dict::Dict;
use crate::vis::Field;
#[test]
fn test_split_with() {
assert_eq!(
@ -261,17 +280,4 @@ mod tests {
vec!["aa", "bb", "ff"]
);
}
#[test]
fn test_std_key() {
let dict = dict! {Str::ever("a") => 1, Str::rc("b") => 2};
assert_eq!(dict.get("a"), Some(&1));
assert_eq!(dict.get("b"), Some(&2));
assert_eq!(dict.get(&Str::ever("b")), Some(&2));
assert_eq!(dict.get(&Str::rc("b")), Some(&2));
let dict = dict! {Field::private(Str::ever("a")) => 1, Field::public(Str::ever("b")) => 2};
assert_eq!(dict.get("a"), Some(&1));
assert_eq!(dict.get("b"), Some(&2));
}
}

View file

@ -0,0 +1,82 @@
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Triple<T, E> {
Ok(T),
Err(E),
None,
}
impl<T, E> Triple<T, E> {
pub fn none_then(self, err: E) -> Result<T, E> {
match self {
Triple::None => Err(err),
Triple::Ok(ok) => Ok(ok),
Triple::Err(err) => Err(err),
}
}
pub fn none_or_result(self, f: impl FnOnce() -> E) -> Result<T, E> {
match self {
Triple::None => Err(f()),
Triple::Ok(ok) => Ok(ok),
Triple::Err(err) => Err(err),
}
}
pub fn none_or_else(self, f: impl FnOnce() -> Triple<T, E>) -> Triple<T, E> {
match self {
Triple::None => f(),
Triple::Ok(ok) => Triple::Ok(ok),
Triple::Err(err) => Triple::Err(err),
}
}
pub fn unwrap_to_result(self) -> Result<T, E> {
match self {
Triple::None => panic!("unwrapping Triple::None"),
Triple::Ok(ok) => Ok(ok),
Triple::Err(err) => Err(err),
}
}
pub fn ok(self) -> Option<T> {
match self {
Triple::None => None,
Triple::Ok(ok) => Some(ok),
Triple::Err(_) => None,
}
}
pub fn or_else(self, f: impl FnOnce() -> Result<T, E>) -> Result<T, E> {
match self {
Triple::None => f(),
Triple::Ok(ok) => Ok(ok),
Triple::Err(err) => Err(err),
}
}
pub fn unwrap_or(self, default: T) -> T {
match self {
Triple::None => default,
Triple::Ok(ok) => ok,
Triple::Err(_) => default,
}
}
pub fn unwrap_err(self) -> E {
match self {
Triple::None => panic!("unwrapping Triple::None"),
Triple::Ok(_) => panic!("unwrapping Triple::Ok"),
Triple::Err(err) => err,
}
}
}
impl<T, E: std::error::Error> Triple<T, E> {
pub fn unwrap(self) -> T {
match self {
Triple::None => panic!("unwrapping Triple::None"),
Triple::Ok(ok) => ok,
Triple::Err(err) => panic!("unwrapping Triple::Err({err})"),
}
}
}

View file

@ -1,81 +0,0 @@
use std::borrow::Borrow;
use std::fmt;
use crate::Str;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(u8)]
pub enum Visibility {
Private,
Public,
}
impl Visibility {
pub const fn is_public(&self) -> bool {
matches!(self, Self::Public)
}
pub const fn is_private(&self) -> bool {
matches!(self, Self::Private)
}
}
/// same structure as `Identifier`, but only for Record fields.
#[derive(Debug, Clone, Eq)]
pub struct Field {
pub vis: Visibility,
pub symbol: Str,
}
impl PartialEq for Field {
fn eq(&self, other: &Self) -> bool {
self.symbol == other.symbol
}
}
impl std::hash::Hash for Field {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.symbol.hash(state);
}
}
impl fmt::Display for Field {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.vis.is_public() {
write!(f, ".{}", self.symbol)
} else {
write!(f, "::{}", self.symbol)
}
}
}
impl Borrow<str> for Field {
#[inline]
fn borrow(&self) -> &str {
&self.symbol[..]
}
}
impl Borrow<Str> for Field {
#[inline]
fn borrow(&self) -> &Str {
&self.symbol
}
}
impl Field {
pub const fn new(vis: Visibility, symbol: Str) -> Self {
Field { vis, symbol }
}
pub const fn private(symbol: Str) -> Self {
Field::new(Visibility::Private, symbol)
}
pub const fn public(symbol: Str) -> Self {
Field::new(Visibility::Public, symbol)
}
pub fn is_const(&self) -> bool {
self.symbol.starts_with(char::is_uppercase)
}
}

View file

@ -17,11 +17,11 @@ use erg_common::opcode311::{BinOpCode, Opcode311};
use erg_common::option_enum_unwrap;
use erg_common::python_util::{env_python_version, PythonVersion};
use erg_common::traits::{Locational, Stream};
use erg_common::vis::Visibility;
use erg_common::Str;
use erg_common::{
debug_power_assert, enum_unwrap, fn_name, fn_name_full, impl_stream, log, switch_unreachable,
};
use erg_parser::ast::VisModifierSpec;
use erg_parser::ast::{DefId, DefKind};
use CommonOpcode::*;
@ -38,7 +38,7 @@ use crate::hir::{
SubrSignature, Tuple, UnaryOp, VarSignature, HIR,
};
use crate::ty::value::ValueObj;
use crate::ty::{HasType, Type, TypeCode, TypePair};
use crate::ty::{HasType, Type, TypeCode, TypePair, VisibilityModifier};
use crate::varinfo::VarInfo;
use erg_common::fresh::fresh_varname;
use AccessKind::*;
@ -70,7 +70,7 @@ fn debind(ident: &Identifier) -> Option<Str> {
}
}
fn escape_name(name: &str, vis: Visibility) -> Str {
fn escape_name(name: &str, vis: &VisibilityModifier) -> Str {
let name = name.replace('!', "__erg_proc__");
let name = name.replace('$', "__erg_shared__");
if vis.is_private() {
@ -908,7 +908,7 @@ impl PyCodeGenerator {
if s == "_" {
format!("_{i}")
} else {
escape_name(s, Visibility::Private).to_string()
escape_name(s, &VisibilityModifier::Private).to_string()
}
})
.map(|s| self.get_cached(&s))
@ -930,11 +930,11 @@ impl PyCodeGenerator {
// Since Erg does not allow the coexistence of private and public variables with the same name, there is no problem in this trick.
let is_record = a.obj.ref_t().is_record();
if is_record {
a.ident.dot = Some(DOT);
a.ident.raw.vis = VisModifierSpec::Public(DOT);
}
if let Some(varname) = debind(&a.ident) {
a.ident.dot = None;
a.ident.name = VarName::from_str(varname);
a.ident.raw.vis = VisModifierSpec::Private;
a.ident.raw.name = VarName::from_str(varname);
self.emit_load_name_instr(a.ident);
} else {
self.emit_expr(*a.obj);
@ -1153,9 +1153,9 @@ impl PyCodeGenerator {
self.emit_load_const(code);
if self.py_version.minor < Some(11) {
if let Some(class) = class_name {
self.emit_load_const(Str::from(format!("{class}.{}", ident.name.inspect())));
self.emit_load_const(Str::from(format!("{class}.{}", ident.inspect())));
} else {
self.emit_load_const(ident.name.inspect().clone());
self.emit_load_const(ident.inspect().clone());
}
} else {
self.stack_inc();
@ -1213,8 +1213,8 @@ impl PyCodeGenerator {
patch_def.sig.ident().to_string_notype(),
def.sig.ident().to_string_notype()
);
def.sig.ident_mut().name = VarName::from_str(Str::from(name));
def.sig.ident_mut().dot = None;
def.sig.ident_mut().raw.name = VarName::from_str(Str::from(name));
def.sig.ident_mut().raw.vis = VisModifierSpec::Private;
self.emit_def(def);
}
}
@ -1925,7 +1925,8 @@ impl PyCodeGenerator {
}
match param.raw.pat {
ParamPattern::VarName(name) => {
let ident = Identifier::bare(None, name);
let ident = erg_parser::ast::Identifier::private_from_varname(name);
let ident = Identifier::bare(ident);
self.emit_store_instr(ident, AccessKind::Name);
}
ParamPattern::Discard(_) => {
@ -2190,7 +2191,7 @@ impl PyCodeGenerator {
let kw = if is_py_api {
arg.keyword.content
} else {
escape_name(&arg.keyword.content, Visibility::Private)
escape_name(&arg.keyword.content, &VisibilityModifier::Private)
};
kws.push(ValueObj::Str(kw));
self.emit_expr(arg.expr);
@ -2301,7 +2302,7 @@ impl PyCodeGenerator {
mut args: Args,
) {
log!(info "entered {}", fn_name!());
method_name.dot = None;
method_name.raw.vis = VisModifierSpec::Private;
method_name.vi.py_name = Some(func_name);
self.emit_push_null();
self.emit_load_name_instr(method_name);
@ -2785,6 +2786,7 @@ impl PyCodeGenerator {
let vi = VarInfo::nd_parameter(
__new__.return_t().unwrap().clone(),
ident.vi.def_loc.clone(),
"?".into(),
);
let raw =
erg_parser::ast::NonDefaultParamSignature::new(ParamPattern::VarName(self_param), None);
@ -2797,7 +2799,11 @@ impl PyCodeGenerator {
let param = VarName::from_str_and_line(Str::from(param_name.clone()), line);
let raw =
erg_parser::ast::NonDefaultParamSignature::new(ParamPattern::VarName(param), None);
let vi = VarInfo::nd_parameter(new_first_param.typ().clone(), ident.vi.def_loc.clone());
let vi = VarInfo::nd_parameter(
new_first_param.typ().clone(),
ident.vi.def_loc.clone(),
"?".into(),
);
let param = NonDefaultParamSignature::new(raw, vi, None);
let params = Params::new(vec![self_param, param], None, vec![], None);
(param_name, params)
@ -2818,20 +2824,19 @@ impl PyCodeGenerator {
for field in rec.keys() {
let obj =
Expr::Accessor(Accessor::private_with_line(Str::from(&param_name), line));
let expr = obj.attr_expr(Identifier::bare(
Some(DOT),
VarName::from_str(field.symbol.clone()),
));
let ident = erg_parser::ast::Identifier::public(field.symbol.clone());
let expr = obj.attr_expr(Identifier::bare(ident));
let obj = Expr::Accessor(Accessor::private_with_line(Str::ever("self"), line));
let dot = if field.vis.is_private() {
None
VisModifierSpec::Private
} else {
Some(DOT)
VisModifierSpec::Public(DOT)
};
let attr = obj.attr(Identifier::bare(
let attr = erg_parser::ast::Identifier::new(
dot,
VarName::from_str(field.symbol.clone()),
));
);
let attr = obj.attr(Identifier::bare(attr));
let redef = ReDef::new(attr, Block::new(vec![expr]));
attrs.push(Expr::ReDef(redef));
}
@ -2865,8 +2870,7 @@ impl PyCodeGenerator {
let line = sig.ln_begin().unwrap();
let mut ident = Identifier::public_with_line(DOT, Str::ever("new"), line);
let class = Expr::Accessor(Accessor::Ident(class_ident.clone()));
let mut new_ident =
Identifier::bare(None, VarName::from_str_and_line(Str::ever("__new__"), line));
let mut new_ident = Identifier::private_with_line(Str::ever("__new__"), line);
new_ident.vi.py_name = Some(Str::ever("__call__"));
let class_new = class.attr_expr(new_ident);
ident.vi.t = __new__;
@ -2876,7 +2880,11 @@ impl PyCodeGenerator {
.map(|s| s.to_string())
.unwrap_or_else(fresh_varname);
let param = VarName::from_str_and_line(Str::from(param_name.clone()), line);
let vi = VarInfo::nd_parameter(new_first_param.typ().clone(), ident.vi.def_loc.clone());
let vi = VarInfo::nd_parameter(
new_first_param.typ().clone(),
ident.vi.def_loc.clone(),
"?".into(),
);
let raw =
erg_parser::ast::NonDefaultParamSignature::new(ParamPattern::VarName(param), None);
let param = NonDefaultParamSignature::new(raw, vi, None);

View file

@ -1,21 +1,20 @@
//! provides type-comparison
use std::option::Option; // conflicting to Type::Option
use erg_common::dict::Dict;
use erg_common::error::MultiErrorDisplay;
use erg_common::style::colors::DEBUG_ERROR;
use erg_common::traits::StructuralEq;
use erg_common::{assume_unreachable, log};
use crate::ty::constructors::{and, not, or, poly};
use crate::ty::free::{Constraint, FreeKind};
use crate::ty::typaram::{OpKind, TyParam, TyParamOrdering};
use crate::ty::value::ValueObj;
use crate::ty::value::ValueObj::Inf;
use crate::ty::{Predicate, RefinementType, SubrKind, SubrType, Type};
use crate::ty::{Field, Predicate, RefinementType, SubrKind, SubrType, Type};
use Predicate as Pred;
use erg_common::dict::Dict;
use erg_common::vis::Field;
use erg_common::{assume_unreachable, log};
use TyParamOrdering::*;
use Type::*;
@ -705,7 +704,12 @@ impl Context {
.unwrap_or_else(|| panic!("{other} is not found"));
ctx.type_dir()
.into_iter()
.map(|(name, vi)| (Field::new(vi.vis, name.inspect().clone()), vi.t.clone()))
.map(|(name, vi)| {
(
Field::new(vi.vis.modifier.clone(), name.inspect().clone()),
vi.t.clone(),
)
})
.collect()
}
}

View file

@ -7,7 +7,6 @@ use erg_common::log;
use erg_common::set::Set;
use erg_common::shared::Shared;
use erg_common::traits::{Locational, Stream};
use erg_common::vis::Field;
use erg_common::{dict, fn_name, option_enum_unwrap, set};
use erg_common::{enum_unwrap, fmt_vec};
use erg_common::{RcArray, Str};
@ -27,7 +26,7 @@ use crate::ty::typaram::{OpKind, TyParam};
use crate::ty::value::{GenTypeObj, TypeObj, ValueObj};
use crate::ty::{ConstSubr, HasType, Predicate, SubrKind, Type, UserConstSubr, ValueArgs};
use crate::context::instantiate::ParamKind;
use crate::context::instantiate_spec::ParamKind;
use crate::context::{ClassDefType, Context, ContextKind, RegistrationMode};
use crate::error::{EvalError, EvalErrors, EvalResult, SingleEvalResult};
@ -166,7 +165,10 @@ impl Context {
}
fn eval_attr(&self, obj: ValueObj, ident: &Identifier) -> SingleEvalResult<ValueObj> {
if let Some(val) = obj.try_get_attr(&Field::from(ident)) {
let field = self
.instantiate_field(ident)
.map_err(|mut errs| errs.remove(0))?;
if let Some(val) = obj.try_get_attr(&field) {
return Ok(val);
}
if let ValueObj::Type(t) = &obj {
@ -301,7 +303,7 @@ impl Context {
fn eval_const_def(&mut self, def: &Def) -> EvalResult<ValueObj> {
if def.is_const() {
let __name__ = def.sig.ident().unwrap().inspect();
let vis = def.sig.vis();
let vis = self.instantiate_vis_modifier(def.sig.vis())?;
let tv_cache = match &def.sig {
Signature::Subr(subr) => {
let ty_cache =
@ -430,7 +432,7 @@ impl Context {
let elem = record_ctx.eval_const_block(&attr.body.block)?;
let ident = match &attr.sig {
Signature::Var(var) => match &var.pat {
VarPattern::Ident(ident) => Field::new(ident.vis(), ident.inspect().clone()),
VarPattern::Ident(ident) => self.instantiate_field(ident)?,
other => {
return feature_error!(self, other.loc(), &format!("record field: {other}"))
}

File diff suppressed because it is too large Load diff

View file

@ -1,25 +1,23 @@
#[allow(unused_imports)]
use erg_common::log;
use erg_common::vis::{Field, Visibility};
use crate::ty::constructors::*;
use crate::ty::typaram::TyParam;
use crate::ty::value::ValueObj;
use crate::ty::Type;
use crate::ty::{Field, Type, Visibility};
use Type::*;
use crate::context::initialize::*;
use crate::context::Context;
use crate::varinfo::Mutability;
use Mutability::*;
use Visibility::*;
impl Context {
pub(super) fn init_builtin_funcs(&mut self) {
let vis = if cfg!(feature = "py_compatible") {
Public
Visibility::BUILTIN_PUBLIC
} else {
Private
Visibility::BUILTIN_PRIVATE
};
let T = mono_q(TY_T, instanceof(Type));
let U = mono_q(TY_U, instanceof(Type));
@ -222,96 +220,144 @@ impl Context {
self.register_py_builtin(FUNC_ANY, t_any, Some(FUNC_ANY), 33);
self.register_py_builtin(FUNC_ASCII, t_ascii, Some(FUNC_ASCII), 53);
// Leave as `Const`, as it may negatively affect assert casting.
self.register_builtin_erg_impl(FUNC_ASSERT, t_assert, Const, vis);
self.register_builtin_py_impl(FUNC_BIN, t_bin, Immutable, vis, Some(FUNC_BIN));
self.register_builtin_py_impl(FUNC_BYTES, t_bytes, Immutable, vis, Some(FUNC_BYTES));
self.register_builtin_py_impl(FUNC_CHR, t_chr, Immutable, vis, Some(FUNC_CHR));
self.register_builtin_py_impl(FUNC_CLASSOF, t_classof, Immutable, vis, Some(FUNC_TYPE));
self.register_builtin_py_impl(FUNC_COMPILE, t_compile, Immutable, vis, Some(FUNC_COMPILE));
self.register_builtin_erg_impl(KW_COND, t_cond, Immutable, vis);
self.register_builtin_erg_impl(FUNC_ASSERT, t_assert, Const, vis.clone());
self.register_builtin_py_impl(FUNC_BIN, t_bin, Immutable, vis.clone(), Some(FUNC_BIN));
self.register_builtin_py_impl(
FUNC_BYTES,
t_bytes,
Immutable,
vis.clone(),
Some(FUNC_BYTES),
);
self.register_builtin_py_impl(FUNC_CHR, t_chr, Immutable, vis.clone(), Some(FUNC_CHR));
self.register_builtin_py_impl(
FUNC_CLASSOF,
t_classof,
Immutable,
vis.clone(),
Some(FUNC_TYPE),
);
self.register_builtin_py_impl(
FUNC_COMPILE,
t_compile,
Immutable,
vis.clone(),
Some(FUNC_COMPILE),
);
self.register_builtin_erg_impl(KW_COND, t_cond, Immutable, vis.clone());
self.register_builtin_py_impl(
FUNC_ENUMERATE,
t_enumerate,
Immutable,
vis,
vis.clone(),
Some(FUNC_ENUMERATE),
);
self.register_builtin_py_impl(FUNC_EXIT, t_exit, Immutable, vis, Some(FUNC_EXIT));
self.register_builtin_py_impl(FUNC_EXIT, t_exit, Immutable, vis.clone(), Some(FUNC_EXIT));
self.register_builtin_py_impl(
FUNC_ISINSTANCE,
t_isinstance,
Immutable,
vis,
vis.clone(),
Some(FUNC_ISINSTANCE),
);
self.register_builtin_py_impl(
FUNC_ISSUBCLASS,
t_issubclass,
Immutable,
vis,
vis.clone(),
Some(FUNC_ISSUBCLASS),
);
self.register_builtin_py_impl(FUNC_ITER, t_iter, Immutable, vis, Some(FUNC_ITER));
self.register_builtin_py_impl(FUNC_LEN, t_len, Immutable, vis, Some(FUNC_LEN));
self.register_builtin_py_impl(FUNC_MAP, t_map, Immutable, vis, Some(FUNC_MAP));
self.register_builtin_py_impl(FUNC_MAX, t_max, Immutable, vis, Some(FUNC_MAX));
self.register_builtin_py_impl(FUNC_MIN, t_min, Immutable, vis, Some(FUNC_MIN));
self.register_builtin_py_impl(FUNC_NOT, t_not, Immutable, vis, None); // `not` is not a function in Python
self.register_builtin_py_impl(FUNC_OCT, t_oct, Immutable, vis, Some(FUNC_OCT));
self.register_builtin_py_impl(FUNC_ORD, t_ord, Immutable, vis, Some(FUNC_ORD));
self.register_builtin_py_impl(FUNC_POW, t_pow, Immutable, vis, Some(FUNC_POW));
self.register_builtin_py_impl(FUNC_ITER, t_iter, Immutable, vis.clone(), Some(FUNC_ITER));
self.register_builtin_py_impl(FUNC_LEN, t_len, Immutable, vis.clone(), Some(FUNC_LEN));
self.register_builtin_py_impl(FUNC_MAP, t_map, Immutable, vis.clone(), Some(FUNC_MAP));
self.register_builtin_py_impl(FUNC_MAX, t_max, Immutable, vis.clone(), Some(FUNC_MAX));
self.register_builtin_py_impl(FUNC_MIN, t_min, Immutable, vis.clone(), Some(FUNC_MIN));
self.register_builtin_py_impl(FUNC_NOT, t_not, Immutable, vis.clone(), None); // `not` is not a function in Python
self.register_builtin_py_impl(FUNC_OCT, t_oct, Immutable, vis.clone(), Some(FUNC_OCT));
self.register_builtin_py_impl(FUNC_ORD, t_ord, Immutable, vis.clone(), Some(FUNC_ORD));
self.register_builtin_py_impl(FUNC_POW, t_pow, Immutable, vis.clone(), Some(FUNC_POW));
self.register_builtin_py_impl(
PYIMPORT,
t_pyimport.clone(),
Immutable,
vis,
vis.clone(),
Some(FUNDAMENTAL_IMPORT),
);
self.register_builtin_py_impl(FUNC_QUIT, t_quit, Immutable, vis, Some(FUNC_QUIT));
self.register_builtin_py_impl(FUNC_REPR, t_repr, Immutable, vis, Some(FUNC_REPR));
self.register_builtin_py_impl(FUNC_QUIT, t_quit, Immutable, vis.clone(), Some(FUNC_QUIT));
self.register_builtin_py_impl(FUNC_REPR, t_repr, Immutable, vis.clone(), Some(FUNC_REPR));
self.register_builtin_py_impl(
FUNC_REVERSED,
t_reversed,
Immutable,
vis,
vis.clone(),
Some(FUNC_REVERSED),
);
self.register_builtin_py_impl(FUNC_ROUND, t_round, Immutable, vis, Some(FUNC_ROUND));
self.register_builtin_py_impl(FUNC_SORTED, t_sorted, Immutable, vis, Some(FUNC_SORTED));
self.register_builtin_py_impl(FUNC_STR, t_str, Immutable, vis, Some(FUNC_STR__));
self.register_builtin_py_impl(FUNC_SUM, t_sum, Immutable, vis, Some(FUNC_SUM));
self.register_builtin_py_impl(FUNC_ZIP, t_zip, Immutable, vis, Some(FUNC_ZIP));
self.register_builtin_py_impl(
FUNC_ROUND,
t_round,
Immutable,
vis.clone(),
Some(FUNC_ROUND),
);
self.register_builtin_py_impl(
FUNC_SORTED,
t_sorted,
Immutable,
vis.clone(),
Some(FUNC_SORTED),
);
self.register_builtin_py_impl(FUNC_STR, t_str, Immutable, vis.clone(), Some(FUNC_STR__));
self.register_builtin_py_impl(FUNC_SUM, t_sum, Immutable, vis.clone(), Some(FUNC_SUM));
self.register_builtin_py_impl(FUNC_ZIP, t_zip, Immutable, vis.clone(), Some(FUNC_ZIP));
let name = if cfg!(feature = "py_compatible") {
FUNC_INT
} else {
FUNC_INT__
};
self.register_builtin_py_impl(FUNC_INT, t_int, Immutable, vis, Some(name));
self.register_builtin_py_impl(FUNC_INT, t_int, Immutable, vis.clone(), Some(name));
if !cfg!(feature = "py_compatible") {
self.register_builtin_py_impl(FUNC_IF, t_if, Immutable, vis, Some(FUNC_IF__));
self.register_builtin_py_impl(FUNC_IF, t_if, Immutable, vis.clone(), Some(FUNC_IF__));
self.register_builtin_py_impl(
FUNC_DISCARD,
t_discard,
Immutable,
vis,
vis.clone(),
Some(FUNC_DISCARD__),
);
self.register_builtin_py_impl(
FUNC_IMPORT,
t_import,
Immutable,
vis,
vis.clone(),
Some(FUNDAMENTAL_IMPORT),
);
self.register_builtin_py_impl(FUNC_LOG, t_log, Immutable, vis, Some(FUNC_PRINT));
self.register_builtin_py_impl(FUNC_NAT, t_nat, Immutable, vis, Some(FUNC_NAT__));
self.register_builtin_py_impl(FUNC_PANIC, t_panic, Immutable, vis, Some(FUNC_QUIT));
self.register_builtin_py_impl(
FUNC_LOG,
t_log,
Immutable,
vis.clone(),
Some(FUNC_PRINT),
);
self.register_builtin_py_impl(
FUNC_NAT,
t_nat,
Immutable,
vis.clone(),
Some(FUNC_NAT__),
);
self.register_builtin_py_impl(
FUNC_PANIC,
t_panic,
Immutable,
vis.clone(),
Some(FUNC_QUIT),
);
if cfg!(feature = "debug") {
self.register_builtin_py_impl(
PY,
t_pyimport,
Immutable,
vis,
vis.clone(),
Some(FUNDAMENTAL_IMPORT),
);
}
@ -319,7 +365,7 @@ impl Context {
PYCOMPILE,
t_pycompile,
Immutable,
vis,
vis.clone(),
Some(FUNC_COMPILE),
);
// TODO: original implementation
@ -340,7 +386,13 @@ impl Context {
],
poly(RANGE, vec![ty_tp(Int)]),
);
self.register_builtin_py_impl(FUNC_RANGE, t_range, Immutable, vis, Some(FUNC_RANGE));
self.register_builtin_py_impl(
FUNC_RANGE,
t_range,
Immutable,
vis.clone(),
Some(FUNC_RANGE),
);
let t_list = func(
vec![],
None,
@ -348,7 +400,13 @@ impl Context {
poly(ARRAY, vec![ty_tp(T.clone()), TyParam::erased(Nat)]),
)
.quantify();
self.register_builtin_py_impl(FUNC_LIST, t_list, Immutable, vis, Some(FUNC_LIST));
self.register_builtin_py_impl(
FUNC_LIST,
t_list,
Immutable,
vis.clone(),
Some(FUNC_LIST),
);
let t_dict = func(
vec![],
None,
@ -365,9 +423,9 @@ impl Context {
pub(super) fn init_builtin_const_funcs(&mut self) {
let vis = if cfg!(feature = "py_compatible") {
Public
Visibility::BUILTIN_PUBLIC
} else {
Private
Visibility::BUILTIN_PRIVATE
};
let class_t = func(
vec![],
@ -376,7 +434,7 @@ impl Context {
ClassType,
);
let class = ConstSubr::Builtin(BuiltinConstSubr::new(CLASS, class_func, class_t, None));
self.register_builtin_const(CLASS, vis, ValueObj::Subr(class));
self.register_builtin_const(CLASS, vis.clone(), ValueObj::Subr(class));
let inherit_t = func(
vec![kw(KW_SUPER, ClassType)],
None,
@ -389,7 +447,7 @@ impl Context {
inherit_t,
None,
));
self.register_builtin_const(INHERIT, vis, ValueObj::Subr(inherit));
self.register_builtin_const(INHERIT, vis.clone(), ValueObj::Subr(inherit));
let trait_t = func(
vec![kw(KW_REQUIREMENT, Type)],
None,
@ -397,7 +455,7 @@ impl Context {
TraitType,
);
let trait_ = ConstSubr::Builtin(BuiltinConstSubr::new(TRAIT, trait_func, trait_t, None));
self.register_builtin_const(TRAIT, vis, ValueObj::Subr(trait_));
self.register_builtin_const(TRAIT, vis.clone(), ValueObj::Subr(trait_));
let subsume_t = func(
vec![kw(KW_SUPER, TraitType)],
None,
@ -410,14 +468,14 @@ impl Context {
subsume_t,
None,
));
self.register_builtin_const(SUBSUME, vis, ValueObj::Subr(subsume));
self.register_builtin_const(SUBSUME, vis.clone(), ValueObj::Subr(subsume));
let structural = ConstSubr::Builtin(BuiltinConstSubr::new(
STRUCTURAL,
structural_func,
func1(Type, Type),
None,
));
self.register_builtin_const(STRUCTURAL, vis, ValueObj::Subr(structural));
self.register_builtin_const(STRUCTURAL, vis.clone(), ValueObj::Subr(structural));
// decorators
let inheritable_t = func1(ClassType, ClassType);
let inheritable = ConstSubr::Builtin(BuiltinConstSubr::new(
@ -426,10 +484,10 @@ impl Context {
inheritable_t,
None,
));
self.register_builtin_const(INHERITABLE, vis, ValueObj::Subr(inheritable));
self.register_builtin_const(INHERITABLE, vis.clone(), ValueObj::Subr(inheritable));
// TODO: register Del function object
let t_del = nd_func(vec![kw(KW_OBJ, Obj)], None, NoneType);
self.register_builtin_erg_impl(DEL, t_del, Immutable, vis);
self.register_builtin_erg_impl(DEL, t_del, Immutable, vis.clone());
let patch_t = func(
vec![kw(KW_REQUIREMENT, Type)],
None,
@ -451,65 +509,65 @@ impl Context {
proj(L, OUTPUT),
)
.quantify();
self.register_builtin_erg_impl(OP_ADD, op_t, Const, Private);
self.register_builtin_erg_impl(OP_ADD, op_t, Const, Visibility::BUILTIN_PRIVATE);
let L = mono_q(TY_L, subtypeof(poly(SUB, params.clone())));
let op_t = bin_op(L.clone(), R.clone(), proj(L, OUTPUT)).quantify();
self.register_builtin_erg_impl(OP_SUB, op_t, Const, Private);
self.register_builtin_erg_impl(OP_SUB, op_t, Const, Visibility::BUILTIN_PRIVATE);
let L = mono_q(TY_L, subtypeof(poly(MUL, params.clone())));
let op_t = bin_op(L.clone(), R.clone(), proj(L, OUTPUT)).quantify();
self.register_builtin_erg_impl(OP_MUL, op_t, Const, Private);
self.register_builtin_erg_impl(OP_MUL, op_t, Const, Visibility::BUILTIN_PRIVATE);
let L = mono_q(TY_L, subtypeof(poly(DIV, params.clone())));
let op_t = bin_op(L.clone(), R.clone(), proj(L, OUTPUT)).quantify();
self.register_builtin_erg_impl(OP_DIV, op_t, Const, Private);
self.register_builtin_erg_impl(OP_DIV, op_t, Const, Visibility::BUILTIN_PRIVATE);
let L = mono_q(TY_L, subtypeof(poly(FLOOR_DIV, params)));
let op_t = bin_op(L.clone(), R, proj(L, OUTPUT)).quantify();
self.register_builtin_erg_impl(OP_FLOOR_DIV, op_t, Const, Private);
self.register_builtin_erg_impl(OP_FLOOR_DIV, op_t, Const, Visibility::BUILTIN_PRIVATE);
let P = mono_q(TY_P, Constraint::Uninited);
let P = mono_q(TY_P, subtypeof(poly(MUL, vec![ty_tp(P)])));
let op_t = bin_op(P.clone(), P.clone(), proj(P, POW_OUTPUT)).quantify();
// TODO: add bound: M == M.Output
self.register_builtin_erg_impl(OP_POW, op_t, Const, Private);
self.register_builtin_erg_impl(OP_POW, op_t, Const, Visibility::BUILTIN_PRIVATE);
let M = mono_q(TY_M, Constraint::Uninited);
let M = mono_q(TY_M, subtypeof(poly(DIV, vec![ty_tp(M)])));
let op_t = bin_op(M.clone(), M.clone(), proj(M, MOD_OUTPUT)).quantify();
self.register_builtin_erg_impl(OP_MOD, op_t, Const, Private);
self.register_builtin_erg_impl(OP_MOD, op_t, Const, Visibility::BUILTIN_PRIVATE);
let op_t = nd_proc(vec![kw(KW_LHS, Obj), kw(KW_RHS, Obj)], None, Bool);
self.register_builtin_erg_impl(OP_IS, op_t.clone(), Const, Private);
self.register_builtin_erg_impl(OP_IS_NOT, op_t, Const, Private);
self.register_builtin_erg_impl(OP_IS, op_t.clone(), Const, Visibility::BUILTIN_PRIVATE);
self.register_builtin_erg_impl(OP_IS_NOT, op_t, Const, Visibility::BUILTIN_PRIVATE);
let E = mono_q(TY_E, subtypeof(mono(EQ)));
let op_t = bin_op(E.clone(), E, Bool).quantify();
self.register_builtin_erg_impl(OP_EQ, op_t.clone(), Const, Private);
self.register_builtin_erg_impl(OP_NE, op_t, Const, Private);
self.register_builtin_erg_impl(OP_EQ, op_t.clone(), Const, Visibility::BUILTIN_PRIVATE);
self.register_builtin_erg_impl(OP_NE, op_t, Const, Visibility::BUILTIN_PRIVATE);
let O = mono_q(TY_O, subtypeof(mono(ORD)));
let op_t = bin_op(O.clone(), O.clone(), Bool).quantify();
self.register_builtin_erg_impl(OP_LT, op_t.clone(), Const, Private);
self.register_builtin_erg_impl(OP_LE, op_t.clone(), Const, Private);
self.register_builtin_erg_impl(OP_GT, op_t.clone(), Const, Private);
self.register_builtin_erg_impl(OP_GE, op_t, Const, Private);
self.register_builtin_erg_impl(OP_LT, op_t.clone(), Const, Visibility::BUILTIN_PRIVATE);
self.register_builtin_erg_impl(OP_LE, op_t.clone(), Const, Visibility::BUILTIN_PRIVATE);
self.register_builtin_erg_impl(OP_GT, op_t.clone(), Const, Visibility::BUILTIN_PRIVATE);
self.register_builtin_erg_impl(OP_GE, op_t, Const, Visibility::BUILTIN_PRIVATE);
let BT = mono_q(TY_BT, subtypeof(or(Bool, Type)));
let op_t = bin_op(BT.clone(), BT.clone(), BT).quantify();
self.register_builtin_erg_impl(OP_AND, op_t.clone(), Const, Private);
self.register_builtin_erg_impl(OP_OR, op_t, Const, Private);
self.register_builtin_erg_impl(OP_AND, op_t.clone(), Const, Visibility::BUILTIN_PRIVATE);
self.register_builtin_erg_impl(OP_OR, op_t, Const, Visibility::BUILTIN_PRIVATE);
let op_t = bin_op(O.clone(), O.clone(), range(O)).quantify();
self.register_builtin_erg_decl(OP_RNG, op_t.clone(), Private);
self.register_builtin_erg_decl(OP_LORNG, op_t.clone(), Private);
self.register_builtin_erg_decl(OP_RORNG, op_t.clone(), Private);
self.register_builtin_erg_decl(OP_ORNG, op_t, Private);
self.register_builtin_erg_decl(OP_RNG, op_t.clone(), Visibility::BUILTIN_PRIVATE);
self.register_builtin_erg_decl(OP_LORNG, op_t.clone(), Visibility::BUILTIN_PRIVATE);
self.register_builtin_erg_decl(OP_RORNG, op_t.clone(), Visibility::BUILTIN_PRIVATE);
self.register_builtin_erg_decl(OP_ORNG, op_t, Visibility::BUILTIN_PRIVATE);
// TODO: use existential type: |T: Type| (T, In(T)) -> Bool
let T = mono_q(TY_T, instanceof(Type));
let I = mono_q(KW_I, subtypeof(poly(IN, vec![ty_tp(T.clone())])));
let op_t = bin_op(I, T, Bool).quantify();
self.register_builtin_erg_impl(OP_IN, op_t.clone(), Const, Private);
self.register_builtin_erg_impl(OP_NOT_IN, op_t, Const, Private);
self.register_builtin_erg_impl(OP_IN, op_t.clone(), Const, Visibility::BUILTIN_PRIVATE);
self.register_builtin_erg_impl(OP_NOT_IN, op_t, Const, Visibility::BUILTIN_PRIVATE);
/* unary */
// TODO: +/- Bool would like to be warned
let M = mono_q(TY_M, subtypeof(mono(MUTIZABLE)));
let op_t = func1(M.clone(), proj(M, MUTABLE_MUT_TYPE)).quantify();
self.register_builtin_erg_impl(OP_MUTATE, op_t, Const, Private);
self.register_builtin_erg_impl(OP_MUTATE, op_t, Const, Visibility::BUILTIN_PRIVATE);
let N = mono_q(TY_N, subtypeof(mono(NUM)));
let op_t = func1(N.clone(), N).quantify();
self.register_builtin_erg_decl(OP_POS, op_t.clone(), Private);
self.register_builtin_erg_decl(OP_NEG, op_t, Private);
self.register_builtin_erg_decl(OP_POS, op_t.clone(), Visibility::BUILTIN_PRIVATE);
self.register_builtin_erg_decl(OP_NEG, op_t, Visibility::BUILTIN_PRIVATE);
}
pub(super) fn init_py_builtin_operators(&mut self) {
@ -525,7 +583,7 @@ impl Context {
.structuralize();
bin_op(S, R.clone(), O.clone()).quantify()
};
self.register_builtin_erg_impl(OP_ADD, op_t, Const, Private);
self.register_builtin_erg_impl(OP_ADD, op_t, Const, Visibility::BUILTIN_PRIVATE);
let op_t = {
let S = Type::from(
dict! { Field::public("__sub__".into()) => fn1_met(Never, R.clone(), O.clone()) },
@ -533,7 +591,7 @@ impl Context {
.structuralize();
bin_op(S, R.clone(), O.clone()).quantify()
};
self.register_builtin_erg_impl(OP_SUB, op_t, Const, Private);
self.register_builtin_erg_impl(OP_SUB, op_t, Const, Visibility::BUILTIN_PRIVATE);
let op_t = {
let S = Type::from(
dict! { Field::public("__mul__".into()) => fn1_met(Never, R.clone(), O.clone()) },
@ -541,7 +599,7 @@ impl Context {
.structuralize();
bin_op(S, R.clone(), O.clone()).quantify()
};
self.register_builtin_erg_impl(OP_MUL, op_t, Const, Private);
self.register_builtin_erg_impl(OP_MUL, op_t, Const, Visibility::BUILTIN_PRIVATE);
let op_t = {
let S = Type::from(
dict! { Field::public("__div__".into()) => fn1_met(Never, R.clone(), O.clone()) },
@ -549,7 +607,7 @@ impl Context {
.structuralize();
bin_op(S, R.clone(), O.clone()).quantify()
};
self.register_builtin_erg_impl(OP_DIV, op_t, Const, Private);
self.register_builtin_erg_impl(OP_DIV, op_t, Const, Visibility::BUILTIN_PRIVATE);
let op_t = {
let S = Type::from(
dict! { Field::public("__floordiv__".into()) => fn1_met(Never, R.clone(), O.clone()) },
@ -557,7 +615,7 @@ impl Context {
.structuralize();
bin_op(S, R.clone(), O.clone()).quantify()
};
self.register_builtin_erg_impl(OP_FLOOR_DIV, op_t, Const, Private);
self.register_builtin_erg_impl(OP_FLOOR_DIV, op_t, Const, Visibility::BUILTIN_PRIVATE);
let op_t = {
let S = Type::from(
dict! { Field::public("__pow__".into()) => fn1_met(Never, R.clone(), O.clone()) },
@ -565,7 +623,7 @@ impl Context {
.structuralize();
bin_op(S, R.clone(), O.clone()).quantify()
};
self.register_builtin_erg_impl(OP_POW, op_t, Const, Private);
self.register_builtin_erg_impl(OP_POW, op_t, Const, Visibility::BUILTIN_PRIVATE);
let op_t = {
let S = Type::from(
dict! { Field::public("__mod__".into()) => fn1_met(Never, R.clone(), O.clone()) },
@ -573,10 +631,10 @@ impl Context {
.structuralize();
bin_op(S, R.clone(), O.clone()).quantify()
};
self.register_builtin_erg_impl(OP_MOD, op_t, Const, Private);
self.register_builtin_erg_impl(OP_MOD, op_t, Const, Visibility::BUILTIN_PRIVATE);
let op_t = nd_proc(vec![kw(KW_LHS, Obj), kw(KW_RHS, Obj)], None, Bool);
self.register_builtin_erg_impl(OP_IS, op_t.clone(), Const, Private);
self.register_builtin_erg_impl(OP_IS_NOT, op_t, Const, Private);
self.register_builtin_erg_impl(OP_IS, op_t.clone(), Const, Visibility::BUILTIN_PRIVATE);
self.register_builtin_erg_impl(OP_IS_NOT, op_t, Const, Visibility::BUILTIN_PRIVATE);
let op_t = {
let S = Type::from(
dict! { Field::public("__eq__".into()) => fn1_met(Never, R.clone(), Bool) },
@ -584,7 +642,7 @@ impl Context {
.structuralize();
bin_op(S, R.clone(), Bool).quantify()
};
self.register_builtin_erg_impl(OP_EQ, op_t, Const, Private);
self.register_builtin_erg_impl(OP_EQ, op_t, Const, Visibility::BUILTIN_PRIVATE);
let op_t = {
let S = Type::from(
dict! { Field::public("__ne__".into()) => fn1_met(Never, R.clone(), Bool) },
@ -592,7 +650,7 @@ impl Context {
.structuralize();
bin_op(S, R.clone(), Bool).quantify()
};
self.register_builtin_erg_impl(OP_NE, op_t, Const, Private);
self.register_builtin_erg_impl(OP_NE, op_t, Const, Visibility::BUILTIN_PRIVATE);
let op_t = {
let S = Type::from(
dict! { Field::public("__lt__".into()) => fn1_met(Never, R.clone(), Bool) },
@ -600,7 +658,7 @@ impl Context {
.structuralize();
bin_op(S, R.clone(), Bool).quantify()
};
self.register_builtin_erg_impl(OP_LT, op_t, Const, Private);
self.register_builtin_erg_impl(OP_LT, op_t, Const, Visibility::BUILTIN_PRIVATE);
let op_t = {
let S = Type::from(
dict! { Field::public("__le__".into()) => fn1_met(Never, R.clone(), Bool) },
@ -608,7 +666,7 @@ impl Context {
.structuralize();
bin_op(S, R.clone(), Bool).quantify()
};
self.register_builtin_erg_impl(OP_LE, op_t, Const, Private);
self.register_builtin_erg_impl(OP_LE, op_t, Const, Visibility::BUILTIN_PRIVATE);
let op_t = {
let S = Type::from(
dict! { Field::public("__gt__".into()) => fn1_met(Never, R.clone(), Bool) },
@ -616,7 +674,7 @@ impl Context {
.structuralize();
bin_op(S, R.clone(), Bool).quantify()
};
self.register_builtin_erg_impl(OP_GT, op_t, Const, Private);
self.register_builtin_erg_impl(OP_GT, op_t, Const, Visibility::BUILTIN_PRIVATE);
let op_t = {
let S = Type::from(
dict! { Field::public("__ge__".into()) => fn1_met(Never, R.clone(), Bool) },
@ -624,7 +682,7 @@ impl Context {
.structuralize();
bin_op(S, R.clone(), Bool).quantify()
};
self.register_builtin_erg_impl(OP_GE, op_t, Const, Private);
self.register_builtin_erg_impl(OP_GE, op_t, Const, Visibility::BUILTIN_PRIVATE);
let op_t = {
let S = Type::from(
dict! { Field::public("__and__".into()) => fn1_met(Never, R.clone(), O.clone()) },
@ -632,7 +690,7 @@ impl Context {
.structuralize();
bin_op(S, R.clone(), O.clone()).quantify()
};
self.register_builtin_erg_impl(OP_AND, op_t, Const, Private);
self.register_builtin_erg_impl(OP_AND, op_t, Const, Visibility::BUILTIN_PRIVATE);
let op_t = {
let S = Type::from(
dict! { Field::public("__or__".into()) => fn1_met(Never, R.clone(), O.clone()) },
@ -640,7 +698,7 @@ impl Context {
.structuralize();
bin_op(S, R.clone(), O).quantify()
};
self.register_builtin_erg_impl(OP_OR, op_t, Const, Private);
self.register_builtin_erg_impl(OP_OR, op_t, Const, Visibility::BUILTIN_PRIVATE);
/* unary */
let op_t = {
let S =
@ -648,13 +706,13 @@ impl Context {
.structuralize();
func1(S, R.clone()).quantify()
};
self.register_builtin_erg_decl(OP_POS, op_t, Private);
self.register_builtin_erg_decl(OP_POS, op_t, Visibility::BUILTIN_PRIVATE);
let op_t = {
let S =
Type::from(dict! { Field::public("__neg__".into()) => fn0_met(Never, R.clone()) })
.structuralize();
func1(S, R).quantify()
};
self.register_builtin_erg_decl(OP_NEG, op_t, Private);
self.register_builtin_erg_decl(OP_NEG, op_t, Visibility::BUILTIN_PRIVATE);
}
}

View file

@ -18,28 +18,26 @@ use erg_common::error::Location;
use erg_common::fresh::fresh_varname;
#[allow(unused_imports)]
use erg_common::log;
use erg_common::vis::Visibility;
use erg_common::Str;
use erg_common::{set, unique_in_place};
use erg_parser::ast::VarName;
use crate::context::initialize::const_func::*;
use crate::context::instantiate::ConstTemplate;
use crate::context::instantiate_spec::ConstTemplate;
use crate::context::{
ClassDefType, Context, ContextKind, MethodInfo, ModuleContext, ParamSpec, TraitImpl,
};
use crate::module::SharedCompilerResource;
use crate::ty::free::Constraint;
use crate::ty::value::ValueObj;
use crate::ty::Type;
use crate::ty::{constructors::*, BuiltinConstSubr, ConstSubr, Predicate};
use crate::ty::{Type, Visibility};
use crate::varinfo::{AbsLocation, Mutability, VarInfo, VarKind};
use Mutability::*;
use ParamSpec as PS;
use Type::*;
use VarKind::*;
use Visibility::*;
const NUM: &str = "Num";
@ -543,7 +541,7 @@ impl Context {
);
if let Some(_vi) = self.locals.get(&name) {
if _vi != &vi {
panic!("already registered: {} {name}", self.name);
unreachable!("already registered: {} {name}", self.name);
}
} else {
self.locals.insert(name, vi);
@ -599,9 +597,9 @@ impl Context {
VarName::from_static(name)
};
let vis = if cfg!(feature = "py_compatible") || &self.name[..] != "<builtins>" {
Public
Visibility::BUILTIN_PUBLIC
} else {
Private
Visibility::BUILTIN_PRIVATE
};
let muty = Immutable;
let loc = Location::range(lineno, 0, lineno, name.inspect().len() as u32);
@ -859,50 +857,56 @@ impl Context {
fn init_builtin_consts(&mut self) {
let vis = if cfg!(feature = "py_compatible") {
Public
Visibility::BUILTIN_PUBLIC
} else {
Private
Visibility::BUILTIN_PRIVATE
};
// TODO: this is not a const, but a special property
self.register_builtin_py_impl(
FUNDAMENTAL_NAME,
Str,
Immutable,
vis,
vis.clone(),
Some(FUNDAMENTAL_NAME),
);
self.register_builtin_py_impl(
LICENSE,
mono(SITEBUILTINS_PRINTER),
Immutable,
vis,
vis.clone(),
Some(LICENSE),
);
self.register_builtin_py_impl(
CREDITS,
mono(SITEBUILTINS_PRINTER),
Immutable,
vis,
vis.clone(),
Some(CREDITS),
);
self.register_builtin_py_impl(
COPYRIGHT,
mono(SITEBUILTINS_PRINTER),
Immutable,
vis,
vis.clone(),
Some(COPYRIGHT),
);
self.register_builtin_py_impl(
NOT_IMPLEMENTED,
NotImplementedType,
Const,
vis,
vis.clone(),
Some(NOT_IMPLEMENTED),
);
self.register_builtin_py_impl(ELLIPSIS, Ellipsis, Const, vis, Some(ELLIPSIS));
self.register_builtin_py_impl(TRUE, Bool, Const, Private, Some(TRUE));
self.register_builtin_py_impl(FALSE, Bool, Const, Private, Some(FALSE));
self.register_builtin_py_impl(NONE, NoneType, Const, Private, Some(NONE));
self.register_builtin_py_impl(TRUE, Bool, Const, Visibility::BUILTIN_PRIVATE, Some(TRUE));
self.register_builtin_py_impl(FALSE, Bool, Const, Visibility::BUILTIN_PRIVATE, Some(FALSE));
self.register_builtin_py_impl(
NONE,
NoneType,
Const,
Visibility::BUILTIN_PRIVATE,
Some(NONE),
);
}
pub(crate) fn init_builtins(cfg: ErgConfig, shared: SharedCompilerResource) {

View file

@ -1,18 +1,16 @@
#[allow(unused_imports)]
use erg_common::log;
use erg_common::vis::Visibility;
use crate::ty::constructors::*;
use crate::ty::typaram::TyParam;
use crate::ty::value::ValueObj;
use crate::ty::Type;
use crate::ty::{Type, Visibility};
use Type::*;
use crate::context::initialize::*;
use crate::context::Context;
use crate::varinfo::Mutability;
use Mutability::*;
use Visibility::*;
impl Context {
pub(super) fn init_builtin_patches(&mut self) {
@ -38,10 +36,10 @@ impl Context {
)
.quantify();
let mut interval_add = Self::builtin_methods(Some(impls), 2);
interval_add.register_builtin_erg_impl("__add__", op_t, Const, Public);
interval_add.register_builtin_erg_impl("__add__", op_t, Const, Visibility::BUILTIN_PUBLIC);
interval_add.register_builtin_const(
"Output",
Public,
Visibility::BUILTIN_PUBLIC,
ValueObj::builtin_t(Type::from(m.clone() + o.clone()..=n.clone() + p.clone())),
);
interval.register_trait(class.clone(), interval_add);
@ -53,18 +51,18 @@ impl Context {
Type::from(m.clone() - p.clone()..=n.clone() - o.clone()),
)
.quantify();
interval_sub.register_builtin_erg_impl("__sub__", op_t, Const, Public);
interval_sub.register_builtin_erg_impl("__sub__", op_t, Const, Visibility::BUILTIN_PUBLIC);
interval_sub.register_builtin_const(
"Output",
Public,
Visibility::BUILTIN_PUBLIC,
ValueObj::builtin_t(Type::from(m - p..=n - o)),
);
interval.register_trait(class, interval_sub);
self.register_builtin_patch("Interval", interval, Private, Const);
// eq.register_impl("__ne__", op_t, Const, Public);
// ord.register_impl("__le__", op_t.clone(), Const, Public);
// ord.register_impl("__gt__", op_t.clone(), Const, Public);
// ord.register_impl("__ge__", op_t, Const, Public);
self.register_builtin_patch("Interval", interval, Visibility::BUILTIN_PRIVATE, Const);
// eq.register_impl("__ne__", op_t, Const, Visibility::BUILTIN_PUBLIC);
// ord.register_impl("__le__", op_t.clone(), Const, Visibility::BUILTIN_PUBLIC);
// ord.register_impl("__gt__", op_t.clone(), Const, Visibility::BUILTIN_PUBLIC);
// ord.register_impl("__ge__", op_t, Const, Visibility::BUILTIN_PUBLIC);
let E = mono_q("E", subtypeof(mono("Eq")));
let base = or(E, NoneType);
let impls = mono("Eq");
@ -73,8 +71,8 @@ impl Context {
Self::builtin_poly_glue_patch("OptionEq", base.clone(), impls.clone(), params, 1);
let mut option_eq_impl = Self::builtin_methods(Some(impls), 1);
let op_t = fn1_met(base.clone(), base.clone(), Bool).quantify();
option_eq_impl.register_builtin_erg_impl("__eq__", op_t, Const, Public);
option_eq_impl.register_builtin_erg_impl("__eq__", op_t, Const, Visibility::BUILTIN_PUBLIC);
option_eq.register_trait(base, option_eq_impl);
self.register_builtin_patch("OptionEq", option_eq, Private, Const);
self.register_builtin_patch("OptionEq", option_eq, Visibility::BUILTIN_PRIVATE, Const);
}
}

View file

@ -1,24 +1,22 @@
#[allow(unused_imports)]
use erg_common::log;
use erg_common::vis::Visibility;
use crate::ty::constructors::*;
use crate::ty::typaram::TyParam;
use crate::ty::Type;
use crate::ty::{Type, Visibility};
use Type::*;
use crate::context::initialize::*;
use crate::context::Context;
use crate::varinfo::Mutability;
use Mutability::*;
use Visibility::*;
impl Context {
pub(super) fn init_builtin_procs(&mut self) {
let vis = if cfg!(feature = "py_compatible") {
Public
Visibility::BUILTIN_PUBLIC
} else {
Private
Visibility::BUILTIN_PRIVATE
};
let T = mono_q("T", instanceof(Type));
let U = mono_q("U", instanceof(Type));
@ -119,32 +117,38 @@ impl Context {
U,
)
.quantify();
self.register_builtin_py_impl("dir!", t_dir, Immutable, vis, Some("dir"));
self.register_builtin_py_impl("dir!", t_dir, Immutable, vis.clone(), Some("dir"));
self.register_py_builtin("print!", t_print, Some("print"), 81);
self.register_builtin_py_impl("id!", t_id, Immutable, vis, Some("id"));
self.register_builtin_py_impl("input!", t_input, Immutable, vis, Some("input"));
self.register_builtin_py_impl("globals!", t_globals, Immutable, vis, Some("globals"));
self.register_builtin_py_impl("locals!", t_locals, Immutable, vis, Some("locals"));
self.register_builtin_py_impl("next!", t_next, Immutable, vis, Some("next"));
self.register_builtin_py_impl("id!", t_id, Immutable, vis.clone(), Some("id"));
self.register_builtin_py_impl("input!", t_input, Immutable, vis.clone(), Some("input"));
self.register_builtin_py_impl(
"globals!",
t_globals,
Immutable,
vis.clone(),
Some("globals"),
);
self.register_builtin_py_impl("locals!", t_locals, Immutable, vis.clone(), Some("locals"));
self.register_builtin_py_impl("next!", t_next, Immutable, vis.clone(), Some("next"));
self.register_py_builtin("open!", t_open, Some("open"), 198);
let name = if cfg!(feature = "py_compatible") {
"if"
} else {
"if__"
};
self.register_builtin_py_impl("if!", t_if, Immutable, vis, Some(name));
self.register_builtin_py_impl("if!", t_if, Immutable, vis.clone(), Some(name));
let name = if cfg!(feature = "py_compatible") {
"for"
} else {
"for__"
};
self.register_builtin_py_impl("for!", t_for, Immutable, vis, Some(name));
self.register_builtin_py_impl("for!", t_for, Immutable, vis.clone(), Some(name));
let name = if cfg!(feature = "py_compatible") {
"while"
} else {
"while__"
};
self.register_builtin_py_impl("while!", t_while, Immutable, vis, Some(name));
self.register_builtin_py_impl("while!", t_while, Immutable, vis.clone(), Some(name));
let name = if cfg!(feature = "py_compatible") {
"with"
} else {

View file

@ -1,11 +1,10 @@
#[allow(unused_imports)]
use erg_common::log;
use erg_common::vis::Visibility;
use crate::ty::constructors::*;
use crate::ty::typaram::TyParam;
use crate::ty::value::ValueObj;
use crate::ty::Type;
use crate::ty::{Type, Visibility};
use ParamSpec as PS;
use Type::*;
@ -14,7 +13,6 @@ use crate::context::{ConstTemplate, Context, DefaultInfo, ParamSpec};
use crate::varinfo::Mutability;
use DefaultInfo::*;
use Mutability::*;
use Visibility::*;
impl Context {
/// see std/prelude.er
@ -24,9 +22,9 @@ impl Context {
// push_subtype_boundなどはユーザー定義APIの型境界決定のために使用する
pub(super) fn init_builtin_traits(&mut self) {
let vis = if cfg!(feature = "py_compatible") {
Public
Visibility::BUILTIN_PUBLIC
} else {
Private
Visibility::BUILTIN_PRIVATE
};
let unpack = Self::builtin_mono_trait(UNPACK, 2);
let inheritable_type = Self::builtin_mono_trait(INHERITABLE_TYPE, 2);
@ -36,25 +34,35 @@ impl Context {
let immut_t = proj(Slf.clone(), IMMUT_TYPE);
let f_t = func(vec![kw(KW_OLD, immut_t.clone())], None, vec![], immut_t);
let t = pr1_met(ref_mut(Slf, None), f_t, NoneType).quantify();
mutable.register_builtin_erg_decl(PROC_UPDATE, t, Public);
mutable.register_builtin_erg_decl(PROC_UPDATE, t, Visibility::BUILTIN_PUBLIC);
// REVIEW: Immutatable?
let mut immutizable = Self::builtin_mono_trait(IMMUTIZABLE, 2);
immutizable.register_superclass(mono(MUTABLE), &mutable);
immutizable.register_builtin_erg_decl(IMMUT_TYPE, Type, Public);
immutizable.register_builtin_erg_decl(IMMUT_TYPE, Type, Visibility::BUILTIN_PUBLIC);
// REVIEW: Mutatable?
let mut mutizable = Self::builtin_mono_trait(MUTIZABLE, 2);
mutizable.register_builtin_erg_decl(MUTABLE_MUT_TYPE, Type, Public);
mutizable.register_builtin_erg_decl(MUTABLE_MUT_TYPE, Type, Visibility::BUILTIN_PUBLIC);
let pathlike = Self::builtin_mono_trait(PATH_LIKE, 2);
/* Readable */
let mut readable = Self::builtin_mono_trait(MUTABLE_READABLE, 2);
let Slf = mono_q(SELF, subtypeof(mono(MUTABLE_READABLE)));
let t_read = pr_met(ref_mut(Slf, None), vec![], None, vec![kw(KW_N, Int)], Str).quantify();
readable.register_builtin_py_decl(PROC_READ, t_read, Public, Some(FUNC_READ));
readable.register_builtin_py_decl(
PROC_READ,
t_read,
Visibility::BUILTIN_PUBLIC,
Some(FUNC_READ),
);
/* Writable */
let mut writable = Self::builtin_mono_trait(MUTABLE_WRITABLE, 2);
let Slf = mono_q(SELF, subtypeof(mono(MUTABLE_WRITABLE)));
let t_write = pr1_kw_met(ref_mut(Slf, None), kw("s", Str), Nat).quantify();
writable.register_builtin_py_decl(PROC_WRITE, t_write, Public, Some(FUNC_WRITE));
writable.register_builtin_py_decl(
PROC_WRITE,
t_write,
Visibility::BUILTIN_PUBLIC,
Some(FUNC_WRITE),
);
// TODO: Add required methods
let mut filelike = Self::builtin_mono_trait(FILE_LIKE, 2);
filelike.register_superclass(mono(READABLE), &readable);
@ -65,7 +73,12 @@ impl Context {
let mut show = Self::builtin_mono_trait(SHOW, 2);
let Slf = mono_q(SELF, subtypeof(mono(SHOW)));
let t_show = fn0_met(ref_(Slf), Str).quantify();
show.register_builtin_py_decl(TO_STR, t_show, Public, Some(FUNDAMENTAL_STR));
show.register_builtin_py_decl(
TO_STR,
t_show,
Visibility::BUILTIN_PUBLIC,
Some(FUNDAMENTAL_STR),
);
/* In */
let mut in_ = Self::builtin_poly_trait(IN, vec![PS::t_nd(TY_T)], 2);
let params = vec![PS::t_nd(TY_T)];
@ -75,7 +88,7 @@ impl Context {
let I = mono_q(TY_I, subtypeof(poly(IN, vec![ty_tp(T.clone())])));
in_.register_superclass(poly(INPUT, vec![ty_tp(T.clone())]), &input);
let op_t = fn1_met(T.clone(), I, Bool).quantify();
in_.register_builtin_erg_decl(OP_IN, op_t, Public);
in_.register_builtin_erg_decl(OP_IN, op_t, Visibility::BUILTIN_PUBLIC);
/* Eq */
// Erg does not have a trait equivalent to `PartialEq` in Rust
// This means, Erg's `Float` cannot be compared with other `Float`
@ -84,13 +97,13 @@ impl Context {
let Slf = mono_q(SELF, subtypeof(mono(EQ)));
// __eq__: |Self <: Eq| (self: Self, other: Self) -> Bool
let op_t = fn1_met(Slf.clone(), Slf, Bool).quantify();
eq.register_builtin_erg_decl(OP_EQ, op_t, Public);
eq.register_builtin_erg_decl(OP_EQ, op_t, Visibility::BUILTIN_PUBLIC);
/* Ord */
let mut ord = Self::builtin_mono_trait(ORD, 2);
ord.register_superclass(mono(EQ), &eq);
let Slf = mono_q(SELF, subtypeof(mono(ORD)));
let op_t = fn1_met(Slf.clone(), Slf, or(mono(ORDERING), NoneType)).quantify();
ord.register_builtin_erg_decl(OP_CMP, op_t, Public);
ord.register_builtin_erg_decl(OP_CMP, op_t, Visibility::BUILTIN_PUBLIC);
// FIXME: poly trait
/* Num */
let num = Self::builtin_mono_trait(NUM, 2);
@ -104,24 +117,29 @@ impl Context {
seq.register_superclass(poly(OUTPUT, vec![ty_tp(T.clone())]), &output);
let Slf = mono_q(SELF, subtypeof(poly(SEQ, vec![TyParam::erased(Type)])));
let t = fn0_met(Slf.clone(), Nat).quantify();
seq.register_builtin_erg_decl(FUNC_LEN, t, Public);
seq.register_builtin_erg_decl(FUNC_LEN, t, Visibility::BUILTIN_PUBLIC);
let t = fn1_met(Slf, Nat, T.clone()).quantify();
// Seq.get: |Self <: Seq(T)| Self.(Nat) -> T
seq.register_builtin_erg_decl(FUNC_GET, t, Public);
seq.register_builtin_erg_decl(FUNC_GET, t, Visibility::BUILTIN_PUBLIC);
/* Iterable */
let mut iterable = Self::builtin_poly_trait(ITERABLE, vec![PS::t_nd(TY_T)], 2);
iterable.register_superclass(poly(OUTPUT, vec![ty_tp(T.clone())]), &output);
let Slf = mono_q(SELF, subtypeof(poly(ITERABLE, vec![ty_tp(T.clone())])));
let t = fn0_met(Slf.clone(), proj(Slf, ITER)).quantify();
iterable.register_builtin_py_decl(FUNC_ITER, t, Public, Some(FUNDAMENTAL_ITER));
iterable.register_builtin_erg_decl(ITER, Type, Public);
iterable.register_builtin_py_decl(
FUNC_ITER,
t,
Visibility::BUILTIN_PUBLIC,
Some(FUNDAMENTAL_ITER),
);
iterable.register_builtin_erg_decl(ITER, Type, Visibility::BUILTIN_PUBLIC);
let mut context_manager = Self::builtin_mono_trait(CONTEXT_MANAGER, 2);
let Slf = mono_q(SELF, subtypeof(mono(CONTEXT_MANAGER)));
let t = fn0_met(Slf.clone(), NoneType).quantify();
context_manager.register_builtin_py_decl(
FUNDAMENTAL_ENTER,
t,
Public,
Visibility::BUILTIN_PUBLIC,
Some(FUNDAMENTAL_ENTER),
);
let t = fn_met(
@ -139,7 +157,7 @@ impl Context {
context_manager.register_builtin_py_decl(
FUNDAMENTAL_EXIT,
t,
Public,
Visibility::BUILTIN_PUBLIC,
Some(FUNDAMENTAL_EXIT),
);
let R = mono_q(TY_R, instanceof(Type));
@ -152,111 +170,141 @@ impl Context {
add.register_superclass(poly(OUTPUT, vec![ty_tp(R.clone())]), &output);
let Slf = mono_q(SELF, subtypeof(poly(ADD, ty_params.clone())));
let op_t = fn1_met(Slf.clone(), R.clone(), proj(Slf, OUTPUT)).quantify();
add.register_builtin_erg_decl(OP_ADD, op_t, Public);
add.register_builtin_erg_decl(OUTPUT, Type, Public);
add.register_builtin_erg_decl(OP_ADD, op_t, Visibility::BUILTIN_PUBLIC);
add.register_builtin_erg_decl(OUTPUT, Type, Visibility::BUILTIN_PUBLIC);
/* Sub */
let mut sub = Self::builtin_poly_trait(SUB, params.clone(), 2);
sub.register_superclass(poly(OUTPUT, vec![ty_tp(R.clone())]), &output);
let Slf = mono_q(SELF, subtypeof(poly(SUB, ty_params.clone())));
let op_t = fn1_met(Slf.clone(), R.clone(), proj(Slf, OUTPUT)).quantify();
sub.register_builtin_erg_decl(OP_SUB, op_t, Public);
sub.register_builtin_erg_decl(OUTPUT, Type, Public);
sub.register_builtin_erg_decl(OP_SUB, op_t, Visibility::BUILTIN_PUBLIC);
sub.register_builtin_erg_decl(OUTPUT, Type, Visibility::BUILTIN_PUBLIC);
/* Mul */
let mut mul = Self::builtin_poly_trait(MUL, params.clone(), 2);
mul.register_superclass(poly(OUTPUT, vec![ty_tp(R.clone())]), &output);
let Slf = mono_q(SELF, subtypeof(poly(MUL, ty_params.clone())));
let op_t = fn1_met(Slf.clone(), R.clone(), proj(Slf, OUTPUT)).quantify();
mul.register_builtin_erg_decl(OP_MUL, op_t, Public);
mul.register_builtin_erg_decl(OUTPUT, Type, Public);
mul.register_builtin_erg_decl(OP_MUL, op_t, Visibility::BUILTIN_PUBLIC);
mul.register_builtin_erg_decl(OUTPUT, Type, Visibility::BUILTIN_PUBLIC);
/* Div */
let mut div = Self::builtin_poly_trait(DIV, params.clone(), 2);
div.register_superclass(poly(OUTPUT, vec![ty_tp(R.clone())]), &output);
let Slf = mono_q(SELF, subtypeof(poly(DIV, ty_params.clone())));
let op_t = fn1_met(Slf.clone(), R.clone(), proj(Slf, OUTPUT)).quantify();
div.register_builtin_erg_decl(OP_DIV, op_t, Public);
div.register_builtin_erg_decl(OUTPUT, Type, Public);
div.register_builtin_erg_decl(OP_DIV, op_t, Visibility::BUILTIN_PUBLIC);
div.register_builtin_erg_decl(OUTPUT, Type, Visibility::BUILTIN_PUBLIC);
/* FloorDiv */
let mut floor_div = Self::builtin_poly_trait(FLOOR_DIV, params, 2);
floor_div.register_superclass(poly(OUTPUT, vec![ty_tp(R.clone())]), &output);
let Slf = mono_q(SELF, subtypeof(poly(FLOOR_DIV, ty_params.clone())));
let op_t = fn1_met(Slf.clone(), R, proj(Slf.clone(), OUTPUT)).quantify();
floor_div.register_builtin_erg_decl(OP_FLOOR_DIV, op_t, Public);
floor_div.register_builtin_erg_decl(OUTPUT, Type, Public);
floor_div.register_builtin_erg_decl(OP_FLOOR_DIV, op_t, Visibility::BUILTIN_PUBLIC);
floor_div.register_builtin_erg_decl(OUTPUT, Type, Visibility::BUILTIN_PUBLIC);
/* Pos */
let mut pos = Self::builtin_mono_trait(POS, 2);
let _Slf = mono_q(SELF, subtypeof(mono(POS)));
let op_t = fn0_met(_Slf.clone(), proj(_Slf, OUTPUT)).quantify();
pos.register_builtin_erg_decl(OP_POS, op_t, Public);
pos.register_builtin_erg_decl(OUTPUT, Type, Public);
pos.register_builtin_erg_decl(OP_POS, op_t, Visibility::BUILTIN_PUBLIC);
pos.register_builtin_erg_decl(OUTPUT, Type, Visibility::BUILTIN_PUBLIC);
/* Neg */
let mut neg = Self::builtin_mono_trait(NEG, 2);
let _Slf = mono_q(SELF, subtypeof(mono(NEG)));
let op_t = fn0_met(_Slf.clone(), proj(_Slf, OUTPUT)).quantify();
neg.register_builtin_erg_decl(OP_NEG, op_t, Public);
neg.register_builtin_erg_decl(OUTPUT, Type, Public);
self.register_builtin_type(mono(UNPACK), unpack, vis, Const, None);
neg.register_builtin_erg_decl(OP_NEG, op_t, Visibility::BUILTIN_PUBLIC);
neg.register_builtin_erg_decl(OUTPUT, Type, Visibility::BUILTIN_PUBLIC);
self.register_builtin_type(mono(UNPACK), unpack, vis.clone(), Const, None);
self.register_builtin_type(
mono(INHERITABLE_TYPE),
inheritable_type,
Private,
Visibility::BUILTIN_PRIVATE,
Const,
None,
);
self.register_builtin_type(mono(NAMED), named, vis, Const, None);
self.register_builtin_type(mono(MUTABLE), mutable, vis, Const, None);
self.register_builtin_type(mono(IMMUTIZABLE), immutizable, vis, Const, None);
self.register_builtin_type(mono(MUTIZABLE), mutizable, vis, Const, None);
self.register_builtin_type(mono(PATH_LIKE), pathlike, vis, Const, None);
self.register_builtin_type(mono(NAMED), named, vis.clone(), Const, None);
self.register_builtin_type(mono(MUTABLE), mutable, vis.clone(), Const, None);
self.register_builtin_type(mono(IMMUTIZABLE), immutizable, vis.clone(), Const, None);
self.register_builtin_type(mono(MUTIZABLE), mutizable, vis.clone(), Const, None);
self.register_builtin_type(mono(PATH_LIKE), pathlike, vis.clone(), Const, None);
self.register_builtin_type(
mono(MUTABLE_READABLE),
readable,
Private,
Visibility::BUILTIN_PRIVATE,
Const,
Some(READABLE),
);
self.register_builtin_type(
mono(MUTABLE_WRITABLE),
writable,
Private,
Visibility::BUILTIN_PRIVATE,
Const,
Some(WRITABLE),
);
self.register_builtin_type(mono(FILE_LIKE), filelike, vis, Const, None);
self.register_builtin_type(mono(MUTABLE_FILE_LIKE), filelike_mut, vis, Const, None);
self.register_builtin_type(mono(SHOW), show, vis, Const, None);
self.register_builtin_type(mono(FILE_LIKE), filelike, vis.clone(), Const, None);
self.register_builtin_type(
mono(MUTABLE_FILE_LIKE),
filelike_mut,
vis.clone(),
Const,
None,
);
self.register_builtin_type(mono(SHOW), show, vis.clone(), Const, None);
self.register_builtin_type(
poly(INPUT, vec![ty_tp(T.clone())]),
input,
Private,
Visibility::BUILTIN_PRIVATE,
Const,
None,
);
self.register_builtin_type(
poly(OUTPUT, vec![ty_tp(T.clone())]),
output,
Private,
Visibility::BUILTIN_PRIVATE,
Const,
None,
);
self.register_builtin_type(
poly(IN, vec![ty_tp(T.clone())]),
in_,
Visibility::BUILTIN_PRIVATE,
Const,
None,
);
self.register_builtin_type(mono(EQ), eq, vis.clone(), Const, None);
self.register_builtin_type(mono(ORD), ord, vis.clone(), Const, None);
self.register_builtin_type(mono(NUM), num, vis.clone(), Const, None);
self.register_builtin_type(
poly(SEQ, vec![ty_tp(T.clone())]),
seq,
Visibility::BUILTIN_PRIVATE,
Const,
None,
);
self.register_builtin_type(poly(IN, vec![ty_tp(T.clone())]), in_, Private, Const, None);
self.register_builtin_type(mono(EQ), eq, vis, Const, None);
self.register_builtin_type(mono(ORD), ord, vis, Const, None);
self.register_builtin_type(mono(NUM), num, vis, Const, None);
self.register_builtin_type(poly(SEQ, vec![ty_tp(T.clone())]), seq, Private, Const, None);
self.register_builtin_type(
poly(ITERABLE, vec![ty_tp(T)]),
iterable,
Private,
Visibility::BUILTIN_PRIVATE,
Const,
None,
);
self.register_builtin_type(mono(CONTEXT_MANAGER), context_manager, Private, Const, None);
self.register_builtin_type(poly(ADD, ty_params.clone()), add, vis, Const, None);
self.register_builtin_type(poly(SUB, ty_params.clone()), sub, vis, Const, None);
self.register_builtin_type(poly(MUL, ty_params.clone()), mul, vis, Const, None);
self.register_builtin_type(poly(DIV, ty_params.clone()), div, vis, Const, None);
self.register_builtin_type(poly(FLOOR_DIV, ty_params), floor_div, vis, Const, None);
self.register_builtin_type(mono(POS), pos, vis, Const, None);
self.register_builtin_type(
mono(CONTEXT_MANAGER),
context_manager,
Visibility::BUILTIN_PRIVATE,
Const,
None,
);
self.register_builtin_type(poly(ADD, ty_params.clone()), add, vis.clone(), Const, None);
self.register_builtin_type(poly(SUB, ty_params.clone()), sub, vis.clone(), Const, None);
self.register_builtin_type(poly(MUL, ty_params.clone()), mul, vis.clone(), Const, None);
self.register_builtin_type(poly(DIV, ty_params.clone()), div, vis.clone(), Const, None);
self.register_builtin_type(
poly(FLOOR_DIV, ty_params),
floor_div,
vis.clone(),
Const,
None,
);
self.register_builtin_type(mono(POS), pos, vis.clone(), Const, None);
self.register_builtin_type(mono(NEG), neg, vis, Const, None);
self.register_const_param_defaults(
ADD,

View file

@ -5,28 +5,27 @@ use std::path::{Path, PathBuf};
use erg_common::config::{ErgConfig, Input};
use erg_common::env::{erg_py_external_lib_path, erg_pystd_path, erg_std_path};
use erg_common::error::{ErrorCore, ErrorKind, Location, SubMessage};
use erg_common::levenshtein::get_similar_name;
use erg_common::levenshtein;
use erg_common::pathutil::add_postfix_foreach;
use erg_common::set::Set;
use erg_common::traits::{Locational, NoTypeDisplay, Stream};
use erg_common::vis::Visibility;
use erg_common::triple::Triple;
use erg_common::Str;
use erg_common::{
fmt_option, fmt_slice, log, normalize_path, option_enum_unwrap, set, switch_lang,
};
use Type::*;
use ast::VarName;
use erg_parser::ast::{self, Identifier};
use erg_parser::ast::{self, Identifier, VarName};
use erg_parser::token::Token;
use crate::ty::constructors::{anon, free_var, func, mono, poly, proc, proj, ref_, subr_t};
use crate::ty::free::Constraint;
use crate::ty::typaram::TyParam;
use crate::ty::value::{GenTypeObj, TypeObj, ValueObj};
use crate::ty::{HasType, ParamTy, SubrKind, SubrType, Type};
use crate::ty::{HasType, ParamTy, SubrKind, SubrType, Type, Visibility};
use Type::*;
use crate::context::instantiate::ConstTemplate;
use crate::context::instantiate_spec::ConstTemplate;
use crate::context::{Context, RegistrationMode, TraitImpl, TyVarCache, Variance};
use crate::error::{
binop_to_dname, readable_name, unaryop_to_dname, SingleTyCheckResult, TyCheckError,
@ -36,9 +35,8 @@ use crate::varinfo::{AbsLocation, Mutability, VarInfo, VarKind};
use crate::{feature_error, hir};
use crate::{unreachable_error, AccessKind};
use RegistrationMode::*;
use Visibility::*;
use super::instantiate::ParamKind;
use super::instantiate_spec::ParamKind;
use super::{ContextKind, MethodInfo};
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@ -105,7 +103,7 @@ impl Context {
pub fn get_singular_ctx_by_hir_expr(
&self,
obj: &hir::Expr,
namespace: &Str,
namespace: &Context,
) -> SingleTyCheckResult<&Context> {
match obj {
hir::Expr::Accessor(hir::Accessor::Ident(ident)) => {
@ -132,19 +130,22 @@ impl Context {
pub(crate) fn get_singular_ctx_by_ident(
&self,
ident: &ast::Identifier,
namespace: &Str,
namespace: &Context,
) -> SingleTyCheckResult<&Context> {
self.get_mod(ident.inspect())
.or_else(|| self.rec_local_get_type(ident.inspect()).map(|(_, ctx)| ctx))
.or_else(|| self.rec_get_patch(ident.inspect()))
.ok_or_else(|| {
TyCheckError::no_var_error(
let (similar_info, similar_name) =
self.get_similar_name_and_info(ident.inspect()).unzip();
TyCheckError::detailed_no_var_error(
self.cfg.input.clone(),
line!() as usize,
ident.loc(),
namespace.into(),
namespace.name.to_string(),
ident.inspect(),
self.get_similar_name(ident.inspect()),
similar_name,
similar_info,
)
})
}
@ -170,7 +171,7 @@ impl Context {
pub(crate) fn get_singular_ctx(
&self,
obj: &ast::Expr,
namespace: &Str,
namespace: &Context,
) -> SingleTyCheckResult<&Context> {
match obj {
ast::Expr::Accessor(ast::Accessor::Ident(ident)) => {
@ -342,16 +343,16 @@ impl Context {
ident: &Identifier,
acc_kind: AccessKind,
input: &Input,
namespace: &Str,
) -> SingleTyCheckResult<VarInfo> {
namespace: &Context,
) -> Triple<VarInfo, TyCheckError> {
if let Some(vi) = self.get_current_scope_var(&ident.name) {
match self.validate_visibility(ident, vi, input, namespace) {
Ok(()) => {
return Ok(vi.clone());
return Triple::Ok(vi.clone());
}
Err(err) => {
if !acc_kind.is_local() {
return Err(err);
return Triple::Err(err);
}
}
}
@ -359,21 +360,21 @@ impl Context {
.future_defined_locals
.get_key_value(&ident.inspect()[..])
{
return Err(TyCheckError::access_before_def_error(
return Triple::Err(TyCheckError::access_before_def_error(
input.clone(),
line!() as usize,
ident.loc(),
namespace.into(),
namespace.name.to_string(),
ident.inspect(),
name.ln_begin().unwrap_or(0),
self.get_similar_name(ident.inspect()),
));
} else if let Some((name, _vi)) = self.deleted_locals.get_key_value(&ident.inspect()[..]) {
return Err(TyCheckError::access_deleted_var_error(
return Triple::Err(TyCheckError::access_deleted_var_error(
input.clone(),
line!() as usize,
ident.loc(),
namespace.into(),
namespace.name.to_string(),
ident.inspect(),
name.ln_begin().unwrap_or(0),
self.get_similar_name(ident.inspect()),
@ -381,20 +382,22 @@ impl Context {
}
if acc_kind.is_local() {
if let Some(parent) = self.get_outer().or_else(|| self.get_builtins()) {
return match parent.rec_get_var_info(ident, acc_kind, input, namespace) {
Ok(vi) => Ok(vi),
Err(err) => Err(err),
};
return parent.rec_get_var_info(ident, acc_kind, input, namespace);
}
}
Err(TyCheckError::no_var_error(
/*
let (similar_info, similar_name) = self.get_similar_name_and_info(ident.inspect()).unzip();
Err(TyCheckError::detailed_no_var_error(
input.clone(),
line!() as usize,
ident.loc(),
namespace.into(),
ident.inspect(),
self.get_similar_name(ident.inspect()),
similar_name,
similar_info,
))
*/
Triple::None
}
pub(crate) fn rec_get_decl_info(
@ -402,8 +405,8 @@ impl Context {
ident: &Identifier,
acc_kind: AccessKind,
input: &Input,
namespace: &Str,
) -> SingleTyCheckResult<VarInfo> {
namespace: &Context,
) -> Triple<VarInfo, TyCheckError> {
if let Some(vi) = self
.decls
.get(&ident.inspect()[..])
@ -411,11 +414,11 @@ impl Context {
{
match self.validate_visibility(ident, vi, input, namespace) {
Ok(()) => {
return Ok(vi.clone());
return Triple::Ok(vi.clone());
}
Err(err) => {
if !acc_kind.is_local() {
return Err(err);
return Triple::Err(err);
}
}
}
@ -425,14 +428,15 @@ impl Context {
return parent.rec_get_decl_info(ident, acc_kind, input, namespace);
}
}
Err(TyCheckError::no_var_error(
/*Err(TyCheckError::no_var_error(
input.clone(),
line!() as usize,
ident.loc(),
namespace.into(),
ident.inspect(),
self.get_similar_name(ident.inspect()),
))
))*/
Triple::None
}
pub(crate) fn get_attr_info(
@ -440,51 +444,59 @@ impl Context {
obj: &hir::Expr,
ident: &Identifier,
input: &Input,
namespace: &Str,
) -> SingleTyCheckResult<VarInfo> {
namespace: &Context,
) -> Triple<VarInfo, TyCheckError> {
let self_t = obj.t();
let name = ident.name.token();
match self.get_attr_info_from_attributive(&self_t, ident, namespace) {
Ok(vi) => {
return Ok(vi);
match self.get_attr_info_from_attributive(&self_t, ident) {
Triple::Ok(vi) => {
return Triple::Ok(vi);
}
Err(e) if e.core.kind == ErrorKind::AttributeError => {}
Err(e) => {
return Err(e);
Triple::Err(e) => {
return Triple::Err(e);
}
_ => {}
}
if let Ok(singular_ctx) = self.get_singular_ctx_by_hir_expr(obj, namespace) {
match singular_ctx.rec_get_var_info(ident, AccessKind::Attr, input, namespace) {
Ok(vi) => {
return Ok(vi);
Triple::Ok(vi) => {
return Triple::Ok(vi);
}
Err(e) if e.core.kind == ErrorKind::NameError => {}
Err(e) => {
return Err(e);
Triple::Err(e) => {
return Triple::Err(e);
}
Triple::None => {}
}
}
match self.get_attr_from_nominal_t(obj, ident, input, namespace) {
Ok(vi) => {
Triple::Ok(vi) => {
if let Some(self_t) = vi.t.self_t() {
self.sub_unify(obj.ref_t(), self_t, obj, Some(&"self".into()))
.map_err(|mut e| e.remove(0))?;
}
return Ok(vi);
}
Err(e) if e.core.kind == ErrorKind::AttributeError => {}
match self
.sub_unify(obj.ref_t(), self_t, obj, Some(&"self".into()))
.map_err(|mut e| e.remove(0))
{
Ok(_) => {}
Err(e) => {
return Err(e);
return Triple::Err(e);
}
}
}
return Triple::Ok(vi);
}
Triple::Err(e) => {
return Triple::Err(e);
}
_ => {}
}
for patch in self.find_patches_of(obj.ref_t()) {
if let Some(vi) = patch
.locals
.get(ident.inspect())
.or_else(|| patch.decls.get(ident.inspect()))
{
self.validate_visibility(ident, vi, input, namespace)?;
return Ok(vi.clone());
return match self.validate_visibility(ident, vi, input, namespace) {
Ok(_) => Triple::Ok(vi.clone()),
Err(e) => Triple::Err(e),
};
}
for (_, methods_ctx) in patch.methods_list.iter() {
if let Some(vi) = methods_ctx
@ -492,12 +504,15 @@ impl Context {
.get(ident.inspect())
.or_else(|| methods_ctx.decls.get(ident.inspect()))
{
self.validate_visibility(ident, vi, input, namespace)?;
return Ok(vi.clone());
return match self.validate_visibility(ident, vi, input, namespace) {
Ok(_) => Triple::Ok(vi.clone()),
Err(e) => Triple::Err(e),
};
}
}
}
Err(TyCheckError::no_attr_error(
Triple::None
/*Err(TyCheckError::no_attr_error(
input.clone(),
line!() as usize,
name.loc(),
@ -505,7 +520,7 @@ impl Context {
&self_t,
name.inspect(),
self.get_similar_attr(&self_t, name.inspect()),
))
))*/
}
fn get_attr_from_nominal_t(
@ -513,39 +528,45 @@ impl Context {
obj: &hir::Expr,
ident: &Identifier,
input: &Input,
namespace: &Str,
) -> SingleTyCheckResult<VarInfo> {
namespace: &Context,
) -> Triple<VarInfo, TyCheckError> {
let self_t = obj.t();
if let Some(sups) = self.get_nominal_super_type_ctxs(&self_t) {
for ctx in sups {
match ctx.rec_get_var_info(ident, AccessKind::Attr, input, namespace) {
Ok(vi) => {
return Ok(vi);
Triple::Ok(vi) => {
return Triple::Ok(vi);
}
Err(e) if e.core.kind == ErrorKind::NameError => {}
Err(e) => {
return Err(e);
Triple::Err(e) => {
return Triple::Err(e);
}
_ => {}
}
// if self is a methods context
if let Some(ctx) = self.get_same_name_context(&ctx.name) {
match ctx.rec_get_var_info(ident, AccessKind::Method, input, namespace) {
Ok(vi) => {
return Ok(vi);
Triple::Ok(vi) => {
return Triple::Ok(vi);
}
Err(e) if e.core.kind == ErrorKind::NameError => {}
Err(e) => {
return Err(e);
Triple::Err(e) => {
return Triple::Err(e);
}
_ => {}
}
}
}
}
}
let coerced = self
let coerced = match self
.deref_tyvar(obj.t(), Variance::Covariant, &set! {}, &())
.map_err(|mut es| es.remove(0))?;
.map_err(|mut es| es.remove(0))
{
Ok(t) => t,
Err(e) => {
return Triple::Err(e);
}
};
if obj.ref_t() != &coerced {
for ctx in self.get_nominal_super_type_ctxs(&coerced).ok_or_else(|| {
let ctxs = match self.get_nominal_super_type_ctxs(&coerced).ok_or_else(|| {
TyCheckError::type_not_found(
self.cfg.input.clone(),
line!() as usize,
@ -553,31 +574,37 @@ impl Context {
self.caused_by(),
&coerced,
)
})? {
match ctx.rec_get_var_info(ident, AccessKind::Attr, input, namespace) {
Ok(vi) => {
obj.ref_t().coerce();
return Ok(vi);
}
Err(e) if e.core.kind == ErrorKind::NameError => {}
}) {
Ok(ctxs) => ctxs,
Err(e) => {
return Err(e);
return Triple::Err(e);
}
};
for ctx in ctxs {
match ctx.rec_get_var_info(ident, AccessKind::Attr, input, namespace) {
Triple::Ok(vi) => {
obj.ref_t().coerce();
return Triple::Ok(vi);
}
Triple::Err(e) => {
return Triple::Err(e);
}
_ => {}
}
if let Some(ctx) = self.get_same_name_context(&ctx.name) {
match ctx.rec_get_var_info(ident, AccessKind::Method, input, namespace) {
Ok(vi) => {
return Ok(vi);
Triple::Ok(vi) => {
return Triple::Ok(vi);
}
Err(e) if e.core.kind == ErrorKind::NameError => {}
Err(e) => {
return Err(e);
Triple::Err(e) => {
return Triple::Err(e);
}
_ => {}
}
}
}
}
}
Err(TyCheckError::no_attr_error(
/*Err(TyCheckError::no_attr_error(
self.cfg.input.clone(),
line!() as usize,
ident.loc(),
@ -585,7 +612,8 @@ impl Context {
&self_t,
ident.inspect(),
self.get_similar_attr(&self_t, ident.inspect()),
))
))*/
Triple::None
}
/// get type from given attributive type (Record).
@ -594,41 +622,43 @@ impl Context {
&self,
t: &Type,
ident: &Identifier,
namespace: &Str,
) -> SingleTyCheckResult<VarInfo> {
) -> Triple<VarInfo, TyCheckError> {
match t {
// (obj: Never).foo: Never
Type::Never => Ok(VarInfo::ILLEGAL.clone()),
Type::Never => Triple::Ok(VarInfo::ILLEGAL.clone()),
Type::FreeVar(fv) if fv.is_linked() => {
self.get_attr_info_from_attributive(&fv.crack(), ident, namespace)
self.get_attr_info_from_attributive(&fv.crack(), ident)
}
Type::FreeVar(fv) /* if fv.is_unbound() */ => {
let sup = fv.get_super().unwrap();
self.get_attr_info_from_attributive(&sup, ident, namespace)
self.get_attr_info_from_attributive(&sup, ident)
}
Type::Ref(t) => self.get_attr_info_from_attributive(t, ident, namespace),
Type::Ref(t) => self.get_attr_info_from_attributive(t, ident),
Type::RefMut { before, .. } => {
self.get_attr_info_from_attributive(before, ident, namespace)
self.get_attr_info_from_attributive(before, ident)
}
Type::Refinement(refine) => {
self.get_attr_info_from_attributive(&refine.t, ident, namespace)
self.get_attr_info_from_attributive(&refine.t, ident)
}
Type::Record(record) => {
if let Some(attr_t) = record.get(ident.inspect()) {
if let Some((field, attr_t)) = record.get_key_value(ident.inspect()) {
let muty = Mutability::from(&ident.inspect()[..]);
let vi = VarInfo::new(
attr_t.clone(),
muty,
Public,
Visibility::new(field.vis.clone(), Str::ever("<dummy>")),
VarKind::Builtin,
None,
None,
None,
AbsLocation::unknown(),
);
Ok(vi)
if let Err(err) = self.validate_visibility(ident, &vi, &self.cfg.input, self) {
return Triple::Err(err);
}
Triple::Ok(vi)
} else {
Err(TyCheckError::no_attr_error(
/*Err(TyCheckError::no_attr_error(
self.cfg.input.clone(),
line!() as usize,
ident.loc(),
@ -636,73 +666,12 @@ impl Context {
t,
ident.inspect(),
self.get_similar_attr(t, ident.inspect()),
))
}
}
Type::Structural(t) => self.get_attr_info_from_attributive(t, ident, namespace),
other => {
if let Some(v) = self.rec_get_const_obj(&other.local_name()) {
match v {
ValueObj::Type(TypeObj::Generated(gen)) => self
.get_gen_t_require_attr_t(gen, &ident.inspect()[..])
.map(|attr_t| {
let muty = Mutability::from(&ident.inspect()[..]);
VarInfo::new(
attr_t.clone(),
muty,
Public,
VarKind::Builtin,
None,
None,
None,
AbsLocation::unknown(),
)
})
.ok_or_else(|| {
TyCheckError::no_attr_error(
self.cfg.input.clone(),
line!() as usize,
ident.loc(),
namespace.into(),
t,
ident.inspect(),
self.get_similar_attr(t, ident.inspect()),
)
}),
ValueObj::Type(TypeObj::Builtin(_t)) => {
// FIXME:
Err(TyCheckError::no_attr_error(
self.cfg.input.clone(),
line!() as usize,
ident.loc(),
namespace.into(),
_t,
ident.inspect(),
self.get_similar_attr(_t, ident.inspect()),
))
}
_other => Err(TyCheckError::no_attr_error(
self.cfg.input.clone(),
line!() as usize,
ident.loc(),
namespace.into(),
t,
ident.inspect(),
self.get_similar_attr(t, ident.inspect()),
)),
}
} else {
Err(TyCheckError::no_attr_error(
self.cfg.input.clone(),
line!() as usize,
ident.loc(),
namespace.into(),
t,
ident.inspect(),
self.get_similar_attr(t, ident.inspect()),
))
))*/
Triple::None
}
}
Type::Structural(t) => self.get_attr_info_from_attributive(t, ident),
_other => Triple::None,
}
}
@ -712,7 +681,7 @@ impl Context {
obj: &hir::Expr,
attr_name: &Option<Identifier>,
input: &Input,
namespace: &Str,
namespace: &Context,
) -> SingleTyCheckResult<VarInfo> {
if obj.ref_t() == Type::FAILURE {
// (...Obj) -> Failure
@ -750,11 +719,17 @@ impl Context {
obj: &hir::Expr,
attr_name: &Identifier,
input: &Input,
namespace: &Str,
namespace: &Context,
) -> SingleTyCheckResult<VarInfo> {
if let Ok(vi) = self.get_attr_info_from_attributive(obj.ref_t(), attr_name, namespace) {
match self.get_attr_info_from_attributive(obj.ref_t(), attr_name) {
Triple::Ok(vi) => {
return Ok(vi);
}
Triple::Err(e) => {
return Err(e);
}
_ => {}
}
for ctx in self
.get_nominal_super_type_ctxs(obj.ref_t())
.ok_or_else(|| {
@ -787,13 +762,13 @@ impl Context {
}
if let Some(ctx) = self.get_same_name_context(&ctx.name) {
match ctx.rec_get_var_info(attr_name, AccessKind::Method, input, namespace) {
Ok(t) => {
Triple::Ok(t) => {
return Ok(t);
}
Err(e) if e.core.kind == ErrorKind::NameError => {}
Err(e) => {
Triple::Err(e) => {
return Err(e);
}
Triple::None => {}
}
}
}
@ -820,7 +795,7 @@ impl Context {
self.cfg.input.clone(),
line!() as usize,
attr_name.loc(),
namespace.into(),
namespace.name.to_string(),
obj.qual_name().unwrap_or("?"),
obj.ref_t(),
attr_name.inspect(),
@ -863,7 +838,7 @@ impl Context {
self.cfg.input.clone(),
line!() as usize,
attr_name.loc(),
namespace.into(),
namespace.name.to_string(),
obj.ref_t(),
attr_name.inspect(),
self.get_similar_attr(obj.ref_t(), attr_name.inspect()),
@ -875,34 +850,19 @@ impl Context {
ident: &Identifier,
vi: &VarInfo,
input: &Input,
namespace: &str,
namespace: &Context,
) -> SingleTyCheckResult<()> {
if ident.vis() != vi.vis {
Err(TyCheckError::visibility_error(
input.clone(),
line!() as usize,
ident.loc(),
self.caused_by(),
ident.inspect(),
vi.vis,
))
// check if the private variable is loaded from the other scope
} else if vi.vis.is_private()
&& &self.name[..] != "<builtins>"
&& &self.name[..] != namespace
&& !namespace.contains(&self.name[..])
{
log!(err "{namespace}/{}", self.name);
Err(TyCheckError::visibility_error(
input.clone(),
line!() as usize,
ident.loc(),
self.caused_by(),
ident.inspect(),
Private,
))
} else {
if vi.vis.compatible(&ident.acc_kind(), namespace) {
Ok(())
} else {
Err(TyCheckError::visibility_error(
input.clone(),
line!() as usize,
ident.loc(),
self.caused_by(),
ident.inspect(),
vi.vis.clone(),
))
}
}
@ -931,18 +891,20 @@ impl Context {
op: &Token,
args: &[hir::PosArg],
input: &Input,
namespace: &Str,
namespace: &Context,
) -> TyCheckResult<VarInfo> {
erg_common::debug_power_assert!(args.len() == 2);
let cont = binop_to_dname(op.inspect());
// not a `Token::from_str(op.kind, cont)` because ops are defined as symbols
let symbol = Token::symbol(cont);
let t = self.rec_get_var_info(
&Identifier::new(None, VarName::new(symbol.clone())),
let t = self
.rec_get_var_info(
&Identifier::private_from_token(symbol.clone()),
AccessKind::Name,
input,
namespace,
)?;
)
.unwrap_to_result()?;
let op = hir::Expr::Accessor(hir::Accessor::private(symbol, t));
self.get_call_t(&op, &None, args, &[], input, namespace)
.map_err(|(_, errs)| {
@ -952,7 +914,7 @@ impl Context {
let vi = op_ident.vi.clone();
let lhs = args[0].expr.clone();
let rhs = args[1].expr.clone();
let bin = hir::BinOp::new(op_ident.name.into_token(), lhs, rhs, vi);
let bin = hir::BinOp::new(op_ident.raw.name.into_token(), lhs, rhs, vi);
let errs = errs
.into_iter()
.map(|e| self.append_loc_info(e, bin.loc()))
@ -966,17 +928,19 @@ impl Context {
op: &Token,
args: &[hir::PosArg],
input: &Input,
namespace: &Str,
namespace: &Context,
) -> TyCheckResult<VarInfo> {
erg_common::debug_power_assert!(args.len() == 1);
let cont = unaryop_to_dname(op.inspect());
let symbol = Token::symbol(cont);
let vi = self.rec_get_var_info(
&Identifier::new(None, VarName::new(symbol.clone())),
let vi = self
.rec_get_var_info(
&Identifier::private_from_token(symbol.clone()),
AccessKind::Name,
input,
namespace,
)?;
)
.unwrap_to_result()?;
let op = hir::Expr::Accessor(hir::Accessor::private(symbol, vi));
self.get_call_t(&op, &None, args, &[], input, namespace)
.map_err(|(_, errs)| {
@ -985,7 +949,7 @@ impl Context {
};
let vi = op_ident.vi.clone();
let expr = args[0].expr.clone();
let unary = hir::UnaryOp::new(op_ident.name.into_token(), expr, vi);
let unary = hir::UnaryOp::new(op_ident.raw.name.into_token(), expr, vi);
let errs = errs
.into_iter()
.map(|e| self.append_loc_info(e, unary.loc()))
@ -1118,10 +1082,8 @@ impl Context {
if is_method {
obj.clone()
} else {
let attr = hir::Attribute::new(
obj.clone(),
hir::Identifier::bare(ident.dot.clone(), ident.name.clone()),
);
let attr =
hir::Attribute::new(obj.clone(), hir::Identifier::bare(ident.clone()));
hir::Expr::Accessor(hir::Accessor::Attr(attr))
}
} else {
@ -1272,10 +1234,10 @@ impl Context {
}
}
other => {
let one = self.get_singular_ctx_by_hir_expr(obj, &self.name).ok();
let one = self.get_singular_ctx_by_hir_expr(obj, self).ok();
let one = one
.zip(attr_name.as_ref())
.and_then(|(ctx, attr)| ctx.get_singular_ctx_by_ident(attr, &self.name).ok())
.and_then(|(ctx, attr)| ctx.get_singular_ctx_by_ident(attr, self).ok())
.or(one);
let two = obj
.qual_name()
@ -1354,7 +1316,8 @@ impl Context {
))
} else {
let unknown_arg_errors = unknown_args.into_iter().map(|arg| {
let similar = get_similar_name(subr_ty.param_names(), arg.keyword.inspect());
let similar =
levenshtein::get_similar_name(subr_ty.param_names(), arg.keyword.inspect());
TyCheckError::unexpected_kw_arg_error(
self.cfg.input.clone(),
line!() as usize,
@ -1550,7 +1513,8 @@ impl Context {
)
})?;
} else {
let similar = get_similar_name(subr_ty.param_names(), arg.keyword.inspect());
let similar =
levenshtein::get_similar_name(subr_ty.param_names(), arg.keyword.inspect());
return Err(TyCheckErrors::from(TyCheckError::unexpected_kw_arg_error(
self.cfg.input.clone(),
line!() as usize,
@ -1571,7 +1535,7 @@ impl Context {
pos_args: &[hir::PosArg],
kw_args: &[hir::KwArg],
input: &Input,
namespace: &Str,
namespace: &Context,
) -> Result<VarInfo, (Option<VarInfo>, TyCheckErrors)> {
if let hir::Expr::Accessor(hir::Accessor::Ident(local)) = obj {
if local.vis().is_private() {
@ -1692,18 +1656,27 @@ impl Context {
}
pub(crate) fn get_similar_name(&self, name: &str) -> Option<&str> {
get_similar_name(
levenshtein::get_similar_name(
self.dir().into_iter().map(|(vn, _)| &vn.inspect()[..]),
name,
)
}
pub(crate) fn get_similar_name_and_info(&self, name: &str) -> Option<(&VarInfo, &str)> {
levenshtein::get_similar_name_and_some(
self.dir()
.into_iter()
.map(|(vn, vi)| (vi, &vn.inspect()[..])),
name,
)
}
pub(crate) fn get_similar_attr_from_singular<'a>(
&'a self,
obj: &hir::Expr,
name: &str,
) -> Option<&'a str> {
if let Ok(ctx) = self.get_singular_ctx_by_hir_expr(obj, &self.name) {
if let Ok(ctx) = self.get_singular_ctx_by_hir_expr(obj, self) {
if let Some(name) = ctx.get_similar_name(name) {
return Some(name);
}
@ -1720,6 +1693,19 @@ impl Context {
None
}
pub(crate) fn get_similar_attr_and_info<'a>(
&'a self,
self_t: &'a Type,
name: &str,
) -> Option<(&'a VarInfo, &'a str)> {
for ctx in self.get_nominal_super_type_ctxs(self_t)? {
if let Some((vi, name)) = ctx.get_similar_name_and_info(name) {
return Some((vi, name));
}
}
None
}
// Returns what kind of variance the type has for each parameter Type.
// Invariant for types not specified
// selfが示す型が、各パラメータTypeに対してどのような変性Varianceを持つかを返す
@ -2166,7 +2152,7 @@ impl Context {
{
normalize_path(path)
} else {
todo!("{} {}", path.display(), add.display())
todo!("{} // {}", path.display(), add.display())
}
}
@ -2423,7 +2409,11 @@ impl Context {
}
}
fn get_gen_t_require_attr_t<'a>(&'a self, gen: &'a GenTypeObj, attr: &str) -> Option<&'a Type> {
fn _get_gen_t_require_attr_t<'a>(
&'a self,
gen: &'a GenTypeObj,
attr: &str,
) -> Option<&'a Type> {
match gen.base_or_sup().map(|req_sup| req_sup.typ()) {
Some(Type::Record(rec)) => {
if let Some(t) = rec.get(attr) {
@ -2433,7 +2423,7 @@ impl Context {
Some(other) => {
let obj = self.rec_get_const_obj(&other.local_name());
let obj = option_enum_unwrap!(obj, Some:(ValueObj::Type:(TypeObj::Generated:(_))))?;
if let Some(t) = self.get_gen_t_require_attr_t(obj, attr) {
if let Some(t) = self._get_gen_t_require_attr_t(obj, attr) {
return Some(t);
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -10,6 +10,7 @@ pub mod hint;
pub mod initialize;
pub mod inquire;
pub mod instantiate;
pub mod instantiate_spec;
pub mod register;
pub mod test;
pub mod unify;
@ -25,7 +26,6 @@ use erg_common::dict::Dict;
use erg_common::error::Location;
use erg_common::impl_display_from_debug;
use erg_common::traits::{Locational, Stream};
use erg_common::vis::Visibility;
use erg_common::Str;
use erg_common::{fmt_option, fn_name, get_hash, log};
@ -33,14 +33,14 @@ use ast::{DefId, DefKind, VarName};
use erg_parser::ast;
use erg_parser::token::Token;
use crate::context::instantiate::{ConstTemplate, TyVarCache};
use crate::context::instantiate::TyVarCache;
use crate::context::instantiate_spec::ConstTemplate;
use crate::error::{TyCheckError, TyCheckErrors};
use crate::module::{SharedCompilerResource, SharedModuleCache};
use crate::ty::value::ValueObj;
use crate::ty::{Predicate, Type};
use crate::ty::{Predicate, Type, Visibility, VisibilityModifier};
use crate::varinfo::{AbsLocation, Mutability, VarInfo, VarKind};
use Type::*;
use Visibility::*;
/// For implementing LSP or other IDE features
pub trait ContextProvider {
@ -511,12 +511,30 @@ impl Context {
if let Some(name) = param.name {
let kind = VarKind::parameter(id, param.is_var_params, param.default_info);
let muty = Mutability::from(name);
let vi = VarInfo::new(param.t, muty, Private, kind, None, None, None, param.loc);
let vi = VarInfo::new(
param.t,
muty,
Visibility::private(name),
kind,
None,
None,
None,
param.loc,
);
params_.push((Some(VarName::new(Token::static_symbol(name))), vi));
} else {
let kind = VarKind::parameter(id, param.is_var_params, param.default_info);
let muty = Mutability::Immutable;
let vi = VarInfo::new(param.t, muty, Private, kind, None, None, None, param.loc);
let vi = VarInfo::new(
param.t,
muty,
Visibility::private(name.clone()),
kind,
None,
None,
None,
param.loc,
);
params_.push((None, vi));
}
}
@ -925,7 +943,7 @@ impl Context {
&mut self,
name: &str,
kind: ContextKind,
vis: Visibility,
vis: VisibilityModifier,
tv_cache: Option<TyVarCache>,
) {
let name = if vis.is_public() {
@ -999,6 +1017,7 @@ impl Context {
}
}
/// enumerates all the variables/methods in the current context & super contexts.
fn type_dir(&self) -> Vec<(&VarName, &VarInfo)> {
let mut vars: Vec<_> = self
.locals

View file

@ -11,7 +11,7 @@ use erg_common::levenshtein::get_similar_name;
use erg_common::python_util::BUILTIN_PYTHON_MODS;
use erg_common::set::Set;
use erg_common::traits::{Locational, Stream};
use erg_common::vis::Visibility;
use erg_common::triple::Triple;
use erg_common::Str;
use erg_common::{enum_unwrap, get_hash, log, set};
@ -23,7 +23,7 @@ use crate::ty::constructors::{
};
use crate::ty::free::{Constraint, FreeKind, HasLevel};
use crate::ty::value::{GenTypeObj, TypeObj, ValueObj};
use crate::ty::{HasType, ParamTy, SubrType, Type};
use crate::ty::{HasType, ParamTy, SubrType, Type, Visibility};
use crate::build_hir::HIRBuilder;
use crate::context::{
@ -38,9 +38,9 @@ use crate::varinfo::{AbsLocation, Mutability, VarInfo, VarKind};
use crate::{feature_error, hir};
use Mutability::*;
use RegistrationMode::*;
use Visibility::*;
use super::instantiate::{ParamKind, TyVarCache};
use super::instantiate::TyVarCache;
use super::instantiate_spec::ParamKind;
/// format:
/// ```python
@ -133,7 +133,7 @@ impl Context {
}
other => unreachable!("{other}"),
};
let vis = ident.vis();
let vis = self.instantiate_vis_modifier(&ident.vis)?;
let kind = id.map_or(VarKind::Declared, VarKind::Defined);
let sig_t = self.instantiate_var_sig_t(sig.t_spec.as_ref(), PreRegister)?;
let py_name = if let ContextKind::PatchMethodDefs(_base) = &self.kind {
@ -153,7 +153,7 @@ impl Context {
let vi = VarInfo::new(
sig_t,
muty,
vis,
Visibility::new(vis, self.name.clone()),
kind,
None,
self.impl_of(),
@ -172,7 +172,7 @@ impl Context {
id: Option<DefId>,
) -> TyCheckResult<()> {
let name = sig.ident.inspect();
let vis = sig.ident.vis();
let vis = self.instantiate_vis_modifier(&sig.ident.vis)?;
let muty = Mutability::from(&name[..]);
let kind = id.map_or(VarKind::Declared, VarKind::Defined);
let comptime_decos = sig
@ -199,7 +199,7 @@ impl Context {
let vi = VarInfo::new(
t,
muty,
vis,
Visibility::new(vis, self.name.clone()),
kind,
Some(comptime_decos),
self.impl_of(),
@ -238,18 +238,19 @@ impl Context {
ast::VarPattern::Discard(_) => {
return Ok(VarInfo {
t: body_t.clone(),
..VarInfo::const_default()
..VarInfo::const_default_private()
});
}
_ => todo!(),
_ => unreachable!(),
};
let vis = self.instantiate_vis_modifier(&ident.vis)?;
// already defined as const
if sig.is_const() {
let vi = self.decls.remove(ident.inspect()).unwrap_or_else(|| {
VarInfo::new(
body_t.clone(),
Mutability::Const,
sig.vis(),
Visibility::new(vis, self.name.clone()),
VarKind::Declared,
None,
self.impl_of(),
@ -270,7 +271,6 @@ impl Context {
} else {
py_name
};
let vis = ident.vis();
let kind = if id.0 == 0 {
VarKind::Declared
} else {
@ -279,14 +279,14 @@ impl Context {
let vi = VarInfo::new(
body_t.clone(),
muty,
vis,
Visibility::new(vis, self.name.clone()),
kind,
None,
self.impl_of(),
py_name,
self.absolutize(ident.name.loc()),
);
log!(info "Registered {}::{}: {}", self.name, ident.name, vi);
log!(info "Registered {}{}: {}", self.name, ident, vi);
self.locals.insert(ident.name.clone(), vi.clone());
Ok(vi)
}
@ -300,9 +300,9 @@ impl Context {
kind: ParamKind,
) -> TyCheckResult<()> {
let vis = if cfg!(feature = "py_compatible") {
Public
Visibility::BUILTIN_PUBLIC
} else {
Private
Visibility::private(self.name.clone())
};
let default = kind.default_info();
let is_var_params = kind.is_var_params();
@ -622,6 +622,7 @@ impl Context {
self.locals.insert(sig.ident.name.clone(), vi.clone());
return Ok(vi);
}
let vis = self.instantiate_vis_modifier(&sig.ident.vis)?;
let muty = if sig.ident.is_const() {
Mutability::Const
} else {
@ -717,7 +718,7 @@ impl Context {
let vi = VarInfo::new(
found_t,
muty,
sig.ident.vis(),
Visibility::new(vis, self.name.clone()),
VarKind::Defined(id),
Some(comptime_decos),
self.impl_of(),
@ -746,6 +747,7 @@ impl Context {
return Ok(());
}
}
let vis = self.instantiate_vis_modifier(&ident.vis)?;
let muty = if ident.is_const() {
Mutability::Const
} else {
@ -765,7 +767,7 @@ impl Context {
let vi = VarInfo::new(
failure_t,
muty,
ident.vis(),
Visibility::new(vis, self.name.clone()),
VarKind::DoesNotExist,
Some(comptime_decos),
self.impl_of(),
@ -814,7 +816,7 @@ impl Context {
ast::Signature::Subr(sig) => {
if sig.is_const() {
let tv_cache = self.instantiate_ty_bounds(&sig.bounds, PreRegister)?;
let vis = def.sig.vis();
let vis = self.instantiate_vis_modifier(sig.vis())?;
self.grow(__name__, ContextKind::Proc, vis, Some(tv_cache));
let (obj, const_t) = match self.eval_const_block(&def.body.block) {
Ok(obj) => (obj.clone(), v_enum(set! {obj})),
@ -852,7 +854,8 @@ impl Context {
ast::Signature::Var(sig) => {
if sig.is_const() {
let kind = ContextKind::from(def.def_kind());
self.grow(__name__, kind, sig.vis(), None);
let vis = self.instantiate_vis_modifier(sig.vis())?;
self.grow(__name__, kind, vis, None);
let (obj, const_t) = match self.eval_const_block(&def.body.block) {
Ok(obj) => (obj.clone(), v_enum(set! {obj})),
Err(errs) => {
@ -1048,7 +1051,8 @@ impl Context {
ident: &Identifier,
obj: ValueObj,
) -> CompileResult<()> {
if self.rec_get_const_obj(ident.inspect()).is_some() && ident.vis().is_private() {
let vis = self.instantiate_vis_modifier(&ident.vis)?;
if self.rec_get_const_obj(ident.inspect()).is_some() && vis.is_private() {
Err(CompileErrors::from(CompileError::reassign_error(
self.cfg.input.clone(),
line!() as usize,
@ -1068,7 +1072,7 @@ impl Context {
let vi = VarInfo::new(
v_enum(set! {other.clone()}),
Const,
ident.vis(),
Visibility::new(vis, self.name.clone()),
VarKind::Defined(id),
None,
self.impl_of(),
@ -1111,6 +1115,7 @@ impl Context {
field.clone(),
t.clone(),
self.impl_of(),
ctx.name.clone(),
);
ctx.decls.insert(varname, vi);
}
@ -1120,7 +1125,7 @@ impl Context {
"base",
other.typ().clone(),
Immutable,
Private,
Visibility::BUILTIN_PRIVATE,
None,
)?;
}
@ -1133,12 +1138,18 @@ impl Context {
"__new__",
new_t.clone(),
Immutable,
Private,
Visibility::BUILTIN_PRIVATE,
Some("__call__".into()),
)?;
// 必要なら、ユーザーが独自に上書きする
// users can override this if necessary
methods.register_auto_impl("new", new_t, Immutable, Public, None)?;
methods.register_auto_impl(
"new",
new_t,
Immutable,
Visibility::BUILTIN_PUBLIC,
None,
)?;
ctx.methods_list
.push((ClassDefType::Simple(gen.typ().clone()), methods));
self.register_gen_mono_type(ident, gen, ctx, Const)
@ -1189,6 +1200,7 @@ impl Context {
field.clone(),
t.clone(),
self.impl_of(),
ctx.name.clone(),
);
ctx.decls.insert(varname, vi);
}
@ -1202,11 +1214,17 @@ impl Context {
"__new__",
new_t.clone(),
Immutable,
Private,
Visibility::BUILTIN_PRIVATE,
Some("__call__".into()),
)?;
// 必要なら、ユーザーが独自に上書きする
methods.register_auto_impl("new", new_t, Immutable, Public, None)?;
methods.register_auto_impl(
"new",
new_t,
Immutable,
Visibility::BUILTIN_PUBLIC,
None,
)?;
ctx.methods_list
.push((ClassDefType::Simple(gen.typ().clone()), methods));
self.register_gen_mono_type(ident, gen, ctx, Const)
@ -1242,7 +1260,12 @@ impl Context {
);
let Some(TypeObj::Builtin(Type::Record(req))) = gen.base_or_sup() else { todo!("{gen}") };
for (field, t) in req.iter() {
let vi = VarInfo::instance_attr(field.clone(), t.clone(), self.impl_of());
let vi = VarInfo::instance_attr(
field.clone(),
t.clone(),
self.impl_of(),
ctx.name.clone(),
);
ctx.decls
.insert(VarName::from_str(field.symbol.clone()), vi);
}
@ -1273,8 +1296,12 @@ impl Context {
);
if let Some(additional) = additional {
for (field, t) in additional.iter() {
let vi =
VarInfo::instance_attr(field.clone(), t.clone(), self.impl_of());
let vi = VarInfo::instance_attr(
field.clone(),
t.clone(),
self.impl_of(),
ctx.name.clone(),
);
ctx.decls
.insert(VarName::from_str(field.symbol.clone()), vi);
}
@ -1330,6 +1357,7 @@ impl Context {
}
pub(crate) fn register_type_alias(&mut self, ident: &Identifier, t: Type) -> CompileResult<()> {
let vis = self.instantiate_vis_modifier(&ident.vis)?;
if self.mono_types.contains_key(ident.inspect()) {
Err(CompileErrors::from(CompileError::reassign_error(
self.cfg.input.clone(),
@ -1338,7 +1366,7 @@ impl Context {
self.caused_by(),
ident.inspect(),
)))
} else if self.rec_get_const_obj(ident.inspect()).is_some() && ident.vis().is_private() {
} else if self.rec_get_const_obj(ident.inspect()).is_some() && vis.is_private() {
// TODO: display where defined
Err(CompileErrors::from(CompileError::reassign_error(
self.cfg.input.clone(),
@ -1354,7 +1382,7 @@ impl Context {
let vi = VarInfo::new(
Type::Type,
muty,
ident.vis(),
Visibility::new(vis, self.name.clone()),
VarKind::Defined(id),
None,
self.impl_of(),
@ -1376,6 +1404,7 @@ impl Context {
ctx: Self,
muty: Mutability,
) -> CompileResult<()> {
let vis = self.instantiate_vis_modifier(&ident.vis)?;
// FIXME: recursive search
if self.mono_types.contains_key(ident.inspect()) {
Err(CompileErrors::from(CompileError::reassign_error(
@ -1385,7 +1414,7 @@ impl Context {
self.caused_by(),
ident.inspect(),
)))
} else if self.rec_get_const_obj(ident.inspect()).is_some() && ident.vis().is_private() {
} else if self.rec_get_const_obj(ident.inspect()).is_some() && vis.is_private() {
Err(CompileErrors::from(CompileError::reassign_error(
self.cfg.input.clone(),
line!() as usize,
@ -1401,7 +1430,7 @@ impl Context {
let vi = VarInfo::new(
meta_t,
muty,
ident.vis(),
Visibility::new(vis, self.name.clone()),
VarKind::Defined(id),
None,
self.impl_of(),
@ -1454,6 +1483,7 @@ impl Context {
ctx: Self,
muty: Mutability,
) -> CompileResult<()> {
let vis = self.instantiate_vis_modifier(&ident.vis)?;
// FIXME: recursive search
if self.patches.contains_key(ident.inspect()) {
Err(CompileErrors::from(CompileError::reassign_error(
@ -1463,7 +1493,7 @@ impl Context {
self.caused_by(),
ident.inspect(),
)))
} else if self.rec_get_const_obj(ident.inspect()).is_some() && ident.vis().is_private() {
} else if self.rec_get_const_obj(ident.inspect()).is_some() && vis.is_private() {
Err(CompileErrors::from(CompileError::reassign_error(
self.cfg.input.clone(),
line!() as usize,
@ -1481,7 +1511,7 @@ impl Context {
VarInfo::new(
meta_t,
muty,
ident.vis(),
Visibility::new(vis, self.name.clone()),
VarKind::Defined(id),
None,
self.impl_of(),
@ -1758,7 +1788,7 @@ impl Context {
)))
} else if self.locals.get(ident.inspect()).is_some() {
let vi = self.locals.remove(ident.inspect()).unwrap();
self.deleted_locals.insert(ident.name.clone(), vi);
self.deleted_locals.insert(ident.raw.name.clone(), vi);
Ok(())
} else {
Err(TyCheckErrors::from(TyCheckError::no_var_error(
@ -1831,7 +1861,7 @@ impl Context {
#[allow(clippy::single_match)]
match acc {
hir::Accessor::Ident(ident) => {
if let Some(vi) = self.get_mut_current_scope_var(&ident.name) {
if let Some(vi) = self.get_mut_current_scope_var(&ident.raw.name) {
vi.t = t;
} else {
return Err(TyCheckErrors::from(TyCheckError::feature_error(
@ -1850,22 +1880,22 @@ impl Context {
}
pub(crate) fn inc_ref_simple_typespec(&self, simple: &SimpleTypeSpec) {
if let Ok(vi) = self.rec_get_var_info(
if let Triple::Ok(vi) = self.rec_get_var_info(
&simple.ident,
crate::compile::AccessKind::Name,
&self.cfg.input,
&self.name,
self,
) {
self.inc_ref(&vi, &simple.ident.name);
}
}
pub(crate) fn inc_ref_const_local(&self, local: &ConstIdentifier) {
if let Ok(vi) = self.rec_get_var_info(
if let Triple::Ok(vi) = self.rec_get_var_info(
local,
crate::compile::AccessKind::Name,
&self.cfg.input,
&self.name,
self,
) {
self.inc_ref(&vi, &local.name);
}

View file

@ -9,7 +9,7 @@ use crate::lower::ASTLowerer;
use crate::ty::constructors::mono;
use crate::ty::free::HasLevel;
use crate::ty::value::{GenTypeObj, TypeObj};
use crate::ty::{HasType, Type};
use crate::ty::{HasType, Type, Visibility};
use crate::compile::AccessKind;
use crate::context::RegistrationMode;
@ -73,7 +73,7 @@ impl ASTLowerer {
.assign_var_sig(&sig, found_body_t, id, py_name.clone())?;
}
// FIXME: Identifier::new should be used
let mut ident = hir::Identifier::bare(ident.dot.clone(), ident.name.clone());
let mut ident = hir::Identifier::bare(ident.clone());
ident.vi.t = found_body_t.clone();
ident.vi.py_name = py_name;
let sig = hir::VarSignature::new(ident, sig.t_spec);
@ -127,20 +127,15 @@ impl ASTLowerer {
let vi = self
.module
.context
.rec_get_var_info(
&ident,
AccessKind::Name,
self.input(),
&self.module.context.name,
)
.rec_get_var_info(&ident, AccessKind::Name, self.input(), &self.module.context)
.unwrap_or(VarInfo::default());
let ident = hir::Identifier::new(ident.dot, ident.name, None, vi);
let ident = hir::Identifier::new(ident, None, vi);
let acc = hir::Accessor::Ident(ident);
Ok(acc)
}
ast::Accessor::Attr(attr) => {
let obj = self.fake_lower_expr(*attr.obj)?;
let ident = hir::Identifier::bare(attr.ident.dot, attr.ident.name);
let ident = hir::Identifier::bare(attr.ident);
Ok(obj.attr(ident))
}
other => Err(LowerErrors::from(LowerError::declare_error(
@ -177,9 +172,7 @@ impl ASTLowerer {
fn fake_lower_call(&self, call: ast::Call) -> LowerResult<hir::Call> {
let obj = self.fake_lower_expr(*call.obj)?;
let attr_name = call
.attr_name
.map(|ident| hir::Identifier::bare(ident.dot, ident.name));
let attr_name = call.attr_name.map(hir::Identifier::bare);
let args = self.fake_lower_args(call.args)?;
Ok(hir::Call::new(obj, attr_name, args))
}
@ -247,12 +240,12 @@ impl ASTLowerer {
match sig {
ast::Signature::Var(var) => {
let ident = var.ident().unwrap().clone();
let ident = hir::Identifier::bare(ident.dot, ident.name);
let ident = hir::Identifier::bare(ident);
let sig = hir::VarSignature::new(ident, var.t_spec);
Ok(hir::Signature::Var(sig))
}
ast::Signature::Subr(subr) => {
let ident = hir::Identifier::bare(subr.ident.dot, subr.ident.name);
let ident = hir::Identifier::bare(subr.ident);
let params = self.fake_lower_params(subr.params)?;
let sig = hir::SubrSignature::new(ident, subr.bounds, params, subr.return_t_spec);
Ok(hir::Signature::Subr(sig))
@ -454,19 +447,19 @@ impl ASTLowerer {
self.declare_subtype(&ident, &t)?;
}
let muty = Mutability::from(&ident.inspect()[..]);
let vis = ident.vis();
let vis = self.module.context.instantiate_vis_modifier(&ident.vis)?;
let py_name = Str::rc(ident.inspect().trim_end_matches('!'));
let vi = VarInfo::new(
t,
muty,
vis,
Visibility::new(vis, self.module.context.name.clone()),
VarKind::Declared,
None,
None,
Some(py_name),
self.module.context.absolutize(ident.loc()),
);
let ident = hir::Identifier::new(ident.dot, ident.name, None, vi);
let ident = hir::Identifier::new(ident, None, vi);
let t_spec_expr = self.fake_lower_expr(*tasc.t_spec.t_spec_as_expr)?;
let t_spec = hir::TypeSpecWithOp::new(
tasc.t_spec.op,
@ -488,11 +481,10 @@ impl ASTLowerer {
RegistrationMode::Normal,
false,
)?;
let namespace = self.module.context.name.clone();
let ctx = self
.module
.context
.get_mut_singular_ctx(attr.obj.as_ref(), &namespace)?;
.get_mut_singular_ctx(attr.obj.as_ref(), &self.module.context.name.clone())?;
ctx.assign_var_sig(
&ast::VarSignature::new(ast::VarPattern::Ident(attr.ident.clone()), None),
&t,
@ -501,19 +493,22 @@ impl ASTLowerer {
)?;
let obj = self.fake_lower_expr(*attr.obj)?;
let muty = Mutability::from(&attr.ident.inspect()[..]);
let vis = attr.ident.vis();
let vis = self
.module
.context
.instantiate_vis_modifier(&attr.ident.vis)?;
let py_name = Str::rc(attr.ident.inspect().trim_end_matches('!'));
let vi = VarInfo::new(
t,
muty,
vis,
Visibility::new(vis, self.module.context.name.clone()),
VarKind::Declared,
None,
None,
Some(py_name),
self.module.context.absolutize(attr.ident.loc()),
);
let ident = hir::Identifier::new(attr.ident.dot, attr.ident.name, None, vi);
let ident = hir::Identifier::new(attr.ident, None, vi);
let attr = obj.attr_expr(ident);
let t_spec_expr = self.fake_lower_expr(*tasc.t_spec.t_spec_as_expr)?;
let t_spec = hir::TypeSpecWithOp::new(
@ -544,10 +539,11 @@ impl ASTLowerer {
return Ok(());
}
if ident.is_const() {
let vis = self.module.context.instantiate_vis_modifier(&ident.vis)?;
let vi = VarInfo::new(
t.clone(),
Mutability::Const,
ident.vis(),
Visibility::new(vis, self.module.context.name.clone()),
VarKind::Declared,
None,
None,

View file

@ -5,15 +5,12 @@
use erg_common::config::ErgConfig;
use erg_common::log;
use erg_common::traits::{Locational, Stream};
use erg_common::vis::Visibility;
use erg_common::Str;
use erg_parser::token::TokenKind;
use Visibility::*;
use crate::ty::HasType;
use crate::error::{EffectError, EffectErrors};
use crate::hir::{Array, Def, Dict, Expr, Params, Set, Signature, Tuple, HIR};
use crate::ty::{HasType, Visibility};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
enum BlockKind {
@ -36,7 +33,7 @@ use BlockKind::*;
#[derive(Debug)]
pub struct SideEffectChecker {
cfg: ErgConfig,
path_stack: Vec<(Str, Visibility)>,
path_stack: Vec<Visibility>,
block_stack: Vec<BlockKind>,
errs: EffectErrors,
}
@ -52,13 +49,11 @@ impl SideEffectChecker {
}
fn full_path(&self) -> String {
self.path_stack
.iter()
.fold(String::new(), |acc, (path, vis)| {
self.path_stack.iter().fold(String::new(), |acc, vis| {
if vis.is_public() {
acc + "." + &path[..]
acc + "." + &vis.def_namespace[..]
} else {
acc + "::" + &path[..]
acc + "::" + &vis.def_namespace[..]
}
})
}
@ -85,7 +80,7 @@ impl SideEffectChecker {
}
pub fn check(mut self, hir: HIR) -> Result<HIR, (HIR, EffectErrors)> {
self.path_stack.push((hir.name.clone(), Private));
self.path_stack.push(Visibility::private(hir.name.clone()));
self.block_stack.push(Module);
log!(info "the side-effects checking process has started.{RESET}");
// At the top level, there is no problem with side effects, only check for purity violations.
@ -150,7 +145,8 @@ impl SideEffectChecker {
}
},
Expr::Record(rec) => {
self.path_stack.push((Str::ever("<record>"), Private));
self.path_stack
.push(Visibility::private(Str::ever("<record>")));
self.block_stack.push(Instant);
for attr in rec.attrs.iter() {
self.check_def(attr);
@ -184,10 +180,12 @@ impl SideEffectChecker {
Expr::Lambda(lambda) => {
let is_proc = lambda.is_procedural();
if is_proc {
self.path_stack.push((Str::ever("<lambda!>"), Private));
self.path_stack
.push(Visibility::private(Str::ever("<lambda!>")));
self.block_stack.push(Proc);
} else {
self.path_stack.push((Str::ever("<lambda>"), Private));
self.path_stack
.push(Visibility::private(Str::ever("<lambda>")));
self.block_stack.push(Func);
}
lambda.body.iter().for_each(|chunk| self.check_expr(chunk));
@ -244,10 +242,7 @@ impl SideEffectChecker {
}
fn check_def(&mut self, def: &Def) {
let name_and_vis = match &def.sig {
Signature::Var(var) => (var.inspect().clone(), var.vis()),
Signature::Subr(subr) => (subr.ident.inspect().clone(), subr.ident.vis()),
};
let name_and_vis = Visibility::new(def.sig.vis().clone(), def.sig.inspect().clone());
self.path_stack.push(name_and_vis);
let is_procedural = def.sig.is_procedural();
let is_subr = def.sig.is_subr();
@ -360,7 +355,8 @@ impl SideEffectChecker {
}
},
Expr::Record(record) => {
self.path_stack.push((Str::ever("<record>"), Private));
self.path_stack
.push(Visibility::private(Str::ever("<record>")));
self.block_stack.push(Instant);
for attr in record.attrs.iter() {
self.check_def(attr);
@ -433,10 +429,12 @@ impl SideEffectChecker {
Expr::Lambda(lambda) => {
let is_proc = lambda.is_procedural();
if is_proc {
self.path_stack.push((Str::ever("<lambda!>"), Private));
self.path_stack
.push(Visibility::private(Str::ever("<lambda!>")));
self.block_stack.push(Proc);
} else {
self.path_stack.push((Str::ever("<lambda>"), Private));
self.path_stack
.push(Visibility::private(Str::ever("<lambda>")));
self.block_stack.push(Func);
}
self.check_params(&lambda.params);

View file

@ -2,12 +2,12 @@ use erg_common::config::Input;
use erg_common::error::{ErrorCore, ErrorKind::*, Location, SubMessage};
use erg_common::style::{StyledStr, StyledString, StyledStrings, Stylize};
use erg_common::traits::Locational;
use erg_common::vis::Visibility;
use erg_common::{switch_lang, Str};
use crate::error::*;
use crate::hir::{Expr, Identifier};
use crate::ty::{HasType, Type};
use crate::ty::{HasType, Type, Visibility};
use crate::varinfo::VarInfo;
pub type LowerError = CompileError;
pub type LowerWarning = LowerError;
@ -196,7 +196,47 @@ impl LowerError {
"english" => format!("exists a similar name variable: {n}"),
)
});
let found = StyledString::new(name, Some(ERR), Some(ATTR));
let found = name.with_color_and_attr(ERR, ATTR);
Self::new(
ErrorCore::new(
vec![SubMessage::ambiguous_new(loc, vec![], hint)],
switch_lang!(
"japanese" => format!("{found}という変数は定義されていません"),
"simplified_chinese" => format!("{found}未定义"),
"traditional_chinese" => format!("{found}未定義"),
"english" => format!("{found} is not defined"),
),
errno,
NameError,
loc,
),
input,
caused_by,
)
}
/// TODO: replace `no_var_error` with this function
pub fn detailed_no_var_error(
input: Input,
errno: usize,
loc: Location,
caused_by: String,
name: &str,
similar_name: Option<&str>,
similar_info: Option<&VarInfo>,
) -> Self {
let name = readable_name(name);
let hint = similar_name.map(|n| {
let vis = similar_info.map_or("".into(), |vi| vi.vis.modifier.display());
let n = n.with_color_and_attr(HINT, ATTR);
switch_lang!(
"japanese" => format!("似た名前の{vis}変数があります: {n}"),
"simplified_chinese" => format!("存在相同名称{vis}变量: {n}"),
"traditional_chinese" => format!("存在相同名稱{vis}變量: {n}"),
"english" => format!("exists a similar name {vis} variable: {n}"),
)
});
let found = name.with_color_and_attr(ERR, ATTR);
Self::new(
ErrorCore::new(
vec![SubMessage::ambiguous_new(loc, vec![], hint)],
@ -226,7 +266,7 @@ impl LowerError {
) -> Self {
let name = readable_name(name);
let hint = similar_name.map(|n| {
let n = StyledStr::new(n, Some(HINT), Some(ATTR));
let n = n.with_color_and_attr(HINT, ATTR);
switch_lang!(
"japanese" => format!("似た名前の変数があります: {n}"),
"simplified_chinese" => format!("存在相同名称变量: {n}"),
@ -234,7 +274,7 @@ impl LowerError {
"english" => format!("exists a similar name variable: {n}"),
)
});
let found = StyledString::new(name, Some(ERR), Some(ATTR));
let found = name.with_color_and_attr(ERR, ATTR);
Self::new(
ErrorCore::new(
vec![SubMessage::ambiguous_new(loc, vec![], hint)],
@ -264,7 +304,7 @@ impl LowerError {
) -> Self {
let name = readable_name(name);
let hint = similar_name.map(|n| {
let n = StyledStr::new(n, Some(HINT), Some(ATTR));
let n = n.with_color_and_attr(HINT, ATTR);
switch_lang!(
"japanese" => format!("似た名前の変数があります: {n}"),
"simplified_chinese" => format!("存在相同名称变量: {n}"),
@ -272,7 +312,7 @@ impl LowerError {
"english" => format!("exists a similar name variable: {n}"),
)
});
let found = StyledString::new(name, Some(ERR), Some(ATTR));
let found = name.with_color_and_attr(ERR, ATTR);
Self::new(
ErrorCore::new(
vec![SubMessage::ambiguous_new(loc, vec![], hint)],
@ -396,6 +436,45 @@ impl LowerError {
)
}
#[allow(clippy::too_many_arguments)]
pub fn detailed_no_attr_error(
input: Input,
errno: usize,
loc: Location,
caused_by: String,
obj_t: &Type,
name: &str,
similar_name: Option<&str>,
similar_info: Option<&VarInfo>,
) -> Self {
let hint = similar_name.map(|n| {
let vis = similar_info.map_or("".into(), |vi| vi.vis.modifier.display());
switch_lang!(
"japanese" => format!("似た名前の{vis}属性があります: {n}"),
"simplified_chinese" => format!("具有相同名称的{vis}属性: {n}"),
"traditional_chinese" => format!("具有相同名稱的{vis}屬性: {n}"),
"english" => format!("has a similar name {vis} attribute: {n}"),
)
});
let found = StyledString::new(name, Some(ERR), Some(ATTR));
Self::new(
ErrorCore::new(
vec![SubMessage::ambiguous_new(loc, vec![], hint)],
switch_lang!(
"japanese" => format!("{obj_t}型オブジェクトに{found}という属性はありません"),
"simplified_chinese" => format!("{obj_t}对象没有属性{found}"),
"traditional_chinese" => format!("{obj_t}對像沒有屬性{found}"),
"english" => format!("{obj_t} object has no attribute {found}"),
),
errno,
AttributeError,
loc,
),
input,
caused_by,
)
}
#[allow(clippy::too_many_arguments)]
pub fn singular_no_attr_error(
input: Input,
@ -510,21 +589,7 @@ impl LowerError {
name: &str,
vis: Visibility,
) -> Self {
let visibility = if vis.is_private() {
switch_lang!(
"japanese" => "非公開",
"simplified_chinese" => "私有",
"traditional_chinese" => "私有",
"english" => "private",
)
} else {
switch_lang!(
"japanese" => "公開",
"simplified_chinese" => "公有",
"traditional_chinese" => "公有",
"english" => "public",
)
};
let visibility = vis.modifier.display();
let found = StyledString::new(readable_name(name), Some(ERR), Some(ATTR));
Self::new(
ErrorCore::new(

View file

@ -520,7 +520,7 @@ mod test {
varinfo::{AbsLocation, VarInfo},
};
use erg_common::{config::Input, error::Location};
use erg_parser::ast::VarName;
use erg_parser::ast::{VarName, VisModifierSpec};
// These Erg codes are not correct grammar.
// This test make sure sub_msg and hint are displayed correctly.
@ -704,19 +704,17 @@ mod test {
errors.push(err);
let input = Input::pipe("ambiguous type error".to_string());
let expr = Identifier::new(
Some(erg_parser::token::Token {
kind: erg_parser::token::TokenKind::EOF,
content: "expr_content".into(),
lineno: 1,
col_begin: 1,
}),
let raw = erg_parser::ast::Identifier::new(
VisModifierSpec::Private,
VarName::from_str("variable_name".into()),
);
let expr = Identifier::new(
raw,
None,
VarInfo::new(
Type::Nat,
crate::varinfo::Mutability::Const,
erg_common::vis::Visibility::Private,
crate::ty::Visibility::DUMMY_PRIVATE,
crate::varinfo::VarKind::Builtin,
None,
None,
@ -759,7 +757,7 @@ mod test {
let input = Input::pipe("visibility error".to_string());
let loc = Location::Line(1);
let vis = erg_common::vis::Visibility::Private;
let vis = crate::ty::Visibility::DUMMY_PRIVATE;
let err =
TyCheckError::visibility_error(input, errno, loc, caused_by.to_string(), name, vis);
errors.push(err);

View file

@ -6,7 +6,6 @@ use erg_common::error::Location;
#[allow(unused_imports)]
use erg_common::log;
use erg_common::traits::{Locational, NestedDisplay, NoTypeDisplay, Stream};
use erg_common::vis::{Field, Visibility};
use erg_common::Str;
use erg_common::{
enum_unwrap, fmt_option, fmt_vec, impl_display_for_enum, impl_display_from_nested,
@ -23,7 +22,7 @@ use erg_parser::token::{Token, TokenKind, DOT};
use crate::ty::constructors::{array_t, dict_t, set_t, tuple_t};
use crate::ty::typaram::TyParam;
use crate::ty::value::{GenTypeObj, ValueObj};
use crate::ty::{HasType, Type};
use crate::ty::{Field, HasType, Type, VisibilityModifier};
use crate::context::eval::type_from_token_kind;
use crate::error::readable_name;
@ -381,22 +380,14 @@ impl Args {
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Identifier {
pub dot: Option<Token>,
pub name: VarName,
pub raw: ast::Identifier,
pub qual_name: Option<Str>,
pub vi: VarInfo,
}
impl NestedDisplay for Identifier {
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
match &self.dot {
Some(_dot) => {
write!(f, ".{}", self.name)?;
}
None => {
write!(f, "::{}", self.name)?;
}
}
write!(f, "{}", self.raw)?;
if let Some(qn) = &self.qual_name {
write!(f, "(qual_name: {qn})")?;
}
@ -409,10 +400,7 @@ impl NestedDisplay for Identifier {
impl NoTypeDisplay for Identifier {
fn to_string_notype(&self) -> String {
match &self.dot {
Some(_dot) => format!(".{}", self.name),
None => format!("::{}", self.name),
}
self.raw.to_string()
}
}
@ -439,56 +427,50 @@ impl HasType for Identifier {
impl Locational for Identifier {
fn loc(&self) -> Location {
if let Some(dot) = &self.dot {
Location::concat(dot, &self.name)
} else {
self.name.loc()
}
self.raw.loc()
}
}
impl From<&Identifier> for Field {
fn from(ident: &Identifier) -> Self {
Self::new(ident.vis(), ident.inspect().clone())
Self::new(ident.vis().clone(), ident.inspect().clone())
}
}
impl Identifier {
pub const fn new(
dot: Option<Token>,
name: VarName,
qual_name: Option<Str>,
vi: VarInfo,
) -> Self {
Self {
dot,
name,
qual_name,
vi,
}
pub const fn new(raw: ast::Identifier, qual_name: Option<Str>, vi: VarInfo) -> Self {
Self { raw, qual_name, vi }
}
pub fn public(name: &'static str) -> Self {
Self::bare(
Some(Token::from_str(TokenKind::Dot, ".")),
VarName::from_static(name),
)
let ident = ast::Identifier::public_from_token(
Token::from_str(TokenKind::Dot, "."),
Token::static_symbol(name),
);
Self::bare(ident)
}
pub fn private(name: &'static str) -> Self {
Self::bare(None, VarName::from_static(name))
let ident = ast::Identifier::private_from_token(Token::static_symbol(name));
Self::bare(ident)
}
pub fn private_with_line(name: Str, line: u32) -> Self {
Self::bare(None, VarName::from_str_and_line(name, line))
let ident = ast::Identifier::private_from_token(Token::symbol_with_line(&name, line));
Self::bare(ident)
}
pub fn public_with_line(dot: Token, name: Str, line: u32) -> Self {
Self::bare(Some(dot), VarName::from_str_and_line(name, line))
let ident = ast::Identifier::public_from_token(dot, Token::symbol_with_line(&name, line));
Self::bare(ident)
}
pub const fn bare(dot: Option<Token>, name: VarName) -> Self {
Self::new(dot, name, None, VarInfo::const_default())
pub const fn bare(ident: ast::Identifier) -> Self {
if ident.vis.is_public() {
Self::new(ident, None, VarInfo::const_default_public())
} else {
Self::new(ident, None, VarInfo::const_default_private())
}
}
pub fn is_py_api(&self) -> bool {
@ -496,18 +478,15 @@ impl Identifier {
}
pub fn is_const(&self) -> bool {
self.name.is_const()
self.raw.is_const()
}
pub const fn vis(&self) -> Visibility {
match &self.dot {
Some(_) => Visibility::Public,
None => Visibility::Private,
}
pub fn vis(&self) -> &VisibilityModifier {
&self.vi.vis.modifier
}
pub const fn inspect(&self) -> &Str {
self.name.inspect()
self.raw.inspect()
}
/// show dot + name (no qual_name & type)
@ -516,11 +495,11 @@ impl Identifier {
}
pub fn is_procedural(&self) -> bool {
self.name.is_procedural()
self.raw.is_procedural()
}
pub fn downcast(self) -> erg_parser::ast::Identifier {
erg_parser::ast::Identifier::new(self.dot, self.name)
pub fn downcast(self) -> ast::Identifier {
self.raw
}
}
@ -598,12 +577,20 @@ impl Accessor {
Self::Ident(Identifier::public_with_line(DOT, name, line))
}
pub const fn private(name: Token, vi: VarInfo) -> Self {
Self::Ident(Identifier::new(None, VarName::new(name), None, vi))
pub fn private(name: Token, vi: VarInfo) -> Self {
Self::Ident(Identifier::new(
ast::Identifier::private_from_token(name),
None,
vi,
))
}
pub fn public(name: Token, vi: VarInfo) -> Self {
Self::Ident(Identifier::new(Some(DOT), VarName::new(name), None, vi))
Self::Ident(Identifier::new(
ast::Identifier::public_from_token(DOT, name),
None,
vi,
))
}
pub fn attr(obj: Expr, ident: Identifier) -> Self {
@ -655,12 +642,12 @@ impl Accessor {
seps.remove(seps.len() - 1)
})
.or_else(|| {
let mut raw_parts = ident.name.inspect().split_with(&["'"]);
let mut raw_parts = ident.inspect().split_with(&["'"]);
// "'aaa'".split_with(&["'"]) == ["", "aaa", ""]
if raw_parts.len() == 3 || raw_parts.len() == 4 {
Some(raw_parts.remove(1))
} else {
Some(ident.name.inspect())
Some(ident.inspect())
}
}),
_ => None,
@ -1580,9 +1567,13 @@ impl VarSignature {
self.ident.inspect()
}
pub fn vis(&self) -> Visibility {
pub fn vis(&self) -> &VisibilityModifier {
self.ident.vis()
}
pub const fn name(&self) -> &VarName {
&self.ident.raw.name
}
}
/// Once the default_value is set to Some, all subsequent values must be Some
@ -1864,6 +1855,10 @@ impl SubrSignature {
pub fn is_procedural(&self) -> bool {
self.ident.is_procedural()
}
pub const fn name(&self) -> &VarName {
&self.ident.raw.name
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@ -1947,13 +1942,20 @@ impl Signature {
}
}
pub const fn vis(&self) -> Visibility {
pub fn vis(&self) -> &VisibilityModifier {
match self {
Self::Var(v) => v.ident.vis(),
Self::Subr(s) => s.ident.vis(),
}
}
pub const fn inspect(&self) -> &Str {
match self {
Self::Var(v) => v.ident.inspect(),
Self::Subr(s) => s.ident.inspect(),
}
}
pub const fn ident(&self) -> &Identifier {
match self {
Self::Var(v) => &v.ident,
@ -1975,6 +1977,13 @@ impl Signature {
}
}
pub const fn name(&self) -> &VarName {
match self {
Self::Var(v) => v.name(),
Self::Subr(s) => s.name(),
}
}
pub fn t_spec(&self) -> Option<&TypeSpec> {
match self {
Self::Var(v) => v.t_spec.as_ref(),

View file

@ -9,10 +9,10 @@ use erg_common::error::{Location, MultiErrorDisplay};
use erg_common::set;
use erg_common::set::Set;
use erg_common::traits::{Locational, NoTypeDisplay, Runnable, Stream};
use erg_common::vis::Visibility;
use erg_common::triple::Triple;
use erg_common::{fmt_option, fn_name, log, option_enum_unwrap, switch_lang, Str};
use erg_parser::ast;
use erg_parser::ast::{self, VisModifierSpec};
use erg_parser::ast::{OperationKind, TypeSpecWithOp, VarName, AST};
use erg_parser::build_ast::ASTBuilder;
use erg_parser::token::{Token, TokenKind};
@ -27,7 +27,7 @@ use crate::ty::constructors::{
use crate::ty::free::Constraint;
use crate::ty::typaram::TyParam;
use crate::ty::value::{GenTypeObj, TypeObj, ValueObj};
use crate::ty::{HasType, ParamTy, Type};
use crate::ty::{HasType, ParamTy, Type, VisibilityModifier};
use crate::context::{
ClassDefType, Context, ContextKind, ContextProvider, ModuleContext, RegistrationMode,
@ -43,7 +43,8 @@ use crate::reorder::Reorderer;
use crate::varinfo::{VarInfo, VarKind};
use crate::AccessKind;
use crate::{feature_error, unreachable_error};
use Visibility::*;
use VisibilityModifier::*;
/// Checks & infers types of an AST, and convert (lower) it into a HIR
#[derive(Debug)]
@ -624,14 +625,40 @@ impl ASTLowerer {
}
ast::Accessor::Attr(attr) => {
let obj = self.lower_expr(*attr.obj)?;
let vi = self.module.context.get_attr_info(
let vi = match self.module.context.get_attr_info(
&obj,
&attr.ident,
&self.cfg.input,
&self.module.context.name,
)?;
&self.module.context,
) {
Triple::Ok(vi) => vi,
Triple::Err(errs) => {
self.errs.push(errs);
VarInfo::ILLEGAL.clone()
}
Triple::None => {
let self_t = obj.t();
let (similar_info, similar_name) = self
.module
.context
.get_similar_attr_and_info(&self_t, attr.ident.inspect())
.unzip();
let err = LowerError::detailed_no_attr_error(
self.cfg.input.clone(),
line!() as usize,
attr.ident.loc(),
self.module.context.caused_by(),
&self_t,
attr.ident.inspect(),
similar_name,
similar_info,
);
self.errs.push(err);
VarInfo::ILLEGAL.clone()
}
};
self.inc_ref(&vi, &attr.ident.name);
let ident = hir::Identifier::new(attr.ident.dot, attr.ident.name, None, vi);
let ident = hir::Identifier::new(attr.ident, None, vi);
let acc = hir::Accessor::Attr(hir::Attribute::new(obj, ident));
Ok(acc)
}
@ -649,7 +676,7 @@ impl ASTLowerer {
fn lower_ident(&mut self, ident: ast::Identifier) -> LowerResult<hir::Identifier> {
// `match` is a special form, typing is magic
let (vi, __name__) = if ident.vis().is_private()
let (vi, __name__) = if ident.vis.is_private()
&& (&ident.inspect()[..] == "match" || &ident.inspect()[..] == "match!")
{
(
@ -660,22 +687,47 @@ impl ASTLowerer {
None,
)
} else {
(
self.module.context.rec_get_var_info(
let res = match self.module.context.rec_get_var_info(
&ident,
AccessKind::Name,
&self.cfg.input,
&self.module.context.name,
)?,
&self.module.context,
) {
Triple::Ok(vi) => vi,
Triple::Err(err) => {
self.errs.push(err);
VarInfo::ILLEGAL.clone()
}
Triple::None => {
let (similar_info, similar_name) = self
.module
.context
.get_similar_name_and_info(ident.inspect())
.unzip();
let err = LowerError::detailed_no_var_error(
self.cfg.input.clone(),
line!() as usize,
ident.loc(),
self.module.context.caused_by(),
ident.inspect(),
similar_name,
similar_info,
);
self.errs.push(err);
VarInfo::ILLEGAL.clone()
}
};
(
res,
self.module
.context
.get_singular_ctx_by_ident(&ident, &self.module.context.name)
.get_singular_ctx_by_ident(&ident, &self.module.context)
.ok()
.map(|ctx| ctx.name.clone()),
)
};
self.inc_ref(&vi, &ident.name);
let ident = hir::Identifier::new(ident.dot, ident.name, __name__, vi);
let ident = hir::Identifier::new(ident, __name__, vi);
Ok(ident)
}
@ -700,7 +752,7 @@ impl ASTLowerer {
let t = self
.module
.context
.get_binop_t(&bin.op, &args, &self.cfg.input, &self.module.context.name)
.get_binop_t(&bin.op, &args, &self.cfg.input, &self.module.context)
.unwrap_or_else(|errs| {
self.errs.extend(errs);
VarInfo::ILLEGAL.clone()
@ -724,7 +776,7 @@ impl ASTLowerer {
let t = self
.module
.context
.get_unaryop_t(&unary.op, &args, &self.cfg.input, &self.module.context.name)
.get_unaryop_t(&unary.op, &args, &self.cfg.input, &self.module.context)
.unwrap_or_else(|errs| {
self.errs.extend(errs);
VarInfo::ILLEGAL.clone()
@ -824,7 +876,7 @@ impl ASTLowerer {
&hir_args.pos_args,
&hir_args.kw_args,
&self.cfg.input,
&self.module.context.name,
&self.module.context,
) {
Ok(vi) => vi,
Err((vi, es)) => {
@ -835,12 +887,7 @@ impl ASTLowerer {
};
let attr_name = if let Some(attr_name) = call.attr_name {
self.inc_ref(&vi, &attr_name.name);
Some(hir::Identifier::new(
attr_name.dot,
attr_name.name,
None,
vi,
))
Some(hir::Identifier::new(attr_name, None, vi))
} else {
*obj.ref_mut_t() = vi.t;
None
@ -904,17 +951,17 @@ impl ASTLowerer {
let args = self.lower_record(pack.args)?;
let args = vec![hir::PosArg::new(hir::Expr::Record(args))];
let attr_name = ast::Identifier::new(
Some(Token::new(
VisModifierSpec::Public(Token::new(
TokenKind::Dot,
Str::ever("."),
pack.connector.lineno,
pack.connector.col_begin,
pack.connector.ln_begin().unwrap(),
pack.connector.col_begin().unwrap(),
)),
ast::VarName::new(Token::new(
TokenKind::Symbol,
Str::ever("new"),
pack.connector.lineno,
pack.connector.col_begin,
pack.connector.ln_begin().unwrap(),
pack.connector.col_begin().unwrap(),
)),
);
let vi = match self.module.context.get_call_t(
@ -923,7 +970,7 @@ impl ASTLowerer {
&args,
&[],
&self.cfg.input,
&self.module.context.name,
&self.module.context,
) {
Ok(vi) => vi,
Err((vi, errs)) => {
@ -932,7 +979,7 @@ impl ASTLowerer {
}
};
let args = hir::Args::pos_only(args, None);
let attr_name = hir::Identifier::new(attr_name.dot, attr_name.name, None, vi);
let attr_name = hir::Identifier::new(attr_name, None, vi);
Ok(hir::Call::new(class, Some(attr_name), args))
}
@ -1209,7 +1256,10 @@ impl ASTLowerer {
));
}
let kind = ContextKind::from(def.def_kind());
let vis = def.sig.vis();
let vis = self
.module
.context
.instantiate_vis_modifier(def.sig.vis())?;
let res = match def.sig {
ast::Signature::Subr(sig) => {
let tv_cache = self
@ -1263,7 +1313,7 @@ impl ASTLowerer {
let ident = match &sig.pat {
ast::VarPattern::Ident(ident) => ident.clone(),
ast::VarPattern::Discard(token) => {
ast::Identifier::new(None, VarName::new(token.clone()))
ast::Identifier::private_from_token(token.clone())
}
_ => unreachable!(),
};
@ -1287,7 +1337,7 @@ impl ASTLowerer {
body.id,
None,
)?;
let ident = hir::Identifier::new(ident.dot, ident.name, None, vi);
let ident = hir::Identifier::new(ident, None, vi);
let sig = hir::VarSignature::new(ident, sig.t_spec);
let body = hir::DefBody::new(body.op, block, body.id);
Ok(hir::Def::new(hir::Signature::Var(sig), body))
@ -1358,7 +1408,7 @@ impl ASTLowerer {
);
self.warns.push(warn);
}
let ident = hir::Identifier::new(sig.ident.dot, sig.ident.name, None, vi);
let ident = hir::Identifier::new(sig.ident, None, vi);
let sig =
hir::SubrSignature::new(ident, sig.bounds, params, sig.return_t_spec);
let body = hir::DefBody::new(body.op, block, body.id);
@ -1371,7 +1421,7 @@ impl ASTLowerer {
&Type::Failure,
)?;
self.errs.extend(errs);
let ident = hir::Identifier::new(sig.ident.dot, sig.ident.name, None, vi);
let ident = hir::Identifier::new(sig.ident, None, vi);
let sig =
hir::SubrSignature::new(ident, sig.bounds, params, sig.return_t_spec);
let block =
@ -1396,7 +1446,7 @@ impl ASTLowerer {
.unwrap()
.fake_subr_assign(&sig.ident, &sig.decorators, Type::Failure)?;
let block = self.lower_block(body.block)?;
let ident = hir::Identifier::bare(sig.ident.dot, sig.ident.name);
let ident = hir::Identifier::bare(sig.ident);
let sig = hir::SubrSignature::new(ident, sig.bounds, params, sig.return_t_spec);
let body = hir::DefBody::new(body.op, block, body.id);
Ok(hir::Def::new(hir::Signature::Subr(sig), body))
@ -1439,12 +1489,12 @@ impl ASTLowerer {
let kind = ContextKind::MethodDefs(impl_trait.as_ref().map(|(t, _)| t.clone()));
self.module
.context
.grow(&class.local_name(), kind, hir_def.sig.vis(), None);
.grow(&class.local_name(), kind, hir_def.sig.vis().clone(), None);
for attr in methods.attrs.iter_mut() {
match attr {
ast::ClassAttr::Def(def) => {
if methods.vis.is(TokenKind::Dot) {
def.sig.ident_mut().unwrap().dot = Some(Token::new(
if methods.vis.is_public() {
def.sig.ident_mut().unwrap().vis = VisModifierSpec::Public(Token::new(
TokenKind::Dot,
".",
def.sig.ln_begin().unwrap_or(0),
@ -1641,14 +1691,17 @@ impl ASTLowerer {
let mut hir_methods = hir::Block::empty();
for mut methods in class_def.methods_list.into_iter() {
let kind = ContextKind::PatchMethodDefs(base_t.clone());
self.module
.context
.grow(hir_def.sig.ident().inspect(), kind, hir_def.sig.vis(), None);
self.module.context.grow(
hir_def.sig.ident().inspect(),
kind,
hir_def.sig.vis().clone(),
None,
);
for attr in methods.attrs.iter_mut() {
match attr {
ast::ClassAttr::Def(def) => {
if methods.vis.is(TokenKind::Dot) {
def.sig.ident_mut().unwrap().dot = Some(Token::new(
if methods.vis.is_public() {
def.sig.ident_mut().unwrap().vis = VisModifierSpec::Public(Token::new(
TokenKind::Dot,
".",
def.sig.ln_begin().unwrap(),
@ -2037,7 +2090,7 @@ impl ASTLowerer {
let ctx = self
.module
.context
.get_singular_ctx_by_hir_expr(&expr, &self.module.context.name)?;
.get_singular_ctx_by_hir_expr(&expr, &self.module.context)?;
// REVIEW: need to use subtype_of?
if ctx.super_traits.iter().all(|trait_| trait_ != &spec_t)
&& ctx.super_classes.iter().all(|class| class != &spec_t)
@ -2089,14 +2142,30 @@ impl ASTLowerer {
&ident,
AccessKind::Name,
&self.cfg.input,
&self.module.context.name,
&self.module.context,
)
.or_else(|_e| {
.none_or_else(|| {
self.module.context.rec_get_var_info(
&ident,
AccessKind::Name,
&self.cfg.input,
&self.module.context.name,
&self.module.context,
)
})
.none_or_result(|| {
let (similar_info, similar_name) = self
.module
.context
.get_similar_name_and_info(ident.inspect())
.unzip();
LowerError::detailed_no_var_error(
self.cfg.input.clone(),
line!() as usize,
ident.loc(),
self.module.context.caused_by(),
ident.inspect(),
similar_name,
similar_info,
)
})?;
if is_instance_ascription {
@ -2119,10 +2188,10 @@ impl ASTLowerer {
let qual_name = self
.module
.context
.get_singular_ctx_by_ident(&ident, &self.module.context.name)
.get_singular_ctx_by_ident(&ident, &self.module.context)
.ok()
.map(|ctx| ctx.name.clone());
let ident = hir::Identifier::new(ident.dot, ident.name, qual_name, ident_vi);
let ident = hir::Identifier::new(ident, qual_name, ident_vi);
let expr = hir::Expr::Accessor(hir::Accessor::Ident(ident));
let t_spec = self.lower_type_spec_with_op(tasc.t_spec, spec_t)?;
Ok(expr.type_asc(t_spec))

View file

@ -6,13 +6,11 @@ use erg_common::error::Location;
use erg_common::set::Set;
use erg_common::style::colors::DEBUG_MAIN;
use erg_common::traits::{Locational, Stream};
use erg_common::vis::Visibility;
use erg_common::Str;
use erg_common::{impl_display_from_debug, log};
use erg_parser::ast::{ParamPattern, VarName};
use Visibility::*;
use crate::ty::{HasType, Ownership};
use crate::ty::{HasType, Ownership, Visibility};
use crate::error::{OwnershipError, OwnershipErrors};
use crate::hir::{self, Accessor, Array, Block, Def, Expr, Identifier, Signature, Tuple, HIR};
@ -39,7 +37,7 @@ impl_display_from_debug!(LocalVars);
#[derive(Debug)]
pub struct OwnershipChecker {
cfg: ErgConfig,
path_stack: Vec<(Str, Visibility)>,
path_stack: Vec<Visibility>,
dict: Dict<Str, LocalVars>,
errs: OwnershipErrors,
}
@ -55,13 +53,11 @@ impl OwnershipChecker {
}
fn full_path(&self) -> String {
self.path_stack
.iter()
.fold(String::new(), |acc, (path, vis)| {
self.path_stack.iter().fold(String::new(), |acc, vis| {
if vis.is_public() {
acc + "." + &path[..]
acc + "." + &vis.def_namespace[..]
} else {
acc + "::" + &path[..]
acc + "::" + &vis.def_namespace[..]
}
})
}
@ -71,7 +67,7 @@ impl OwnershipChecker {
pub fn check(&mut self, hir: HIR) -> Result<HIR, (HIR, OwnershipErrors)> {
log!(info "the ownership checking process has started.{RESET}");
if self.full_path() != ("::".to_string() + &hir.name[..]) {
self.path_stack.push((hir.name.clone(), Private));
self.path_stack.push(Visibility::private(hir.name.clone()));
self.dict
.insert(Str::from(self.full_path()), LocalVars::default());
}
@ -106,7 +102,8 @@ impl OwnershipChecker {
Signature::Var(var) => var.inspect().clone(),
Signature::Subr(subr) => subr.ident.inspect().clone(),
};
self.path_stack.push((name, def.sig.vis()));
self.path_stack
.push(Visibility::new(def.sig.vis().clone(), name));
self.dict
.insert(Str::from(self.full_path()), LocalVars::default());
if let Signature::Subr(subr) = &def.sig {
@ -247,7 +244,8 @@ impl OwnershipChecker {
},
// TODO: capturing
Expr::Lambda(lambda) => {
let name_and_vis = (Str::from(format!("<lambda_{}>", lambda.id)), Private);
let name_and_vis =
Visibility::private(Str::from(format!("<lambda_{}>", lambda.id)));
self.path_stack.push(name_and_vis);
self.dict
.insert(Str::from(self.full_path()), LocalVars::default());
@ -289,11 +287,11 @@ impl OwnershipChecker {
fn nth_outer_scope(&mut self, n: usize) -> &mut LocalVars {
let path = self.path_stack.iter().take(self.path_stack.len() - n).fold(
String::new(),
|acc, (path, vis)| {
|acc, vis| {
if vis.is_public() {
acc + "." + &path[..]
acc + "." + &vis.def_namespace[..]
} else {
acc + "::" + &path[..]
acc + "::" + &vis.def_namespace[..]
}
},
);

View file

@ -123,7 +123,6 @@ impl Reorderer {
/// ```
fn flatten_method_decls(&mut self, new: &mut Vec<Expr>, methods: Methods) {
let class = methods.class_as_expr.as_ref();
let vis = methods.vis();
for method in methods.attrs.into_iter() {
match method {
ClassAttr::Decl(decl) => {
@ -138,11 +137,7 @@ impl Reorderer {
));
continue;
};
let attr = if vis.is_public() {
Identifier::new(Some(methods.vis.clone()), ident.name)
} else {
Identifier::new(None, ident.name)
};
let attr = Identifier::new(methods.vis.clone(), ident.name);
let expr = class.clone().attr_expr(attr);
let decl = TypeAscription::new(expr, decl.t_spec);
new.push(Expr::TypeAscription(decl));

View file

@ -787,9 +787,9 @@ impl ScriptGenerator {
if let Some(py_name) = ident.vi.py_name {
return demangle(&py_name);
}
let name = ident.name.into_token().content.to_string();
let name = ident.inspect().to_string();
let name = replace_non_symbolic(name);
if ident.dot.is_some() {
if ident.vis().is_public() {
name
} else {
format!("{name}__")
@ -941,7 +941,7 @@ impl ScriptGenerator {
demangle(&patch_def.sig.ident().to_string_notype()),
demangle(&def.sig.ident().to_string_notype()),
);
def.sig.ident_mut().name = VarName::from_str(Str::from(name));
def.sig.ident_mut().raw.name = VarName::from_str(Str::from(name));
code += &" ".repeat(self.level);
code += &self.transpile_def(def);
code.push('\n');

View file

@ -11,6 +11,7 @@ pub mod free;
pub mod predicate;
pub mod typaram;
pub mod value;
pub mod vis;
use std::fmt;
use std::ops::{BitAnd, BitOr, Deref, Not, Range, RangeInclusive};
@ -22,7 +23,6 @@ use erg_common::fresh::fresh_varname;
use erg_common::log;
use erg_common::set::Set;
use erg_common::traits::{LimitedDisplay, StructuralEq};
use erg_common::vis::Field;
use erg_common::{enum_unwrap, fmt_option, ref_addr_eq, set, Str};
use erg_parser::token::TokenKind;
@ -35,6 +35,7 @@ use typaram::{IntervalOp, TyParam};
use value::value_set::*;
use value::ValueObj;
use value::ValueObj::{Inf, NegInf};
pub use vis::*;
/// cloneのコストがあるためなるべく.ref_tを使うようにすること
/// いくつかの構造体は直接Typeを保持していないので、その場合は.tを使う
@ -534,9 +535,6 @@ impl LimitedDisplay for RefinementType {
write!(f, "{rhs}, ")?;
}
write!(f, "}}")?;
if cfg!(feature = "debug") {
write!(f, "(<: {})", self.t)?;
}
Ok(())
} else {
write!(f, "{{{}: ", self.var)?;

View file

@ -7,7 +7,6 @@ use erg_common::dict::Dict;
use erg_common::set;
use erg_common::set::Set;
use erg_common::traits::{LimitedDisplay, StructuralEq};
use erg_common::vis::Field;
use erg_common::Str;
use erg_common::{dict, log};
@ -19,7 +18,7 @@ use super::free::{
};
use super::value::ValueObj;
use super::Type;
use super::{ConstSubr, ParamTy, UserConstSubr};
use super::{ConstSubr, Field, ParamTy, UserConstSubr};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(u8)]

View file

@ -16,7 +16,6 @@ use erg_common::python_util::PythonVersion;
use erg_common::serialize::*;
use erg_common::set::Set;
use erg_common::shared::Shared;
use erg_common::vis::Field;
use erg_common::{dict, fmt_iter, impl_display_from_debug, log, switch_lang};
use erg_common::{RcArray, Str};
use erg_parser::ast::{ConstArgs, ConstExpr};
@ -28,7 +27,7 @@ use self::value_set::inner_class;
use super::codeobj::CodeObj;
use super::constructors::{array_t, dict_t, mono, poly, refinement, set_t, tuple_t};
use super::typaram::TyParam;
use super::{ConstSubr, HasType, Predicate, Type};
use super::{ConstSubr, Field, HasType, Predicate, Type};
pub struct EvalValueError(pub Box<ErrorCore>);
@ -1311,11 +1310,11 @@ impl ValueObj {
}
Self::Subr(subr) => subr.as_type().map(TypeObj::Builtin),
Self::Array(elems) | Self::Tuple(elems) => {
erg_common::log!(err "as_type({})", erg_common::fmt_vec(elems));
log!(err "as_type({})", erg_common::fmt_vec(elems));
None
}
Self::Dict(elems) => {
erg_common::log!(err "as_type({elems})");
log!(err "as_type({elems})");
None
}
_other => None,

View file

@ -0,0 +1,233 @@
use std::borrow::Borrow;
use std::fmt;
#[allow(unused_imports)]
use erg_common::log;
use erg_common::set::Set;
use erg_common::{switch_lang, Str};
use erg_parser::ast::AccessModifier;
use crate::context::Context;
use crate::ty::Type;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum VisibilityModifier {
Public,
Private,
Restricted(Set<Str>),
SubtypeRestricted(Type),
}
impl fmt::Display for VisibilityModifier {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Private => write!(f, "::"),
Self::Public => write!(f, "."),
Self::Restricted(namespaces) => write!(f, "::[{namespaces}]"),
Self::SubtypeRestricted(typ) => write!(f, "::[<: {typ}]"),
}
}
}
impl VisibilityModifier {
pub const fn is_public(&self) -> bool {
matches!(self, Self::Public)
}
pub const fn is_private(&self) -> bool {
matches!(self, Self::Private)
}
pub const fn display_as_accessor(&self) -> &'static str {
match self {
Self::Public => ".",
Self::Private | Self::Restricted(_) | Self::SubtypeRestricted(_) => "::",
}
}
pub fn display(&self) -> String {
match self {
Self::Private => switch_lang!(
"japanese" => "非公開",
"simplified_chinese" => "私有",
"traditional_chinese" => "私有",
"english" => "private",
)
.into(),
Self::Public => switch_lang!(
"japanese" => "公開",
"simplified_chinese" => "公开",
"traditional_chinese" => "公開",
"english" => "public",
)
.into(),
Self::Restricted(namespaces) => switch_lang!(
"japanese" => format!("制限付き公開({namespaces}でのみ公開)"),
"simplified_chinese" => format!("受限公开({namespaces}中可见)"),
"traditional_chinese" => format!("受限公開({namespaces}中可見)"),
"english" => format!("restricted public ({namespaces} only)"),
),
Self::SubtypeRestricted(typ) => switch_lang!(
"japanese" => format!("制限付き公開({typ}の部分型でのみ公開)"),
"simplified_chinese" => format!("受限公开({typ}的子类型中可见)"),
"traditional_chinese" => format!("受限公開({typ}的子類型中可見)"),
"english" => format!("restricted public (subtypes of {typ} only)"),
),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Visibility {
pub modifier: VisibilityModifier,
pub def_namespace: Str,
}
impl Visibility {
pub const DUMMY_PRIVATE: Self = Self {
modifier: VisibilityModifier::Private,
def_namespace: Str::ever("<dummy>"),
};
pub const DUMMY_PUBLIC: Self = Self {
modifier: VisibilityModifier::Public,
def_namespace: Str::ever("<dummy>"),
};
pub const BUILTIN_PRIVATE: Self = Self {
modifier: VisibilityModifier::Private,
def_namespace: Str::ever("<builtins>"),
};
pub const BUILTIN_PUBLIC: Self = Self {
modifier: VisibilityModifier::Public,
def_namespace: Str::ever("<builtins>"),
};
pub const fn new(modifier: VisibilityModifier, def_namespace: Str) -> Self {
Self {
modifier,
def_namespace,
}
}
pub fn private<S: Into<Str>>(namespace: S) -> Self {
Self {
modifier: VisibilityModifier::Private,
def_namespace: namespace.into(),
}
}
pub const fn is_public(&self) -> bool {
self.modifier.is_public()
}
pub const fn is_private(&self) -> bool {
self.modifier.is_private()
}
pub fn compatible(&self, access: &AccessModifier, namespace: &Context) -> bool {
match (&self.modifier, access) {
(_, AccessModifier::Force) => true,
(VisibilityModifier::Public, AccessModifier::Auto | AccessModifier::Public) => true,
// compatible example:
// def_namespace: <module>::C
// namespace: <module>::C::f
(VisibilityModifier::Private, AccessModifier::Auto | AccessModifier::Private) => {
&self.def_namespace[..] == "<builtins>"
|| namespace.name.starts_with(&self.def_namespace[..])
}
(
VisibilityModifier::Restricted(namespaces),
AccessModifier::Auto | AccessModifier::Private,
) => {
namespace.name.starts_with(&self.def_namespace[..])
|| namespaces.contains(&namespace.name)
}
(
VisibilityModifier::SubtypeRestricted(typ),
AccessModifier::Auto | AccessModifier::Private,
) => {
namespace.name.starts_with(&self.def_namespace[..]) || {
let Some(space_t) = namespace.rec_get_self_t() else {
return false;
};
namespace.subtype_of(&space_t, typ)
}
}
_ => false,
}
}
}
/// same structure as `Identifier`, but only for Record fields.
#[derive(Debug, Clone, Eq)]
pub struct Field {
pub vis: VisibilityModifier,
pub symbol: Str,
}
impl PartialEq for Field {
fn eq(&self, other: &Self) -> bool {
self.symbol == other.symbol
}
}
impl std::hash::Hash for Field {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.symbol.hash(state);
}
}
impl fmt::Display for Field {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}{}", self.vis, self.symbol)
}
}
impl Borrow<str> for Field {
#[inline]
fn borrow(&self) -> &str {
&self.symbol[..]
}
}
impl Borrow<Str> for Field {
#[inline]
fn borrow(&self) -> &Str {
&self.symbol
}
}
impl Field {
pub const fn new(vis: VisibilityModifier, symbol: Str) -> Self {
Field { vis, symbol }
}
pub fn private(symbol: Str) -> Self {
Field::new(VisibilityModifier::Private, symbol)
}
pub fn public(symbol: Str) -> Self {
Field::new(VisibilityModifier::Public, symbol)
}
pub fn is_const(&self) -> bool {
self.symbol.starts_with(char::is_uppercase)
}
}
#[cfg(test)]
mod tests {
use super::*;
use erg_common::dict;
#[test]
fn test_std_key() {
let dict = dict! {Str::ever("a") => 1, Str::rc("b") => 2};
assert_eq!(dict.get("a"), Some(&1));
assert_eq!(dict.get("b"), Some(&2));
assert_eq!(dict.get(&Str::ever("b")), Some(&2));
assert_eq!(dict.get(&Str::rc("b")), Some(&2));
let dict = dict! {Field::private(Str::ever("a")) => 1, Field::public(Str::ever("b")) => 2};
assert_eq!(dict.get("a"), Some(&1));
assert_eq!(dict.get("b"), Some(&2));
}
}

View file

@ -3,14 +3,12 @@ use std::path::PathBuf;
use erg_common::error::Location;
use erg_common::set::Set;
use erg_common::vis::{Field, Visibility};
use erg_common::Str;
use Visibility::*;
use erg_parser::ast::DefId;
use crate::context::DefaultInfo;
use crate::ty::{HasType, Type};
use crate::ty::{Field, HasType, Type, Visibility};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(u8)]
@ -200,18 +198,31 @@ impl HasType for VarInfo {
impl Default for VarInfo {
fn default() -> Self {
Self::const_default()
Self::const_default_private()
}
}
impl VarInfo {
pub const ILLEGAL: &'static Self = &Self::const_default();
pub const ILLEGAL: &'static Self = &Self::const_default_private();
pub const fn const_default() -> Self {
pub const fn const_default_private() -> Self {
Self::new(
Type::Failure,
Immutable,
Private,
Visibility::DUMMY_PRIVATE,
VarKind::DoesNotExist,
None,
None,
None,
AbsLocation::unknown(),
)
}
pub const fn const_default_public() -> Self {
Self::new(
Type::Failure,
Immutable,
Visibility::DUMMY_PUBLIC,
VarKind::DoesNotExist,
None,
None,
@ -250,16 +261,25 @@ impl VarInfo {
}
}
pub fn nd_parameter(t: Type, def_loc: AbsLocation) -> Self {
pub fn nd_parameter(t: Type, def_loc: AbsLocation, namespace: Str) -> Self {
let kind = VarKind::Parameter {
def_id: DefId(0),
var: false,
default: DefaultInfo::NonDefault,
};
Self::new(t, Immutable, Private, kind, None, None, None, def_loc)
Self::new(
t,
Immutable,
Visibility::private(namespace),
kind,
None,
None,
None,
def_loc,
)
}
pub fn instance_attr(field: Field, t: Type, impl_of: Option<Type>) -> Self {
pub fn instance_attr(field: Field, t: Type, impl_of: Option<Type>, namespace: Str) -> Self {
let muty = if field.is_const() {
Mutability::Const
} else {
@ -269,7 +289,7 @@ impl VarInfo {
Self::new(
t,
muty,
field.vis,
Visibility::new(field.vis, namespace),
kind,
None,
impl_of,

View file

@ -7,7 +7,6 @@ use erg_common::error::Location;
use erg_common::set::Set as HashSet;
// use erg_common::dict::Dict as HashMap;
use erg_common::traits::{Locational, NestedDisplay, Stream};
use erg_common::vis::{Field, Visibility};
use erg_common::{
fmt_option, fmt_vec, impl_display_for_enum, impl_display_for_single_struct,
impl_display_from_nested, impl_displayable_stream_for_wrapper, impl_from_trait_for_enum,
@ -493,11 +492,31 @@ impl_locational_for_enum!(Accessor; Ident, Attr, TupleAttr, Subscr, TypeApp);
impl Accessor {
pub const fn local(symbol: Token) -> Self {
Self::Ident(Identifier::new(None, VarName::new(symbol)))
Self::Ident(Identifier::new(
VisModifierSpec::Private,
VarName::new(symbol),
))
}
pub const fn public(dot: Token, symbol: Token) -> Self {
Self::Ident(Identifier::new(Some(dot), VarName::new(symbol)))
Self::Ident(Identifier::new(
VisModifierSpec::Public(dot),
VarName::new(symbol),
))
}
pub const fn explicit_local(dcolon: Token, symbol: Token) -> Self {
Self::Ident(Identifier::new(
VisModifierSpec::ExplicitPrivate(dcolon),
VarName::new(symbol),
))
}
pub const fn restricted(rest: VisRestriction, symbol: Token) -> Self {
Self::Ident(Identifier::new(
VisModifierSpec::Restricted(rest),
VarName::new(symbol),
))
}
pub fn attr(obj: Expr, ident: Identifier) -> Self {
@ -1201,7 +1220,7 @@ impl Call {
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct DataPack {
pub class: Box<Expr>,
pub connector: Token,
pub connector: VisModifierSpec,
pub args: Record,
}
@ -1220,7 +1239,7 @@ impl Locational for DataPack {
}
impl DataPack {
pub fn new(class: Expr, connector: Token, args: Record) -> Self {
pub fn new(class: Expr, connector: VisModifierSpec, args: Record) -> Self {
Self {
class: Box::new(class),
connector,
@ -1392,7 +1411,10 @@ impl_locational_for_enum!(ConstAccessor; Local, SelfDot, Attr, TupleAttr, Subscr
impl ConstAccessor {
pub const fn local(symbol: Token) -> Self {
Self::Local(ConstIdentifier::new(None, VarName::new(symbol)))
Self::Local(ConstIdentifier::new(
VisModifierSpec::Private,
VarName::new(symbol),
))
}
pub fn attr(obj: ConstExpr, name: ConstIdentifier) -> Self {
@ -2655,18 +2677,108 @@ impl VarName {
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Namespaces(Vec<Accessor>);
impl_displayable_stream_for_wrapper!(Namespaces, Accessor);
impl NestedDisplay for Namespaces {
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
for (i, ns) in self.iter().enumerate() {
if i > 0 {
write!(f, ", ")?;
}
write!(f, "{ns}")?;
}
Ok(())
}
}
impl Locational for Namespaces {
fn loc(&self) -> Location {
Location::concat(self.first().unwrap(), self.last().unwrap())
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum VisRestriction {
Namespaces(Namespaces),
SubtypeOf(Box<TypeSpec>),
}
impl_locational_for_enum!(VisRestriction; Namespaces, SubtypeOf);
impl_display_from_nested!(VisRestriction);
impl NestedDisplay for VisRestriction {
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
match self {
Self::Namespaces(ns) => write!(f, "{ns}"),
Self::SubtypeOf(ty) => write!(f, "<: {ty}"),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum VisModifierSpec {
Private,
Auto,
Public(Token),
ExplicitPrivate(Token),
Restricted(VisRestriction),
}
impl NestedDisplay for VisModifierSpec {
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
match self {
Self::Private => Ok(()),
Self::Auto => write!(f, ":auto:"),
Self::Public(_token) => write!(f, "."),
Self::ExplicitPrivate(_token) => write!(f, "::"),
Self::Restricted(rest) => write!(f, "::[{rest}]"),
}
}
}
impl_display_from_nested!(VisModifierSpec);
impl Locational for VisModifierSpec {
fn loc(&self) -> Location {
match self {
Self::Private | Self::Auto => Location::Unknown,
Self::Public(token) => token.loc(),
Self::ExplicitPrivate(token) => token.loc(),
Self::Restricted(rest) => rest.loc(),
}
}
}
impl VisModifierSpec {
pub const fn is_public(&self) -> bool {
matches!(self, Self::Public(_))
}
pub const fn is_private(&self) -> bool {
matches!(self, Self::Private | Self::ExplicitPrivate(_))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum AccessModifier {
Private, // `::`
Public, // `.`
Auto, // record unpacking
Force, // can access any identifiers
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Identifier {
pub dot: Option<Token>,
pub vis: VisModifierSpec,
pub name: VarName,
}
impl NestedDisplay for Identifier {
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
match &self.dot {
Some(_dot) => write!(f, ".{}", self.name),
None => write!(f, "::{}", self.name),
}
write!(f, "{}{}", self.vis, self.name)
}
}
@ -2674,24 +2786,16 @@ impl_display_from_nested!(Identifier);
impl Locational for Identifier {
fn loc(&self) -> Location {
if let Some(dot) = &self.dot {
if dot.loc().is_unknown() {
self.name.loc()
} else {
Location::concat(dot, &self.name)
match &self.vis {
VisModifierSpec::Private | VisModifierSpec::Auto => self.name.loc(),
VisModifierSpec::ExplicitPrivate(token) | VisModifierSpec::Public(token) => {
Location::concat(token, &self.name)
}
} else {
self.name.loc()
VisModifierSpec::Restricted(args) => Location::concat(args, &self.name),
}
}
}
impl From<&Identifier> for Field {
fn from(ident: &Identifier) -> Self {
Self::new(ident.vis(), ident.inspect().clone())
}
}
impl From<Identifier> for Expr {
fn from(ident: Identifier) -> Self {
Self::Accessor(Accessor::Ident(ident))
@ -2699,34 +2803,52 @@ impl From<Identifier> for Expr {
}
impl Identifier {
pub const fn new(dot: Option<Token>, name: VarName) -> Self {
Self { dot, name }
pub const fn new(vis: VisModifierSpec, name: VarName) -> Self {
Self { vis, name }
}
pub fn static_public(name: &'static str) -> Self {
Self::new(
Some(Token::from_str(TokenKind::Dot, ".")),
VisModifierSpec::Public(Token::from_str(TokenKind::Dot, ".")),
VarName::from_static(name),
)
}
pub fn public(name: Str) -> Self {
Self::new(
Some(Token::from_str(TokenKind::Dot, ".")),
VisModifierSpec::Public(Token::from_str(TokenKind::Dot, ".")),
VarName::from_str(name),
)
}
pub fn private(name: Str) -> Self {
Self::new(None, VarName::from_str(name))
Self::new(VisModifierSpec::Private, VarName::from_str(name))
}
pub fn private_from_token(symbol: Token) -> Self {
Self::new(VisModifierSpec::Private, VarName::new(symbol))
}
pub fn private_from_varname(name: VarName) -> Self {
Self::new(VisModifierSpec::Private, name)
}
pub fn private_with_line(name: Str, line: u32) -> Self {
Self::new(None, VarName::from_str_and_line(name, line))
Self::new(
VisModifierSpec::Private,
VarName::from_str_and_line(name, line),
)
}
pub fn public_with_line(dot: Token, name: Str, line: u32) -> Self {
Self::new(Some(dot), VarName::from_str_and_line(name, line))
Self::new(
VisModifierSpec::Public(dot),
VarName::from_str_and_line(name, line),
)
}
pub fn public_from_token(dot: Token, symbol: Token) -> Self {
Self::new(VisModifierSpec::Public(dot), VarName::new(symbol))
}
pub fn is_const(&self) -> bool {
@ -2737,10 +2859,13 @@ impl Identifier {
self.name.is_raw()
}
pub const fn vis(&self) -> Visibility {
match &self.dot {
Some(_) => Visibility::Public,
None => Visibility::Private,
pub fn acc_kind(&self) -> AccessModifier {
match &self.vis {
VisModifierSpec::Auto => AccessModifier::Auto,
VisModifierSpec::Public(_) => AccessModifier::Public,
VisModifierSpec::ExplicitPrivate(_)
| VisModifierSpec::Restricted(_)
| VisModifierSpec::Private => AccessModifier::Private,
}
}
@ -2983,11 +3108,11 @@ impl VarPattern {
}
}
pub const fn vis(&self) -> Visibility {
pub fn vis(&self) -> &VisModifierSpec {
match self {
Self::Ident(ident) => ident.vis(),
Self::Ident(ident) => &ident.vis,
// TODO: `[.x, .y]`?
_ => Visibility::Private,
_ => &VisModifierSpec::Private,
}
}
@ -3036,7 +3161,7 @@ impl VarSignature {
self.pat.is_const()
}
pub const fn vis(&self) -> Visibility {
pub fn vis(&self) -> &VisModifierSpec {
self.pat.vis()
}
@ -3493,8 +3618,8 @@ impl SubrSignature {
self.ident.is_const()
}
pub const fn vis(&self) -> Visibility {
self.ident.vis()
pub fn vis(&self) -> &VisModifierSpec {
&self.ident.vis
}
}
@ -3693,7 +3818,7 @@ impl Signature {
matches!(self, Self::Subr(_))
}
pub const fn vis(&self) -> Visibility {
pub fn vis(&self) -> &VisModifierSpec {
match self {
Self::Var(var) => var.vis(),
Self::Subr(subr) => subr.vis(),
@ -3893,13 +4018,13 @@ impl ReDef {
pub struct Methods {
pub class: TypeSpec,
pub class_as_expr: Box<Expr>,
pub vis: Token, // `.` or `::`
pub vis: VisModifierSpec, // `.` or `::`
pub attrs: ClassAttrs,
}
impl NestedDisplay for Methods {
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
writeln!(f, "{}{}", self.class, self.vis.content)?;
writeln!(f, "{}{}", self.class, self.vis)?;
self.attrs.fmt_nest(f, level + 1)
}
}
@ -3908,7 +4033,12 @@ impl_display_from_nested!(Methods);
impl_locational!(Methods, class, attrs);
impl Methods {
pub fn new(class: TypeSpec, class_as_expr: Expr, vis: Token, attrs: ClassAttrs) -> Self {
pub fn new(
class: TypeSpec,
class_as_expr: Expr,
vis: VisModifierSpec,
attrs: ClassAttrs,
) -> Self {
Self {
class,
class_as_expr: Box::new(class_as_expr),
@ -3916,14 +4046,6 @@ impl Methods {
attrs,
}
}
pub fn vis(&self) -> Visibility {
if self.vis.is(TokenKind::Dot) {
Visibility::Public
} else {
Visibility::Private
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]

View file

@ -16,7 +16,7 @@ use crate::ast::{
ParamPattern, ParamRecordAttr, Params, PatchDef, PosArg, ReDef, Record, RecordAttrOrIdent,
RecordAttrs, Set as astSet, SetWithLength, Signature, SubrSignature, Tuple, TupleTypeSpec,
TypeAppArgs, TypeAppArgsKind, TypeBoundSpecs, TypeSpec, TypeSpecWithOp, UnaryOp, VarName,
VarPattern, VarRecordAttr, VarSignature,
VarPattern, VarRecordAttr, VarSignature, VisModifierSpec,
};
use crate::token::{Token, TokenKind, COLON, DOT};
@ -636,7 +636,10 @@ impl Desugarer {
r_brace,
)
}
BufIndex::Record(attr) => obj.attr(attr.clone()),
BufIndex::Record(attr) => {
let attr = Identifier::new(VisModifierSpec::Auto, attr.name.clone());
obj.attr(attr)
}
};
let id = DefId(get_hash(&(&acc, buf_name)));
let block = Block::new(vec![Expr::Accessor(acc)]);
@ -1001,7 +1004,10 @@ impl Desugarer {
r_brace,
)
}
BufIndex::Record(attr) => obj.attr(attr.clone()),
BufIndex::Record(attr) => {
let attr = Identifier::new(VisModifierSpec::Auto, attr.name.clone());
obj.attr(attr)
}
};
let id = DefId(get_hash(&(&acc, buf_name)));
let block = Block::new(vec![Expr::Accessor(acc)]);
@ -1166,7 +1172,7 @@ impl Desugarer {
}
*/
ParamPattern::VarName(name) => {
let ident = Identifier::new(None, name.clone());
let ident = Identifier::new(VisModifierSpec::Private, name.clone());
let v = VarSignature::new(
VarPattern::Ident(ident),
sig.t_spec.as_ref().map(|ts| ts.t_spec.clone()),

View file

@ -560,6 +560,37 @@ impl Parser {
Ok(TypeAppArgs::new(l_vbar, args, r_vbar))
}
fn try_reduce_restriction(&mut self) -> ParseResult<VisRestriction> {
debug_call_info!(self);
expect_pop!(self, LSqBr);
let rest = match self.peek_kind() {
Some(SubtypeOf) => {
self.lpop();
let t_spec_as_expr = self
.try_reduce_expr(false, true, false, false)
.map_err(|_| self.stack_dec(fn_name!()))?;
match Parser::expr_to_type_spec(t_spec_as_expr) {
Ok(t_spec) => VisRestriction::SubtypeOf(Box::new(t_spec)),
Err(err) => {
self.errs.push(err);
debug_exit_info!(self);
return Err(());
}
}
}
_ => {
// FIXME: reduce namespaces
let acc = self
.try_reduce_acc_lhs()
.map_err(|_| self.stack_dec(fn_name!()))?;
VisRestriction::Namespaces(Namespaces::new(vec![acc]))
}
};
expect_pop!(self, RSqBr);
debug_exit_info!(self);
Ok(rest)
}
fn try_reduce_acc_lhs(&mut self) -> ParseResult<Accessor> {
debug_call_info!(self);
let acc = match self.peek_kind() {
@ -576,6 +607,19 @@ impl Parser {
return Err(());
}
}
Some(DblColon) => {
let dbl_colon = self.lpop();
if let Some(LSqBr) = self.peek_kind() {
let rest = self
.try_reduce_restriction()
.map_err(|_| self.stack_dec(fn_name!()))?;
let symbol = expect_pop!(self, Symbol);
Accessor::restricted(rest, symbol)
} else {
let symbol = expect_pop!(self, Symbol);
Accessor::explicit_local(dbl_colon, symbol)
}
}
_ => {
let err = self.skip_and_throw_syntax_err(caused_by!());
self.errs.push(err);
@ -1000,7 +1044,11 @@ impl Parser {
}
}
fn try_reduce_method_defs(&mut self, class: Expr, vis: Token) -> ParseResult<Methods> {
fn try_reduce_method_defs(
&mut self,
class: Expr,
vis: VisModifierSpec,
) -> ParseResult<Methods> {
debug_call_info!(self);
expect_pop!(self, fail_next Indent);
while self.cur_is(Newline) {
@ -1205,7 +1253,7 @@ impl Parser {
));
}
Some(t) if t.is(DblColon) => {
let vis = self.lpop();
let vis = VisModifierSpec::ExplicitPrivate(self.lpop());
match self.lpop() {
symbol if symbol.is(Symbol) => {
let Some(ExprOrOp::Expr(obj)) = stack.pop() else {
@ -1219,11 +1267,13 @@ impl Parser {
.transpose()
.map_err(|_| self.stack_dec(fn_name!()))?
{
let ident = Identifier::new(None, VarName::new(symbol));
let ident =
Identifier::new(VisModifierSpec::Private, VarName::new(symbol));
let call = Call::new(obj, Some(ident), args);
stack.push(ExprOrOp::Expr(Expr::Call(call)));
} else {
let ident = Identifier::new(None, VarName::new(symbol));
let ident =
Identifier::new(VisModifierSpec::Private, VarName::new(symbol));
stack.push(ExprOrOp::Expr(obj.attr_expr(ident)));
}
}
@ -1267,7 +1317,7 @@ impl Parser {
}
}
Some(t) if t.is(Dot) => {
let vis = self.lpop();
let dot = self.lpop();
match self.lpop() {
symbol if symbol.is(Symbol) => {
let Some(ExprOrOp::Expr(obj)) = stack.pop() else {
@ -1281,15 +1331,16 @@ impl Parser {
.transpose()
.map_err(|_| self.stack_dec(fn_name!()))?
{
let ident = Identifier::new(Some(vis), VarName::new(symbol));
let ident = Identifier::public_from_token(dot, symbol);
let call = Expr::Call(Call::new(obj, Some(ident), args));
stack.push(ExprOrOp::Expr(call));
} else {
let ident = Identifier::new(Some(vis), VarName::new(symbol));
let ident = Identifier::public_from_token(dot, symbol);
stack.push(ExprOrOp::Expr(obj.attr_expr(ident)));
}
}
line_break if line_break.is(Newline) => {
let vis = VisModifierSpec::Public(dot);
let maybe_class = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
let defs = self
.try_reduce_method_defs(maybe_class, vis)
@ -1488,11 +1539,17 @@ impl Parser {
.transpose()
.map_err(|_| self.stack_dec(fn_name!()))?
{
let ident = Identifier::new(Some(vis), VarName::new(symbol));
let ident = Identifier::new(
VisModifierSpec::Public(vis),
VarName::new(symbol),
);
let call = Call::new(obj, Some(ident), args);
stack.push(ExprOrOp::Expr(Expr::Call(call)));
} else {
let ident = Identifier::new(Some(vis), VarName::new(symbol));
let ident = Identifier::new(
VisModifierSpec::Public(vis),
VarName::new(symbol),
);
stack.push(ExprOrOp::Expr(obj.attr_expr(ident)));
}
}
@ -1696,7 +1753,7 @@ impl Parser {
}
}
}
Some(t) if t.is(Symbol) || t.is(Dot) || t.is(UBar) => {
Some(t) if t.is(Symbol) || t.is(Dot) || t.is(DblColon) || t.is(UBar) => {
let call_or_acc = self
.try_reduce_call_or_acc(in_type_args)
.map_err(|_| self.stack_dec(fn_name!()))?;
@ -1861,7 +1918,8 @@ impl Parser {
let token = self.lpop();
match token.kind {
Symbol => {
let ident = Identifier::new(Some(vis), VarName::new(token));
let ident =
Identifier::new(VisModifierSpec::Public(vis), VarName::new(token));
obj = obj.attr_expr(ident);
}
NatLit => {
@ -1895,7 +1953,10 @@ impl Parser {
let token = self.lpop();
match token.kind {
Symbol => {
let ident = Identifier::new(None, VarName::new(token));
let ident = Identifier::new(
VisModifierSpec::ExplicitPrivate(vis),
VarName::new(token),
);
obj = obj.attr_expr(ident);
}
LBrace => {
@ -1905,6 +1966,7 @@ impl Parser {
.map_err(|_| self.stack_dec(fn_name!()))?;
match args {
BraceContainer::Record(args) => {
let vis = VisModifierSpec::ExplicitPrivate(vis);
obj = Expr::DataPack(DataPack::new(obj, vis, args));
}
other => {
@ -2023,15 +2085,15 @@ impl Parser {
}
// Empty brace literals
if let Some(first) = self.peek() {
if first.is(RBrace) {
match self.peek_kind() {
Some(RBrace) => {
let r_brace = self.lpop();
let arg = Args::empty();
let set = NormalSet::new(l_brace, r_brace, arg);
debug_exit_info!(self);
return Ok(BraceContainer::Set(Set::Normal(set)));
}
if first.is(Equal) {
Some(Equal) => {
let _eq = self.lpop();
if let Some(t) = self.peek() {
if t.is(RBrace) {
@ -2045,7 +2107,7 @@ impl Parser {
debug_exit_info!(self);
return Err(());
}
if first.is(Colon) {
Some(Colon) => {
let _colon = self.lpop();
if let Some(t) = self.peek() {
if t.is(RBrace) {
@ -2060,6 +2122,7 @@ impl Parser {
debug_exit_info!(self);
return Err(());
}
_ => {}
}
let first = self
@ -2541,7 +2604,8 @@ impl Parser {
.transpose()
.map_err(|_| self.stack_dec(fn_name!()))?
{
let ident = Identifier::new(Some(vis), VarName::new(symbol));
let ident =
Identifier::new(VisModifierSpec::Public(vis), VarName::new(symbol));
let mut call = Expr::Call(Call::new(obj, Some(ident), args));
while let Some(res) = self.opt_reduce_args(false) {
let args = res.map_err(|_| self.stack_dec(fn_name!()))?;

View file

@ -229,11 +229,12 @@ impl Parser {
(ParamPattern::VarName(name), Some(t_spec_with_op)) => {
ParamTySpec::new(Some(name.into_token()), t_spec_with_op.t_spec)
}
(ParamPattern::VarName(name), None) => {
ParamTySpec::anonymous(TypeSpec::PreDeclTy(PreDeclTypeSpec::Simple(
SimpleTypeSpec::new(Identifier::new(None, name), ConstArgs::empty()),
)))
}
(ParamPattern::VarName(name), None) => ParamTySpec::anonymous(TypeSpec::PreDeclTy(
PreDeclTypeSpec::Simple(SimpleTypeSpec::new(
Identifier::new(VisModifierSpec::Private, name),
ConstArgs::empty(),
)),
)),
_ => todo!(),
};
non_defaults.push(param);
@ -247,11 +248,12 @@ impl Parser {
(ParamPattern::VarName(name), Some(t_spec_with_op)) => {
ParamTySpec::new(Some(name.into_token()), t_spec_with_op.t_spec)
}
(ParamPattern::VarName(name), None) => {
ParamTySpec::anonymous(TypeSpec::PreDeclTy(PreDeclTypeSpec::Simple(
SimpleTypeSpec::new(Identifier::new(None, name), ConstArgs::empty()),
)))
}
(ParamPattern::VarName(name), None) => ParamTySpec::anonymous(
TypeSpec::PreDeclTy(PreDeclTypeSpec::Simple(SimpleTypeSpec::new(
Identifier::new(VisModifierSpec::Private, name),
ConstArgs::empty(),
))),
),
_ => todo!(),
});
let mut defaults = vec![];

View file

@ -4,7 +4,7 @@ print! empty
# Inheritance is prohibited by default. Remove this decorator and check for errors.
@Inheritable
Point2D = Class {x = Int; y = Int}
Point2D = Class {::[<: Self]x = Int; ::[<: Self]y = Int}
Point2D::
one = 1
Point2D.

View file

@ -1,5 +1,5 @@
UnpackPoint2D = Class {x = Int; y = Int}, Impl := Unpack
UnpackPoint2D = Class {.x = Int; .y = Int}, Impl := Unpack
q = UnpackPoint2D::{x = 1; y = 2}
q = UnpackPoint2D::{.x = 1; .y = 2}
UnpackPoint2D::{x; y} = q
print! x, y

View file

@ -0,0 +1,25 @@
@Inheritable
Point2D = Class {::[<: Self]x = Int; ::[<: Self]y = Int}
Point2D.
norm self = self::x**2 + self::y**2 #OK
Point3D = Inherit Point2D, Additional := {z = Int}
Point3D.
@Override
norm self = self::x**2 + self::y**2 + self::z**2 #OK
C = Class()
C.
method point: Point2D = point::x # ERR
p = Point3D.new {x = 1; y = 2; z = 3}
p::x # ERR
p.x # ERR
p::z # ERR
rec = {
::[f] x = 1
}
f x = rec::x + x # OK
g x = rec::x + x # ERR

View file

@ -1,6 +1,6 @@
f {x; y}, [_], (_, _) = x + y
f {.x; .y}, [_], (_, _) = x + y
x = f {x = 1; y = 2}, [3], (4, 5)
x = f {.x = 1; .y = 2}, [3], (4, 5)
assert x == 3
#[

View file

@ -306,6 +306,11 @@ fn exec_var_args_err() -> Result<(), ()> {
expect_failure("tests/should_err/var_args.er", 3)
}
#[test]
fn exec_visibility() -> Result<(), ()> {
expect_failure("tests/should_err/visibility.er", 5)
}
#[test]
fn exec_move() -> Result<(), ()> {
expect_failure("tests/should_err/move.er", 1)