mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-28 12:14:43 +00:00
feat: add special namespaces module/global
This commit is contained in:
parent
c4a0efae08
commit
730886021e
29 changed files with 349 additions and 193 deletions
|
@ -1,3 +1,4 @@
|
||||||
|
use erg_common::consts::PYTHON_MODE;
|
||||||
use lsp_types::CompletionResponse;
|
use lsp_types::CompletionResponse;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
|
@ -183,7 +184,7 @@ fn external_item(name: &str, vi: &VarInfo, mod_name: &str) -> CompletionItem {
|
||||||
CompletionItem::new_simple(format!("{name} (import from {mod_name})"), vi.t.to_string());
|
CompletionItem::new_simple(format!("{name} (import from {mod_name})"), vi.t.to_string());
|
||||||
item.sort_text = Some(format!("{}_{}", CompletionOrder::STD_ITEM, item.label));
|
item.sort_text = Some(format!("{}_{}", CompletionOrder::STD_ITEM, item.label));
|
||||||
item.kind = Some(comp_item_kind(vi));
|
item.kind = Some(comp_item_kind(vi));
|
||||||
let import = if cfg!(feature = "py_compat") {
|
let import = if PYTHON_MODE {
|
||||||
format!("from {mod_name} import {name}\n")
|
format!("from {mod_name} import {name}\n")
|
||||||
} else {
|
} else {
|
||||||
format!("{{{name};}} = pyimport \"{mod_name}\"\n")
|
format!("{{{name};}} = pyimport \"{mod_name}\"\n")
|
||||||
|
@ -226,7 +227,7 @@ fn module_completions() -> Vec<CompletionItem> {
|
||||||
);
|
);
|
||||||
item.sort_text = Some(format!("{}_{}", CompletionOrder::STD_ITEM, item.label));
|
item.sort_text = Some(format!("{}_{}", CompletionOrder::STD_ITEM, item.label));
|
||||||
item.kind = Some(CompletionItemKind::MODULE);
|
item.kind = Some(CompletionItemKind::MODULE);
|
||||||
let import = if cfg!(feature = "py_compat") {
|
let import = if PYTHON_MODE {
|
||||||
format!("import {mod_name}\n")
|
format!("import {mod_name}\n")
|
||||||
} else {
|
} else {
|
||||||
format!("{mod_name} = pyimport \"{mod_name}\"\n")
|
format!("{mod_name} = pyimport \"{mod_name}\"\n")
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use erg_common::consts::PYTHON_MODE;
|
||||||
use erg_common::traits::{Locational, Stream};
|
use erg_common::traits::{Locational, Stream};
|
||||||
use erg_compiler::artifact::BuildRunnable;
|
use erg_compiler::artifact::BuildRunnable;
|
||||||
use erg_compiler::context::register::PylyzerStatus;
|
use erg_compiler::context::register::PylyzerStatus;
|
||||||
|
@ -86,7 +87,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
||||||
match (&vi.def_loc.module, util::loc_to_range(vi.def_loc.loc)) {
|
match (&vi.def_loc.module, util::loc_to_range(vi.def_loc.loc)) {
|
||||||
(Some(path), Some(range)) => {
|
(Some(path), Some(range)) => {
|
||||||
let def_uri = NormalizedUrl::try_from(path.as_path()).unwrap();
|
let def_uri = NormalizedUrl::try_from(path.as_path()).unwrap();
|
||||||
let def_file = if cfg!(feature = "py_compat") {
|
let def_file = if PYTHON_MODE {
|
||||||
let header = self
|
let header = self
|
||||||
.file_cache
|
.file_cache
|
||||||
.get_line(&def_uri, 0)
|
.get_line(&def_uri, 0)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use erg_common::consts::ERG_MODE;
|
||||||
use erg_common::traits::Locational;
|
use erg_common::traits::Locational;
|
||||||
use erg_common::Str;
|
use erg_common::Str;
|
||||||
use erg_compiler::erg_parser::token::Token;
|
use erg_compiler::erg_parser::token::Token;
|
||||||
|
@ -25,7 +26,7 @@ impl<'a> HIRVisitor<'a> {
|
||||||
hir,
|
hir,
|
||||||
file_cache,
|
file_cache,
|
||||||
uri,
|
uri,
|
||||||
strict_cmp: !cfg!(feature = "py_compat"),
|
strict_cmp: ERG_MODE,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use erg_common::consts::PYTHON_MODE;
|
||||||
use erg_common::lang::LanguageCode;
|
use erg_common::lang::LanguageCode;
|
||||||
use erg_common::trim_eliminate_top_indent;
|
use erg_common::trim_eliminate_top_indent;
|
||||||
use erg_compiler::artifact::BuildRunnable;
|
use erg_compiler::artifact::BuildRunnable;
|
||||||
|
@ -10,11 +11,7 @@ use lsp_types::{Hover, HoverContents, HoverParams, MarkedString, Url};
|
||||||
use crate::server::{send_log, ELSResult, Server};
|
use crate::server::{send_log, ELSResult, Server};
|
||||||
use crate::util::{self, NormalizedUrl};
|
use crate::util::{self, NormalizedUrl};
|
||||||
|
|
||||||
const PROG_LANG: &str = if cfg!(feature = "py_compat") {
|
const PROG_LANG: &str = if PYTHON_MODE { "python" } else { "erg" };
|
||||||
"python"
|
|
||||||
} else {
|
|
||||||
"erg"
|
|
||||||
};
|
|
||||||
|
|
||||||
const ERG_LANG: &str = "erg";
|
const ERG_LANG: &str = "erg";
|
||||||
|
|
||||||
|
@ -223,7 +220,9 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
def_pos.line = def_pos.line.saturating_sub(1);
|
def_pos.line = def_pos.line.saturating_sub(1);
|
||||||
let def_uri = NormalizedUrl::new(Url::from_file_path(module).unwrap());
|
let Ok(def_uri) = NormalizedUrl::try_from(module.as_path()) else {
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
let mut default_code_block = "".to_string();
|
let mut default_code_block = "".to_string();
|
||||||
let Some(stream) = self.file_cache.get_token_stream(&def_uri) else {
|
let Some(stream) = self.file_cache.get_token_stream(&def_uri) else {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
|
|
@ -130,7 +130,7 @@ impl ASTSemanticState {
|
||||||
|
|
||||||
fn gen_from_poly_typespec(&mut self, t_spec: PolyTypeSpec) -> Vec<SemanticToken> {
|
fn gen_from_poly_typespec(&mut self, t_spec: PolyTypeSpec) -> Vec<SemanticToken> {
|
||||||
let mut tokens = vec![];
|
let mut tokens = vec![];
|
||||||
let token = self.gen_token(t_spec.ident.name.loc(), SemanticTokenType::TYPE);
|
let token = self.gen_token(t_spec.acc.loc(), SemanticTokenType::TYPE);
|
||||||
tokens.push(token);
|
tokens.push(token);
|
||||||
tokens
|
tokens
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ use std::ops::Not;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use erg_common::consts::PYTHON_MODE;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
@ -227,7 +228,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn mode(&self) -> &str {
|
pub const fn mode(&self) -> &str {
|
||||||
if cfg!(feature = "py_compat") {
|
if PYTHON_MODE {
|
||||||
"pylyzer"
|
"pylyzer"
|
||||||
} else {
|
} else {
|
||||||
"erg"
|
"erg"
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
pub const SEMVER: &str = env!("CARGO_PKG_VERSION");
|
pub const SEMVER: &str = env!("CARGO_PKG_VERSION");
|
||||||
pub const GIT_HASH_SHORT: &str = env!("GIT_HASH_SHORT");
|
pub const GIT_HASH_SHORT: &str = env!("GIT_HASH_SHORT");
|
||||||
pub const BUILD_DATE: &str = env!("BUILD_DATE");
|
pub const BUILD_DATE: &str = env!("BUILD_DATE");
|
||||||
|
|
||||||
|
pub const PYTHON_MODE: bool = cfg!(feature = "py_compat");
|
||||||
|
pub const ERG_MODE: bool = !cfg!(feature = "py_compat");
|
||||||
|
pub const ELS: bool = cfg!(feature = "els");
|
||||||
|
pub const DEBUG_MODE: bool = cfg!(feature = "debug");
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use crate::consts::{ERG_MODE, PYTHON_MODE};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub enum LanguageCode {
|
pub enum LanguageCode {
|
||||||
English,
|
English,
|
||||||
|
@ -107,8 +109,8 @@ impl LanguageCode {
|
||||||
Self::Japanese => cfg!(feature = "japanese"),
|
Self::Japanese => cfg!(feature = "japanese"),
|
||||||
Self::SimplifiedChinese => cfg!(feature = "simplified_chinese"),
|
Self::SimplifiedChinese => cfg!(feature = "simplified_chinese"),
|
||||||
Self::TraditionalChinese => cfg!(feature = "traditional_chinese"),
|
Self::TraditionalChinese => cfg!(feature = "traditional_chinese"),
|
||||||
Self::Erg => !cfg!(feature = "py_compat"),
|
Self::Erg => ERG_MODE,
|
||||||
Self::Python => cfg!(feature = "py_compat"),
|
Self::Python => PYTHON_MODE,
|
||||||
Self::ErgOrPython => true,
|
Self::ErgOrPython => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1372,7 +1372,8 @@ impl Context {
|
||||||
t.clone()
|
t.clone()
|
||||||
} else {
|
} else {
|
||||||
let tv = Type::FreeVar(new_fv);
|
let tv = Type::FreeVar(new_fv);
|
||||||
tv_cache.push_or_init_tyvar(&name, &tv, self);
|
let varname = VarName::from_str(name.clone());
|
||||||
|
tv_cache.push_or_init_tyvar(&varname, &tv, self);
|
||||||
tv
|
tv
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1397,7 +1398,8 @@ impl Context {
|
||||||
tp.clone()
|
tp.clone()
|
||||||
} else {
|
} else {
|
||||||
let tp = TyParam::FreeVar(new_fv);
|
let tp = TyParam::FreeVar(new_fv);
|
||||||
tv_cache.push_or_init_typaram(&name, &tp, self);
|
let varname = VarName::from_str(name.clone());
|
||||||
|
tv_cache.push_or_init_typaram(&varname, &tp, self);
|
||||||
tp
|
tp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use erg_common::consts::{ERG_MODE, PYTHON_MODE};
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use erg_common::log;
|
use erg_common::log;
|
||||||
use erg_common::Str as StrStruct;
|
use erg_common::Str as StrStruct;
|
||||||
|
@ -16,7 +17,7 @@ use Mutability::*;
|
||||||
|
|
||||||
impl Context {
|
impl Context {
|
||||||
pub(super) fn init_builtin_classes(&mut self) {
|
pub(super) fn init_builtin_classes(&mut self) {
|
||||||
let vis = if cfg!(feature = "py_compat") {
|
let vis = if PYTHON_MODE {
|
||||||
Visibility::BUILTIN_PUBLIC
|
Visibility::BUILTIN_PUBLIC
|
||||||
} else {
|
} else {
|
||||||
Visibility::BUILTIN_PRIVATE
|
Visibility::BUILTIN_PRIVATE
|
||||||
|
@ -1155,7 +1156,7 @@ impl Context {
|
||||||
let mut module = Self::builtin_poly_class(MODULE, vec![PS::named_nd(PATH, Str)], 2);
|
let mut module = Self::builtin_poly_class(MODULE, vec![PS::named_nd(PATH, Str)], 2);
|
||||||
module.register_superclass(g_module_t.clone(), &generic_module);
|
module.register_superclass(g_module_t.clone(), &generic_module);
|
||||||
let mut py_module = Self::builtin_poly_class(PY_MODULE, vec![PS::named_nd(PATH, Str)], 2);
|
let mut py_module = Self::builtin_poly_class(PY_MODULE, vec![PS::named_nd(PATH, Str)], 2);
|
||||||
if !cfg!(feature = "py_compat") {
|
if ERG_MODE {
|
||||||
py_module.register_superclass(g_module_t.clone(), &generic_module);
|
py_module.register_superclass(g_module_t.clone(), &generic_module);
|
||||||
}
|
}
|
||||||
/* GenericArray */
|
/* GenericArray */
|
||||||
|
@ -2178,32 +2179,16 @@ impl Context {
|
||||||
self.register_builtin_type(Never, never, vis.clone(), Const, Some(NEVER));
|
self.register_builtin_type(Never, never, vis.clone(), Const, Some(NEVER));
|
||||||
self.register_builtin_type(Obj, obj, vis.clone(), Const, Some(FUNC_OBJECT));
|
self.register_builtin_type(Obj, obj, vis.clone(), Const, Some(FUNC_OBJECT));
|
||||||
// self.register_type(mono(RECORD), vec![], record, Visibility::BUILTIN_PRIVATE, Const);
|
// self.register_type(mono(RECORD), vec![], record, Visibility::BUILTIN_PRIVATE, Const);
|
||||||
let name = if cfg!(feature = "py_compat") {
|
let name = if PYTHON_MODE { FUNC_INT } else { INT };
|
||||||
FUNC_INT
|
|
||||||
} else {
|
|
||||||
INT
|
|
||||||
};
|
|
||||||
self.register_builtin_type(Int, int, vis.clone(), Const, Some(name));
|
self.register_builtin_type(Int, int, vis.clone(), Const, Some(name));
|
||||||
self.register_builtin_type(Nat, nat, vis.clone(), Const, Some(NAT));
|
self.register_builtin_type(Nat, nat, vis.clone(), Const, Some(NAT));
|
||||||
let name = if cfg!(feature = "py_compat") {
|
let name = if PYTHON_MODE { FUNC_FLOAT } else { FLOAT };
|
||||||
FUNC_FLOAT
|
|
||||||
} else {
|
|
||||||
FLOAT
|
|
||||||
};
|
|
||||||
self.register_builtin_type(Complex, complex, vis.clone(), Const, Some(COMPLEX));
|
self.register_builtin_type(Complex, complex, vis.clone(), Const, Some(COMPLEX));
|
||||||
self.register_builtin_type(Float, float, vis.clone(), Const, Some(name));
|
self.register_builtin_type(Float, float, vis.clone(), Const, Some(name));
|
||||||
self.register_builtin_type(Ratio, ratio, vis.clone(), Const, Some(RATIO));
|
self.register_builtin_type(Ratio, ratio, vis.clone(), Const, Some(RATIO));
|
||||||
let name = if cfg!(feature = "py_compat") {
|
let name = if PYTHON_MODE { FUNC_BOOL } else { BOOL };
|
||||||
FUNC_BOOL
|
|
||||||
} else {
|
|
||||||
BOOL
|
|
||||||
};
|
|
||||||
self.register_builtin_type(Bool, bool_, vis.clone(), Const, Some(name));
|
self.register_builtin_type(Bool, bool_, vis.clone(), Const, Some(name));
|
||||||
let name = if cfg!(feature = "py_compat") {
|
let name = if PYTHON_MODE { FUNC_STR } else { STR };
|
||||||
FUNC_STR
|
|
||||||
} else {
|
|
||||||
STR
|
|
||||||
};
|
|
||||||
self.register_builtin_type(Str, str_, vis.clone(), Const, Some(name));
|
self.register_builtin_type(Str, str_, vis.clone(), Const, Some(name));
|
||||||
self.register_builtin_type(NoneType, nonetype, vis.clone(), Const, Some(NONE_TYPE));
|
self.register_builtin_type(NoneType, nonetype, vis.clone(), Const, Some(NONE_TYPE));
|
||||||
self.register_builtin_type(Type, type_, vis.clone(), Const, Some(FUNC_TYPE));
|
self.register_builtin_type(Type, type_, vis.clone(), Const, Some(FUNC_TYPE));
|
||||||
|
@ -2365,7 +2350,7 @@ impl Context {
|
||||||
self.register_builtin_type(mono(PROC), proc, vis.clone(), Const, Some(PROC));
|
self.register_builtin_type(mono(PROC), proc, vis.clone(), Const, Some(PROC));
|
||||||
self.register_builtin_type(mono(FUNC), func, vis.clone(), Const, Some(FUNC));
|
self.register_builtin_type(mono(FUNC), func, vis.clone(), Const, Some(FUNC));
|
||||||
self.register_builtin_type(range_t, range, vis.clone(), Const, Some(FUNC_RANGE));
|
self.register_builtin_type(range_t, range, vis.clone(), Const, Some(FUNC_RANGE));
|
||||||
if !cfg!(feature = "py_compat") {
|
if ERG_MODE {
|
||||||
self.register_builtin_type(module_t, module, vis.clone(), Const, Some(MODULE_TYPE));
|
self.register_builtin_type(module_t, module, vis.clone(), Const, Some(MODULE_TYPE));
|
||||||
self.register_builtin_type(
|
self.register_builtin_type(
|
||||||
mono(MUTABLE_OBJ),
|
mono(MUTABLE_OBJ),
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use erg_common::consts::{DEBUG_MODE, ERG_MODE, PYTHON_MODE};
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use erg_common::log;
|
use erg_common::log;
|
||||||
|
|
||||||
|
@ -14,7 +15,7 @@ use Mutability::*;
|
||||||
|
|
||||||
impl Context {
|
impl Context {
|
||||||
pub(super) fn init_builtin_funcs(&mut self) {
|
pub(super) fn init_builtin_funcs(&mut self) {
|
||||||
let vis = if cfg!(feature = "py_compat") {
|
let vis = if PYTHON_MODE {
|
||||||
Visibility::BUILTIN_PUBLIC
|
Visibility::BUILTIN_PUBLIC
|
||||||
} else {
|
} else {
|
||||||
Visibility::BUILTIN_PRIVATE
|
Visibility::BUILTIN_PRIVATE
|
||||||
|
@ -347,13 +348,9 @@ impl Context {
|
||||||
self.register_builtin_py_impl(FUNC_STR, t_str, Immutable, vis.clone(), Some(FUNC_STR__));
|
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_SUM, t_sum, Immutable, vis.clone(), Some(FUNC_SUM));
|
||||||
self.register_builtin_py_impl(FUNC_ZIP, t_zip, Immutable, vis.clone(), Some(FUNC_ZIP));
|
self.register_builtin_py_impl(FUNC_ZIP, t_zip, Immutable, vis.clone(), Some(FUNC_ZIP));
|
||||||
let name = if cfg!(feature = "py_compat") {
|
let name = if PYTHON_MODE { FUNC_INT } else { FUNC_INT__ };
|
||||||
FUNC_INT
|
|
||||||
} else {
|
|
||||||
FUNC_INT__
|
|
||||||
};
|
|
||||||
self.register_builtin_py_impl(FUNC_INT, t_int, Immutable, vis.clone(), Some(name));
|
self.register_builtin_py_impl(FUNC_INT, t_int, Immutable, vis.clone(), Some(name));
|
||||||
if cfg!(feature = "debug") {
|
if DEBUG_MODE {
|
||||||
self.register_builtin_py_impl(
|
self.register_builtin_py_impl(
|
||||||
PY,
|
PY,
|
||||||
t_pyimport.clone(),
|
t_pyimport.clone(),
|
||||||
|
@ -362,7 +359,7 @@ impl Context {
|
||||||
Some(FUNDAMENTAL_IMPORT),
|
Some(FUNDAMENTAL_IMPORT),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if !cfg!(feature = "py_compat") {
|
if ERG_MODE {
|
||||||
self.register_builtin_py_impl(FUNC_IF, t_if, Immutable, vis.clone(), Some(FUNC_IF__));
|
self.register_builtin_py_impl(FUNC_IF, t_if, Immutable, vis.clone(), Some(FUNC_IF__));
|
||||||
self.register_builtin_py_impl(
|
self.register_builtin_py_impl(
|
||||||
FUNC_DISCARD,
|
FUNC_DISCARD,
|
||||||
|
@ -467,7 +464,7 @@ impl Context {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn init_builtin_const_funcs(&mut self) {
|
pub(super) fn init_builtin_const_funcs(&mut self) {
|
||||||
let vis = if cfg!(feature = "py_compat") {
|
let vis = if PYTHON_MODE {
|
||||||
Visibility::BUILTIN_PUBLIC
|
Visibility::BUILTIN_PUBLIC
|
||||||
} else {
|
} else {
|
||||||
Visibility::BUILTIN_PRIVATE
|
Visibility::BUILTIN_PRIVATE
|
||||||
|
|
|
@ -13,6 +13,7 @@ mod traits;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use erg_common::config::ErgConfig;
|
use erg_common::config::ErgConfig;
|
||||||
|
use erg_common::consts::{DEBUG_MODE, ERG_MODE, PYTHON_MODE};
|
||||||
use erg_common::dict;
|
use erg_common::dict;
|
||||||
use erg_common::error::Location;
|
use erg_common::error::Location;
|
||||||
use erg_common::fresh::fresh_varname;
|
use erg_common::fresh::fresh_varname;
|
||||||
|
@ -501,7 +502,7 @@ impl Context {
|
||||||
vis: Visibility,
|
vis: Visibility,
|
||||||
py_name: Option<&'static str>,
|
py_name: Option<&'static str>,
|
||||||
) {
|
) {
|
||||||
if cfg!(feature = "debug") {
|
if DEBUG_MODE {
|
||||||
if let Type::Subr(subr) = &t {
|
if let Type::Subr(subr) = &t {
|
||||||
if subr.has_qvar() {
|
if subr.has_qvar() {
|
||||||
panic!("not quantified subr: {subr}");
|
panic!("not quantified subr: {subr}");
|
||||||
|
@ -513,7 +514,7 @@ impl Context {
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
let name = if cfg!(feature = "py_compat") {
|
let name = if PYTHON_MODE {
|
||||||
if let Some(py_name) = py_name {
|
if let Some(py_name) = py_name {
|
||||||
VarName::from_static(py_name)
|
VarName::from_static(py_name)
|
||||||
} else {
|
} else {
|
||||||
|
@ -603,7 +604,7 @@ impl Context {
|
||||||
vis: Visibility,
|
vis: Visibility,
|
||||||
py_name: Option<&'static str>,
|
py_name: Option<&'static str>,
|
||||||
) {
|
) {
|
||||||
let name = if cfg!(feature = "py_compat") {
|
let name = if PYTHON_MODE {
|
||||||
if let Some(py_name) = py_name {
|
if let Some(py_name) = py_name {
|
||||||
VarName::from_static(py_name)
|
VarName::from_static(py_name)
|
||||||
} else {
|
} else {
|
||||||
|
@ -622,7 +623,7 @@ impl Context {
|
||||||
py_name: Option<&'static str>,
|
py_name: Option<&'static str>,
|
||||||
lineno: u32,
|
lineno: u32,
|
||||||
) {
|
) {
|
||||||
let name = if cfg!(feature = "py_compat") {
|
let name = if PYTHON_MODE {
|
||||||
if let Some(py_name) = py_name {
|
if let Some(py_name) = py_name {
|
||||||
VarName::from_static(py_name)
|
VarName::from_static(py_name)
|
||||||
} else {
|
} else {
|
||||||
|
@ -631,7 +632,7 @@ impl Context {
|
||||||
} else {
|
} else {
|
||||||
VarName::from_static(name)
|
VarName::from_static(name)
|
||||||
};
|
};
|
||||||
let vis = if cfg!(feature = "py_compat") || &self.name[..] != "<builtins>" {
|
let vis = if PYTHON_MODE || &self.name[..] != "<builtins>" {
|
||||||
Visibility::BUILTIN_PUBLIC
|
Visibility::BUILTIN_PUBLIC
|
||||||
} else {
|
} else {
|
||||||
Visibility::BUILTIN_PRIVATE
|
Visibility::BUILTIN_PRIVATE
|
||||||
|
@ -804,7 +805,7 @@ impl Context {
|
||||||
.map(|tp| ParamTy::Pos(tp_enum(self.get_tp_t(&tp).unwrap_or(Obj), set! { tp })))
|
.map(|tp| ParamTy::Pos(tp_enum(self.get_tp_t(&tp).unwrap_or(Obj), set! { tp })))
|
||||||
.collect();
|
.collect();
|
||||||
let meta_t = func(params, None, vec![], v_enum(set! { val.clone() })).quantify();
|
let meta_t = func(params, None, vec![], v_enum(set! { val.clone() })).quantify();
|
||||||
if !cfg!(feature = "py_compat") {
|
if ERG_MODE {
|
||||||
self.locals.insert(
|
self.locals.insert(
|
||||||
name.clone(),
|
name.clone(),
|
||||||
VarInfo::new(
|
VarInfo::new(
|
||||||
|
@ -897,7 +898,7 @@ impl Context {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_builtin_consts(&mut self) {
|
fn init_builtin_consts(&mut self) {
|
||||||
let vis = if cfg!(feature = "py_compat") {
|
let vis = if PYTHON_MODE {
|
||||||
Visibility::BUILTIN_PUBLIC
|
Visibility::BUILTIN_PUBLIC
|
||||||
} else {
|
} else {
|
||||||
Visibility::BUILTIN_PRIVATE
|
Visibility::BUILTIN_PRIVATE
|
||||||
|
@ -956,7 +957,7 @@ impl Context {
|
||||||
ctx.init_builtin_funcs();
|
ctx.init_builtin_funcs();
|
||||||
ctx.init_builtin_const_funcs();
|
ctx.init_builtin_const_funcs();
|
||||||
ctx.init_builtin_procs();
|
ctx.init_builtin_procs();
|
||||||
if cfg!(feature = "py_compat") {
|
if PYTHON_MODE {
|
||||||
ctx.init_py_compat_builtin_operators();
|
ctx.init_py_compat_builtin_operators();
|
||||||
} else {
|
} else {
|
||||||
ctx.init_builtin_operators();
|
ctx.init_builtin_operators();
|
||||||
|
|
|
@ -13,7 +13,7 @@ use Mutability::*;
|
||||||
|
|
||||||
impl Context {
|
impl Context {
|
||||||
pub(super) fn init_builtin_procs(&mut self) {
|
pub(super) fn init_builtin_procs(&mut self) {
|
||||||
let vis = if cfg!(feature = "py_compat") {
|
let vis = if PYTHON_MODE {
|
||||||
Visibility::BUILTIN_PUBLIC
|
Visibility::BUILTIN_PUBLIC
|
||||||
} else {
|
} else {
|
||||||
Visibility::BUILTIN_PRIVATE
|
Visibility::BUILTIN_PRIVATE
|
||||||
|
@ -73,7 +73,7 @@ impl Context {
|
||||||
T.clone(),
|
T.clone(),
|
||||||
)
|
)
|
||||||
.quantify();
|
.quantify();
|
||||||
let t_cond = if cfg!(feature = "py_compat") {
|
let t_cond = if PYTHON_MODE {
|
||||||
Bool
|
Bool
|
||||||
} else {
|
} else {
|
||||||
// not Bool! type because `cond` may be the result of evaluation of a mutable object's method returns Bool.
|
// not Bool! type because `cond` may be the result of evaluation of a mutable object's method returns Bool.
|
||||||
|
@ -103,7 +103,7 @@ impl Context {
|
||||||
mono("File!"),
|
mono("File!"),
|
||||||
)
|
)
|
||||||
.quantify();
|
.quantify();
|
||||||
let C = if cfg!(feature = "py_compat") {
|
let C = if PYTHON_MODE {
|
||||||
mono("ContextManager").structuralize()
|
mono("ContextManager").structuralize()
|
||||||
} else {
|
} else {
|
||||||
mono("ContextManager")
|
mono("ContextManager")
|
||||||
|
@ -131,29 +131,13 @@ impl Context {
|
||||||
self.register_builtin_py_impl("locals!", t_locals, Immutable, vis.clone(), Some("locals"));
|
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_builtin_py_impl("next!", t_next, Immutable, vis.clone(), Some("next"));
|
||||||
self.register_py_builtin("open!", t_open, Some("open"), 198);
|
self.register_py_builtin("open!", t_open, Some("open"), 198);
|
||||||
let name = if cfg!(feature = "py_compat") {
|
let name = if PYTHON_MODE { "if" } else { "if__" };
|
||||||
"if"
|
|
||||||
} else {
|
|
||||||
"if__"
|
|
||||||
};
|
|
||||||
self.register_builtin_py_impl("if!", t_if, Immutable, vis.clone(), Some(name));
|
self.register_builtin_py_impl("if!", t_if, Immutable, vis.clone(), Some(name));
|
||||||
let name = if cfg!(feature = "py_compat") {
|
let name = if PYTHON_MODE { "for" } else { "for__" };
|
||||||
"for"
|
|
||||||
} else {
|
|
||||||
"for__"
|
|
||||||
};
|
|
||||||
self.register_builtin_py_impl("for!", t_for, Immutable, vis.clone(), Some(name));
|
self.register_builtin_py_impl("for!", t_for, Immutable, vis.clone(), Some(name));
|
||||||
let name = if cfg!(feature = "py_compat") {
|
let name = if PYTHON_MODE { "while" } else { "while__" };
|
||||||
"while"
|
|
||||||
} else {
|
|
||||||
"while__"
|
|
||||||
};
|
|
||||||
self.register_builtin_py_impl("while!", t_while, Immutable, vis.clone(), Some(name));
|
self.register_builtin_py_impl("while!", t_while, Immutable, vis.clone(), Some(name));
|
||||||
let name = if cfg!(feature = "py_compat") {
|
let name = if PYTHON_MODE { "with" } else { "with__" };
|
||||||
"with"
|
|
||||||
} else {
|
|
||||||
"with__"
|
|
||||||
};
|
|
||||||
self.register_builtin_py_impl("with!", t_with, Immutable, vis, Some(name));
|
self.register_builtin_py_impl("with!", t_with, Immutable, vis, Some(name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ impl Context {
|
||||||
// 型境界はすべて各サブルーチンで定義する
|
// 型境界はすべて各サブルーチンで定義する
|
||||||
// push_subtype_boundなどはユーザー定義APIの型境界決定のために使用する
|
// push_subtype_boundなどはユーザー定義APIの型境界決定のために使用する
|
||||||
pub(super) fn init_builtin_traits(&mut self) {
|
pub(super) fn init_builtin_traits(&mut self) {
|
||||||
let vis = if cfg!(feature = "py_compat") {
|
let vis = if PYTHON_MODE {
|
||||||
Visibility::BUILTIN_PUBLIC
|
Visibility::BUILTIN_PUBLIC
|
||||||
} else {
|
} else {
|
||||||
Visibility::BUILTIN_PRIVATE
|
Visibility::BUILTIN_PRIVATE
|
||||||
|
|
|
@ -3,6 +3,7 @@ use std::option::Option; // conflicting to Type::Option
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use erg_common::config::{ErgConfig, Input};
|
use erg_common::config::{ErgConfig, Input};
|
||||||
|
use erg_common::consts::{ERG_MODE, PYTHON_MODE};
|
||||||
use erg_common::dict;
|
use erg_common::dict;
|
||||||
use erg_common::env::{erg_py_external_lib_path, erg_pystd_path, erg_std_path};
|
use erg_common::env::{erg_py_external_lib_path, erg_pystd_path, erg_std_path};
|
||||||
use erg_common::error::{ErrorCore, Location, SubMessage};
|
use erg_common::error::{ErrorCore, Location, SubMessage};
|
||||||
|
@ -523,7 +524,7 @@ impl Context {
|
||||||
) -> Triple<VarInfo, TyCheckError> {
|
) -> Triple<VarInfo, TyCheckError> {
|
||||||
// get_attr_info(?T, aaa) == None
|
// get_attr_info(?T, aaa) == None
|
||||||
// => ?T(<: Structural({ .aaa = ?U }))
|
// => ?T(<: Structural({ .aaa = ?U }))
|
||||||
if self.in_subr() && cfg!(feature = "py_compat") {
|
if self.in_subr() && PYTHON_MODE {
|
||||||
let t = free_var(self.level, Constraint::new_type_of(Type));
|
let t = free_var(self.level, Constraint::new_type_of(Type));
|
||||||
if let Some(fv) = obj.ref_t().as_free() {
|
if let Some(fv) = obj.ref_t().as_free() {
|
||||||
if fv.get_sub().is_some() {
|
if fv.get_sub().is_some() {
|
||||||
|
@ -624,7 +625,7 @@ impl Context {
|
||||||
}
|
}
|
||||||
return Triple::Ok(method.method_info.clone());
|
return Triple::Ok(method.method_info.clone());
|
||||||
}
|
}
|
||||||
Triple::Err(err) if !cfg!(feature = "py_compat") => {
|
Triple::Err(err) if ERG_MODE => {
|
||||||
return Triple::Err(err);
|
return Triple::Err(err);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -863,7 +864,7 @@ impl Context {
|
||||||
) -> SingleTyCheckResult<VarInfo> {
|
) -> SingleTyCheckResult<VarInfo> {
|
||||||
// search_method_info(?T, aaa, pos_args: [1, 2]) == None
|
// search_method_info(?T, aaa, pos_args: [1, 2]) == None
|
||||||
// => ?T(<: Structural({ .aaa = (self: ?T, ?U, ?V) -> ?W }))
|
// => ?T(<: Structural({ .aaa = (self: ?T, ?U, ?V) -> ?W }))
|
||||||
if cfg!(feature = "py_compat") && self.in_subr() {
|
if PYTHON_MODE && self.in_subr() {
|
||||||
let nd_params = pos_args
|
let nd_params = pos_args
|
||||||
.iter()
|
.iter()
|
||||||
.map(|_| ParamTy::Pos(free_var(self.level, Constraint::new_type_of(Type))))
|
.map(|_| ParamTy::Pos(free_var(self.level, Constraint::new_type_of(Type))))
|
||||||
|
@ -2497,9 +2498,15 @@ impl Context {
|
||||||
|
|
||||||
// FIXME: 現在の実装だとimportしたモジュールはどこからでも見れる
|
// FIXME: 現在の実装だとimportしたモジュールはどこからでも見れる
|
||||||
pub(crate) fn get_mod(&self, name: &str) -> Option<&Context> {
|
pub(crate) fn get_mod(&self, name: &str) -> Option<&Context> {
|
||||||
|
if name == "module" && ERG_MODE {
|
||||||
|
self.get_module()
|
||||||
|
} else if name == "global" {
|
||||||
|
self.get_builtins()
|
||||||
|
} else {
|
||||||
let t = self.get_var_info(name).map(|(_, vi)| &vi.t)?;
|
let t = self.get_var_info(name).map(|(_, vi)| &vi.t)?;
|
||||||
self.get_mod_from_t(t)
|
self.get_mod_from_t(t)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_mod_from_t(&self, mod_t: &Type) -> Option<&Context> {
|
pub fn get_mod_from_t(&self, mod_t: &Type) -> Option<&Context> {
|
||||||
self.get_ctx_from_path(&self.get_path_from_mod_t(mod_t)?)
|
self.get_ctx_from_path(&self.get_path_from_mod_t(mod_t)?)
|
||||||
|
@ -2571,6 +2578,11 @@ impl Context {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_namespace(&self, namespace: &Str) -> Option<&Context> {
|
pub(crate) fn get_namespace(&self, namespace: &Str) -> Option<&Context> {
|
||||||
|
if &namespace[..] == "global" {
|
||||||
|
return self.get_builtins();
|
||||||
|
} else if &namespace[..] == "module" {
|
||||||
|
return self.get_module();
|
||||||
|
}
|
||||||
let mut namespaces = namespace.split_with(&[".", "::"]);
|
let mut namespaces = namespace.split_with(&[".", "::"]);
|
||||||
let mut namespace = namespaces.first().map(|n| n.to_string())?;
|
let mut namespace = namespaces.first().map(|n| n.to_string())?;
|
||||||
namespaces.remove(0);
|
namespaces.remove(0);
|
||||||
|
|
|
@ -9,6 +9,7 @@ use erg_common::log;
|
||||||
use erg_common::set::Set;
|
use erg_common::set::Set;
|
||||||
use erg_common::traits::Locational;
|
use erg_common::traits::Locational;
|
||||||
use erg_common::Str;
|
use erg_common::Str;
|
||||||
|
use erg_parser::ast::VarName;
|
||||||
|
|
||||||
use crate::feature_error;
|
use crate::feature_error;
|
||||||
use crate::ty::constructors::*;
|
use crate::ty::constructors::*;
|
||||||
|
@ -34,8 +35,8 @@ use crate::hir;
|
||||||
pub struct TyVarCache {
|
pub struct TyVarCache {
|
||||||
_level: usize,
|
_level: usize,
|
||||||
pub(crate) already_appeared: Set<Str>,
|
pub(crate) already_appeared: Set<Str>,
|
||||||
pub(crate) tyvar_instances: Dict<Str, Type>,
|
pub(crate) tyvar_instances: Dict<VarName, Type>,
|
||||||
pub(crate) typaram_instances: Dict<Str, TyParam>,
|
pub(crate) typaram_instances: Dict<VarName, TyParam>,
|
||||||
pub(crate) structural_inner: bool,
|
pub(crate) structural_inner: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,7 +134,7 @@ impl TyVarCache {
|
||||||
self.already_appeared.insert(name);
|
self.already_appeared.insert(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn push_or_init_tyvar(&mut self, name: &Str, tv: &Type, ctx: &Context) {
|
pub(crate) fn push_or_init_tyvar(&mut self, name: &VarName, tv: &Type, ctx: &Context) {
|
||||||
if let Some(inst) = self.tyvar_instances.get(name) {
|
if let Some(inst) = self.tyvar_instances.get(name) {
|
||||||
self.update_tyvar(inst, tv, ctx);
|
self.update_tyvar(inst, tv, ctx);
|
||||||
} else if let Some(inst) = self.typaram_instances.get(name) {
|
} else if let Some(inst) = self.typaram_instances.get(name) {
|
||||||
|
@ -175,7 +176,7 @@ impl TyVarCache {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn push_or_init_typaram(&mut self, name: &Str, tp: &TyParam, ctx: &Context) {
|
pub(crate) fn push_or_init_typaram(&mut self, name: &VarName, tp: &TyParam, ctx: &Context) {
|
||||||
// FIXME:
|
// FIXME:
|
||||||
if let Some(inst) = self.typaram_instances.get(name) {
|
if let Some(inst) = self.typaram_instances.get(name) {
|
||||||
self.update_typaram(inst, tp, ctx);
|
self.update_typaram(inst, tp, ctx);
|
||||||
|
@ -262,10 +263,11 @@ impl Context {
|
||||||
}
|
}
|
||||||
Ok(TyParam::t(t))
|
Ok(TyParam::t(t))
|
||||||
} else {
|
} else {
|
||||||
|
let varname = VarName::from_str(name.clone());
|
||||||
if tmp_tv_cache.appeared(&name) {
|
if tmp_tv_cache.appeared(&name) {
|
||||||
let tp =
|
let tp =
|
||||||
TyParam::named_free_var(name.clone(), self.level, Constraint::Uninited);
|
TyParam::named_free_var(name.clone(), self.level, Constraint::Uninited);
|
||||||
tmp_tv_cache.push_or_init_typaram(&name, &tp, self);
|
tmp_tv_cache.push_or_init_typaram(&varname, &tp, self);
|
||||||
return Ok(tp);
|
return Ok(tp);
|
||||||
}
|
}
|
||||||
if let Some(tv_cache) = &self.tv_cache {
|
if let Some(tv_cache) = &self.tv_cache {
|
||||||
|
@ -278,7 +280,7 @@ impl Context {
|
||||||
tmp_tv_cache.push_appeared(name.clone());
|
tmp_tv_cache.push_appeared(name.clone());
|
||||||
let constr = tmp_tv_cache.instantiate_constraint(constr, self, loc)?;
|
let constr = tmp_tv_cache.instantiate_constraint(constr, self, loc)?;
|
||||||
let tp = TyParam::named_free_var(name.clone(), self.level, constr);
|
let tp = TyParam::named_free_var(name.clone(), self.level, constr);
|
||||||
tmp_tv_cache.push_or_init_typaram(&name, &tp, self);
|
tmp_tv_cache.push_or_init_typaram(&varname, &tp, self);
|
||||||
Ok(tp)
|
Ok(tp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -411,9 +413,10 @@ impl Context {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
let varname = VarName::from_str(name.clone());
|
||||||
if tmp_tv_cache.appeared(&name) {
|
if tmp_tv_cache.appeared(&name) {
|
||||||
let tyvar = named_free_var(name.clone(), self.level, Constraint::Uninited);
|
let tyvar = named_free_var(name.clone(), self.level, Constraint::Uninited);
|
||||||
tmp_tv_cache.push_or_init_tyvar(&name, &tyvar, self);
|
tmp_tv_cache.push_or_init_tyvar(&varname, &tyvar, self);
|
||||||
return Ok(tyvar);
|
return Ok(tyvar);
|
||||||
}
|
}
|
||||||
if let Some(tv_ctx) = &self.tv_cache {
|
if let Some(tv_ctx) = &self.tv_cache {
|
||||||
|
@ -434,7 +437,7 @@ impl Context {
|
||||||
tmp_tv_cache.push_appeared(name.clone());
|
tmp_tv_cache.push_appeared(name.clone());
|
||||||
let constr = tmp_tv_cache.instantiate_constraint(constr, self, loc)?;
|
let constr = tmp_tv_cache.instantiate_constraint(constr, self, loc)?;
|
||||||
let tyvar = named_free_var(name.clone(), self.level, constr);
|
let tyvar = named_free_var(name.clone(), self.level, constr);
|
||||||
tmp_tv_cache.push_or_init_tyvar(&name, &tyvar, self);
|
tmp_tv_cache.push_or_init_tyvar(&varname, &tyvar, self);
|
||||||
Ok(tyvar)
|
Ok(tyvar)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ use ast::{
|
||||||
NonDefaultParamSignature, ParamTySpec, PolyTypeSpec, PreDeclTypeSpec, TypeBoundSpec,
|
NonDefaultParamSignature, ParamTySpec, PolyTypeSpec, PreDeclTypeSpec, TypeBoundSpec,
|
||||||
TypeBoundSpecs, TypeSpec,
|
TypeBoundSpecs, TypeSpec,
|
||||||
};
|
};
|
||||||
use erg_parser::ast::{self, ConstArray, Identifier, VisModifierSpec, VisRestriction};
|
use erg_parser::ast::{self, ConstArray, Identifier, VarName, VisModifierSpec, VisRestriction};
|
||||||
use erg_parser::token::TokenKind;
|
use erg_parser::token::TokenKind;
|
||||||
use erg_parser::Parser;
|
use erg_parser::Parser;
|
||||||
|
|
||||||
|
@ -124,7 +124,7 @@ impl Context {
|
||||||
// TODO: other than type `Type`
|
// TODO: other than type `Type`
|
||||||
let constr = Constraint::new_type_of(Type);
|
let constr = Constraint::new_type_of(Type);
|
||||||
let tv = named_free_var(name.inspect().clone(), self.level, constr);
|
let tv = named_free_var(name.inspect().clone(), self.level, constr);
|
||||||
tv_cache.push_or_init_tyvar(name.inspect(), &tv, self);
|
tv_cache.push_or_init_tyvar(name, &tv, self);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
TypeBoundSpec::NonDefault { lhs, spec } => {
|
TypeBoundSpec::NonDefault { lhs, spec } => {
|
||||||
|
@ -146,10 +146,10 @@ impl Context {
|
||||||
};
|
};
|
||||||
if constr.get_sub_sup().is_none() {
|
if constr.get_sub_sup().is_none() {
|
||||||
let tp = TyParam::named_free_var(lhs.inspect().clone(), self.level, constr);
|
let tp = TyParam::named_free_var(lhs.inspect().clone(), self.level, constr);
|
||||||
tv_cache.push_or_init_typaram(lhs.inspect(), &tp, self);
|
tv_cache.push_or_init_typaram(lhs, &tp, self);
|
||||||
} else {
|
} else {
|
||||||
let tv = named_free_var(lhs.inspect().clone(), self.level, constr);
|
let tv = named_free_var(lhs.inspect().clone(), self.level, constr);
|
||||||
tv_cache.push_or_init_tyvar(lhs.inspect(), &tv, self);
|
tv_cache.push_or_init_tyvar(lhs, &tv, self);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -536,7 +536,7 @@ impl Context {
|
||||||
Ok(typ.clone())
|
Ok(typ.clone())
|
||||||
} else if not_found_is_qvar {
|
} else if not_found_is_qvar {
|
||||||
let tyvar = named_free_var(Str::rc(other), self.level, Constraint::Uninited);
|
let tyvar = named_free_var(Str::rc(other), self.level, Constraint::Uninited);
|
||||||
tmp_tv_cache.push_or_init_tyvar(ident.inspect(), &tyvar, self);
|
tmp_tv_cache.push_or_init_tyvar(&ident.name, &tyvar, self);
|
||||||
Ok(tyvar)
|
Ok(tyvar)
|
||||||
} else {
|
} else {
|
||||||
Err(TyCheckErrors::from(TyCheckError::no_type_error(
|
Err(TyCheckErrors::from(TyCheckError::no_type_error(
|
||||||
|
@ -559,7 +559,7 @@ impl Context {
|
||||||
tmp_tv_cache: &mut TyVarCache,
|
tmp_tv_cache: &mut TyVarCache,
|
||||||
not_found_is_qvar: bool,
|
not_found_is_qvar: bool,
|
||||||
) -> TyCheckResult<Type> {
|
) -> TyCheckResult<Type> {
|
||||||
match &poly_spec.ident.inspect()[..] {
|
match poly_spec.acc.to_string().trim_start_matches("::") {
|
||||||
"Array" => {
|
"Array" => {
|
||||||
// TODO: kw
|
// TODO: kw
|
||||||
let mut args = poly_spec.args.pos_args();
|
let mut args = poly_spec.args.pos_args();
|
||||||
|
@ -647,13 +647,11 @@ impl Context {
|
||||||
Ok(t.structuralize())
|
Ok(t.structuralize())
|
||||||
}
|
}
|
||||||
other => {
|
other => {
|
||||||
let ctx = if let Some((_, ctx)) = self.get_type(&Str::rc(other)) {
|
let Some((typ, ctx)) = self.get_type(&Str::rc(other)) else {
|
||||||
ctx
|
|
||||||
} else {
|
|
||||||
return Err(TyCheckErrors::from(TyCheckError::no_type_error(
|
return Err(TyCheckErrors::from(TyCheckError::no_type_error(
|
||||||
self.cfg.input.clone(),
|
self.cfg.input.clone(),
|
||||||
line!() as usize,
|
line!() as usize,
|
||||||
poly_spec.ident.loc(),
|
poly_spec.acc.loc(),
|
||||||
self.caused_by(),
|
self.caused_by(),
|
||||||
other,
|
other,
|
||||||
self.get_similar_name(other),
|
self.get_similar_name(other),
|
||||||
|
@ -680,7 +678,8 @@ impl Context {
|
||||||
self.level,
|
self.level,
|
||||||
Constraint::Uninited,
|
Constraint::Uninited,
|
||||||
);
|
);
|
||||||
tmp_tv_cache.push_or_init_typaram(&name, &tp, self);
|
let varname = VarName::from_str(name);
|
||||||
|
tmp_tv_cache.push_or_init_typaram(&varname, &tp, self);
|
||||||
Ok(tp)
|
Ok(tp)
|
||||||
} else {
|
} else {
|
||||||
Err(e)
|
Err(e)
|
||||||
|
@ -711,7 +710,7 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// FIXME: non-builtin
|
// FIXME: non-builtin
|
||||||
Ok(poly(Str::rc(other), new_params))
|
Ok(poly(typ.qual_name(), new_params))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -723,6 +722,7 @@ impl Context {
|
||||||
tmp_tv_cache: &mut TyVarCache,
|
tmp_tv_cache: &mut TyVarCache,
|
||||||
not_found_is_qvar: bool,
|
not_found_is_qvar: bool,
|
||||||
) -> TyCheckResult<TyParam> {
|
) -> TyCheckResult<TyParam> {
|
||||||
|
self.inc_ref_acc(&acc.clone().downcast(), self);
|
||||||
match acc {
|
match acc {
|
||||||
ast::ConstAccessor::Attr(attr) => {
|
ast::ConstAccessor::Attr(attr) => {
|
||||||
let obj = self.instantiate_const_expr(
|
let obj = self.instantiate_const_expr(
|
||||||
|
@ -734,14 +734,7 @@ impl Context {
|
||||||
Ok(obj.proj(attr.name.inspect()))
|
Ok(obj.proj(attr.name.inspect()))
|
||||||
}
|
}
|
||||||
ast::ConstAccessor::Local(local) => {
|
ast::ConstAccessor::Local(local) => {
|
||||||
self.inc_ref_local(local, self);
|
self.instantiate_local(local, erased_idx, tmp_tv_cache, local, not_found_is_qvar)
|
||||||
self.instantiate_local(
|
|
||||||
local.inspect(),
|
|
||||||
erased_idx,
|
|
||||||
tmp_tv_cache,
|
|
||||||
local,
|
|
||||||
not_found_is_qvar,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
other => type_feature_error!(
|
other => type_feature_error!(
|
||||||
self,
|
self,
|
||||||
|
@ -753,13 +746,13 @@ impl Context {
|
||||||
|
|
||||||
fn instantiate_local(
|
fn instantiate_local(
|
||||||
&self,
|
&self,
|
||||||
name: &Str,
|
name: &Identifier,
|
||||||
erased_idx: Option<(&Context, usize)>,
|
erased_idx: Option<(&Context, usize)>,
|
||||||
tmp_tv_cache: &mut TyVarCache,
|
tmp_tv_cache: &mut TyVarCache,
|
||||||
loc: &impl Locational,
|
loc: &impl Locational,
|
||||||
not_found_is_qvar: bool,
|
not_found_is_qvar: bool,
|
||||||
) -> TyCheckResult<TyParam> {
|
) -> TyCheckResult<TyParam> {
|
||||||
if &name[..] == "_" {
|
if &name.inspect()[..] == "_" {
|
||||||
let t = if let Some((ctx, i)) = erased_idx {
|
let t = if let Some((ctx, i)) = erased_idx {
|
||||||
let param = ctx.params.get(i).ok_or_else(|| {
|
let param = ctx.params.get(i).ok_or_else(|| {
|
||||||
TyCheckErrors::from(TyCheckError::too_many_args_error(
|
TyCheckErrors::from(TyCheckError::too_many_args_error(
|
||||||
|
@ -779,15 +772,15 @@ impl Context {
|
||||||
};
|
};
|
||||||
return Ok(TyParam::erased(t));
|
return Ok(TyParam::erased(t));
|
||||||
}
|
}
|
||||||
if let Some(tp) = self.get_tp_from_tv_cache(name, tmp_tv_cache) {
|
if let Some(tp) = self.get_tp_from_tv_cache(name.inspect(), tmp_tv_cache) {
|
||||||
return Ok(tp);
|
return Ok(tp);
|
||||||
}
|
}
|
||||||
if let Some(value) = self.rec_get_const_obj(name) {
|
if let Some(value) = self.rec_get_const_obj(name.inspect()) {
|
||||||
return Ok(TyParam::Value(value.clone()));
|
return Ok(TyParam::Value(value.clone()));
|
||||||
}
|
}
|
||||||
if not_found_is_qvar {
|
if not_found_is_qvar {
|
||||||
let tyvar = named_free_var(name.clone(), self.level, Constraint::Uninited);
|
let tyvar = named_free_var(name.inspect().clone(), self.level, Constraint::Uninited);
|
||||||
tmp_tv_cache.push_or_init_tyvar(name, &tyvar, self);
|
tmp_tv_cache.push_or_init_tyvar(&name.name, &tyvar, self);
|
||||||
return Ok(TyParam::t(tyvar));
|
return Ok(TyParam::t(tyvar));
|
||||||
}
|
}
|
||||||
Err(TyCheckErrors::from(TyCheckError::no_var_error(
|
Err(TyCheckErrors::from(TyCheckError::no_var_error(
|
||||||
|
@ -795,8 +788,8 @@ impl Context {
|
||||||
line!() as usize,
|
line!() as usize,
|
||||||
loc.loc(),
|
loc.loc(),
|
||||||
self.caused_by(),
|
self.caused_by(),
|
||||||
name,
|
name.inspect(),
|
||||||
self.get_similar_name(name),
|
self.get_similar_name(name.inspect()),
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -814,7 +807,6 @@ impl Context {
|
||||||
}
|
}
|
||||||
match expr {
|
match expr {
|
||||||
ast::ConstExpr::Lit(lit) => Ok(TyParam::Value(self.eval_lit(lit)?)),
|
ast::ConstExpr::Lit(lit) => Ok(TyParam::Value(self.eval_lit(lit)?)),
|
||||||
// TODO: inc_ref
|
|
||||||
ast::ConstExpr::Accessor(acc) => {
|
ast::ConstExpr::Accessor(acc) => {
|
||||||
self.instantiate_acc(acc, erased_idx, tmp_tv_cache, not_found_is_qvar)
|
self.instantiate_acc(acc, erased_idx, tmp_tv_cache, not_found_is_qvar)
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ use std::option::Option; // conflicting to Type::Option
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use erg_common::config::ErgConfig;
|
use erg_common::config::ErgConfig;
|
||||||
|
use erg_common::consts::PYTHON_MODE;
|
||||||
use erg_common::dict::Dict;
|
use erg_common::dict::Dict;
|
||||||
use erg_common::error::Location;
|
use erg_common::error::Location;
|
||||||
use erg_common::impl_display_from_debug;
|
use erg_common::impl_display_from_debug;
|
||||||
|
@ -68,7 +69,7 @@ impl TryFrom<&str> for ControlKind {
|
||||||
match s {
|
match s {
|
||||||
"if" | "if!" => Ok(ControlKind::If),
|
"if" | "if!" => Ok(ControlKind::If),
|
||||||
"while!" => Ok(ControlKind::While),
|
"while!" => Ok(ControlKind::While),
|
||||||
"while" if cfg!(feature = "py_compat") => Ok(ControlKind::While),
|
"while" if PYTHON_MODE => Ok(ControlKind::While),
|
||||||
"for" | "for!" => Ok(ControlKind::For),
|
"for" | "for!" => Ok(ControlKind::For),
|
||||||
"match" | "match!" => Ok(ControlKind::Match),
|
"match" | "match!" => Ok(ControlKind::Match),
|
||||||
"try" | "try!" => Ok(ControlKind::Try),
|
"try" | "try!" => Ok(ControlKind::Try),
|
||||||
|
@ -981,6 +982,18 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn get_module(&self) -> Option<&Context> {
|
||||||
|
self.get_outer()
|
||||||
|
.and_then(|outer| {
|
||||||
|
if outer.kind == ContextKind::Module {
|
||||||
|
Some(outer)
|
||||||
|
} else {
|
||||||
|
outer.get_module()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.or(Some(self))
|
||||||
|
}
|
||||||
|
|
||||||
/// This method is intended to be called __only__ in the top-level module.
|
/// This method is intended to be called __only__ in the top-level module.
|
||||||
/// `.cfg` is not initialized and is used around.
|
/// `.cfg` is not initialized and is used around.
|
||||||
pub fn initialize(&mut self) {
|
pub fn initialize(&mut self) {
|
||||||
|
@ -1016,6 +1029,9 @@ impl Context {
|
||||||
};
|
};
|
||||||
log!(info "{}: current namespace: {name}", fn_name!());
|
log!(info "{}: current namespace: {name}", fn_name!());
|
||||||
self.outer = Some(Box::new(mem::take(self)));
|
self.outer = Some(Box::new(mem::take(self)));
|
||||||
|
if let Some(tv_cache) = tv_cache.as_ref() {
|
||||||
|
self.assign_bounds(tv_cache)
|
||||||
|
};
|
||||||
self.cfg = self.get_outer().unwrap().cfg.clone();
|
self.cfg = self.get_outer().unwrap().cfg.clone();
|
||||||
self.shared = self.get_outer().unwrap().shared.clone();
|
self.shared = self.get_outer().unwrap().shared.clone();
|
||||||
self.tv_cache = tv_cache;
|
self.tv_cache = tv_cache;
|
||||||
|
|
|
@ -6,6 +6,7 @@ use std::process::{Command, Stdio};
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
|
|
||||||
use erg_common::config::ErgMode;
|
use erg_common::config::ErgMode;
|
||||||
|
use erg_common::consts::PYTHON_MODE;
|
||||||
use erg_common::env::erg_pystd_path;
|
use erg_common::env::erg_pystd_path;
|
||||||
use erg_common::erg_util::BUILTIN_ERG_MODS;
|
use erg_common::erg_util::BUILTIN_ERG_MODS;
|
||||||
use erg_common::levenshtein::get_similar_name;
|
use erg_common::levenshtein::get_similar_name;
|
||||||
|
@ -16,8 +17,11 @@ use erg_common::triple::Triple;
|
||||||
use erg_common::Str;
|
use erg_common::Str;
|
||||||
use erg_common::{get_hash, log, set};
|
use erg_common::{get_hash, log, set};
|
||||||
|
|
||||||
use ast::{ConstIdentifier, Decorator, DefId, Identifier, OperationKind, PolyTypeSpec, VarName};
|
use ast::{
|
||||||
use erg_parser::ast::{self, PreDeclTypeSpec};
|
ConstIdentifier, Decorator, DefId, Identifier, OperationKind, PolyTypeSpec, PreDeclTypeSpec,
|
||||||
|
VarName,
|
||||||
|
};
|
||||||
|
use erg_parser::ast;
|
||||||
|
|
||||||
use crate::ty::constructors::{
|
use crate::ty::constructors::{
|
||||||
free_var, func, func0, func1, proc, ref_, ref_mut, unknown_len_array_t, v_enum,
|
free_var, func, func0, func1, proc, ref_, ref_mut, unknown_len_array_t, v_enum,
|
||||||
|
@ -256,7 +260,7 @@ impl Context {
|
||||||
self.erg_to_py_names
|
self.erg_to_py_names
|
||||||
.insert(ident.inspect().clone(), py_name.clone());
|
.insert(ident.inspect().clone(), py_name.clone());
|
||||||
}
|
}
|
||||||
let ident = if cfg!(feature = "py_compat") && py_name.is_some() {
|
let ident = if PYTHON_MODE && py_name.is_some() {
|
||||||
let mut symbol = ident.name.clone().into_token();
|
let mut symbol = ident.name.clone().into_token();
|
||||||
symbol.content = py_name.clone().unwrap();
|
symbol.content = py_name.clone().unwrap();
|
||||||
Identifier::new(ident.vis.clone(), VarName::new(symbol))
|
Identifier::new(ident.vis.clone(), VarName::new(symbol))
|
||||||
|
@ -344,7 +348,7 @@ impl Context {
|
||||||
opt_decl_t: Option<&ParamTy>,
|
opt_decl_t: Option<&ParamTy>,
|
||||||
kind: ParamKind,
|
kind: ParamKind,
|
||||||
) -> TyCheckResult<()> {
|
) -> TyCheckResult<()> {
|
||||||
let vis = if cfg!(feature = "py_compat") {
|
let vis = if PYTHON_MODE {
|
||||||
Visibility::BUILTIN_PUBLIC
|
Visibility::BUILTIN_PUBLIC
|
||||||
} else {
|
} else {
|
||||||
Visibility::private(self.name.clone())
|
Visibility::private(self.name.clone())
|
||||||
|
@ -552,6 +556,19 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn assign_bounds(&mut self, tv_cache: &TyVarCache) {
|
||||||
|
for tyvar in tv_cache.tyvar_instances.keys() {
|
||||||
|
let vi =
|
||||||
|
VarInfo::nd_parameter(Type::Type, self.absolutize(tyvar.loc()), self.name.clone());
|
||||||
|
self.locals.insert(tyvar.clone(), vi);
|
||||||
|
}
|
||||||
|
for (typaram, tp) in tv_cache.typaram_instances.iter() {
|
||||||
|
let t = self.get_tp_t(tp).unwrap_or(Type::Obj);
|
||||||
|
let vi = VarInfo::nd_parameter(t, self.absolutize(typaram.loc()), self.name.clone());
|
||||||
|
self.locals.insert(typaram.clone(), vi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn assign_params(
|
pub(crate) fn assign_params(
|
||||||
&mut self,
|
&mut self,
|
||||||
params: &mut hir::Params,
|
params: &mut hir::Params,
|
||||||
|
@ -2003,48 +2020,53 @@ impl Context {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inc_ref_acc(&self, acc: &ast::Accessor, namespace: &Context) {
|
pub(crate) fn inc_ref<L: Locational>(&self, vi: &VarInfo, name: &L, namespace: &Context) {
|
||||||
|
self.index().inc_ref(vi, namespace.absolutize(name.loc()));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn inc_ref_acc(&self, acc: &ast::Accessor, namespace: &Context) -> bool {
|
||||||
match acc {
|
match acc {
|
||||||
ast::Accessor::Ident(ident) => self.inc_ref_local(ident, namespace),
|
ast::Accessor::Ident(ident) => self.inc_ref_local(ident, namespace),
|
||||||
ast::Accessor::Attr(attr) => {
|
ast::Accessor::Attr(attr) => {
|
||||||
self.inc_ref_expr(&attr.obj, namespace);
|
self.inc_ref_expr(&attr.obj, namespace);
|
||||||
if let Ok(ctxs) = self.get_singular_ctxs(&attr.obj, self) {
|
if let Ok(ctxs) = self.get_singular_ctxs(&attr.obj, self) {
|
||||||
if let Some(first) = ctxs.first() {
|
for ctx in ctxs {
|
||||||
first.inc_ref_local(&attr.ident, namespace);
|
if ctx.inc_ref_local(&attr.ident, namespace) {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
false
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inc_ref_expr(&self, expr: &ast::Expr, namespace: &Context) {
|
pub(crate) fn inc_ref_predecl_typespec(
|
||||||
#[allow(clippy::single_match)]
|
&self,
|
||||||
match expr {
|
predecl: &PreDeclTypeSpec,
|
||||||
ast::Expr::Accessor(acc) => self.inc_ref_acc(acc, namespace),
|
namespace: &Context,
|
||||||
// TODO:
|
) -> bool {
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn inc_ref_predecl_typespec(&self, predecl: &PreDeclTypeSpec, namespace: &Context) {
|
|
||||||
match predecl {
|
match predecl {
|
||||||
PreDeclTypeSpec::Mono(mono) => self.inc_ref_mono_typespec(mono, namespace),
|
PreDeclTypeSpec::Mono(mono) => self.inc_ref_mono_typespec(mono, namespace),
|
||||||
PreDeclTypeSpec::Poly(poly) => self.inc_ref_poly_typespec(poly, namespace),
|
PreDeclTypeSpec::Poly(poly) => self.inc_ref_poly_typespec(poly, namespace),
|
||||||
PreDeclTypeSpec::Attr { namespace: obj, t } => {
|
PreDeclTypeSpec::Attr { namespace: obj, t } => {
|
||||||
self.inc_ref_expr(obj, namespace);
|
self.inc_ref_expr(obj, namespace);
|
||||||
if let Ok(ctxs) = self.get_singular_ctxs(obj, self) {
|
if let Ok(ctxs) = self.get_singular_ctxs(obj, self) {
|
||||||
if let Some(first) = ctxs.first() {
|
for ctx in ctxs {
|
||||||
first.inc_ref_mono_typespec(t, namespace);
|
if ctx.inc_ref_mono_typespec(t, namespace) {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
// TODO:
|
// TODO:
|
||||||
_ => {}
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn inc_ref_mono_typespec(&self, ident: &Identifier, namespace: &Context) {
|
fn inc_ref_mono_typespec(&self, ident: &Identifier, namespace: &Context) -> bool {
|
||||||
if let Triple::Ok(vi) = self.rec_get_var_info(
|
if let Triple::Ok(vi) = self.rec_get_var_info(
|
||||||
ident,
|
ident,
|
||||||
crate::compile::AccessKind::Name,
|
crate::compile::AccessKind::Name,
|
||||||
|
@ -2052,22 +2074,18 @@ impl Context {
|
||||||
self,
|
self,
|
||||||
) {
|
) {
|
||||||
self.inc_ref(&vi, &ident.name, namespace);
|
self.inc_ref(&vi, &ident.name, namespace);
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TODO:
|
/// TODO: params
|
||||||
pub(crate) fn inc_ref_poly_typespec(&self, poly: &PolyTypeSpec, namespace: &Context) {
|
fn inc_ref_poly_typespec(&self, poly: &PolyTypeSpec, namespace: &Context) -> bool {
|
||||||
if let Triple::Ok(vi) = self.rec_get_var_info(
|
self.inc_ref_acc(&poly.acc.clone().downcast(), namespace)
|
||||||
&poly.ident,
|
|
||||||
crate::compile::AccessKind::Name,
|
|
||||||
&self.cfg.input,
|
|
||||||
self,
|
|
||||||
) {
|
|
||||||
self.inc_ref(&vi, &poly.ident.name, namespace);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn inc_ref_local(&self, local: &ConstIdentifier, namespace: &Context) {
|
fn inc_ref_local(&self, local: &ConstIdentifier, namespace: &Context) -> bool {
|
||||||
if let Triple::Ok(vi) = self.rec_get_var_info(
|
if let Triple::Ok(vi) = self.rec_get_var_info(
|
||||||
local,
|
local,
|
||||||
crate::compile::AccessKind::Name,
|
crate::compile::AccessKind::Name,
|
||||||
|
@ -2075,10 +2093,18 @@ impl Context {
|
||||||
self,
|
self,
|
||||||
) {
|
) {
|
||||||
self.inc_ref(&vi, &local.name, namespace);
|
self.inc_ref(&vi, &local.name, namespace);
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
&local.inspect()[..] == "module" || &local.inspect()[..] == "global"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn inc_ref<L: Locational>(&self, vi: &VarInfo, name: &L, namespace: &Context) {
|
fn inc_ref_expr(&self, expr: &ast::Expr, namespace: &Context) -> bool {
|
||||||
self.index().inc_ref(vi, namespace.absolutize(name.loc()));
|
#[allow(clippy::single_match)]
|
||||||
|
match expr {
|
||||||
|
ast::Expr::Accessor(acc) => self.inc_ref_acc(acc, namespace),
|
||||||
|
// TODO:
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use erg_common::consts::PYTHON_MODE;
|
||||||
use erg_common::traits::{Locational, Runnable, Stream};
|
use erg_common::traits::{Locational, Runnable, Stream};
|
||||||
use erg_common::{enum_unwrap, fn_name, log, set, Str};
|
use erg_common::{enum_unwrap, fn_name, log, set, Str};
|
||||||
|
|
||||||
|
@ -562,7 +563,7 @@ impl ASTLowerer {
|
||||||
Some(py_name.clone()),
|
Some(py_name.clone()),
|
||||||
self.module.context.absolutize(ident.name.loc()),
|
self.module.context.absolutize(ident.name.loc()),
|
||||||
);
|
);
|
||||||
let name = if cfg!(feature = "py_compat") {
|
let name = if PYTHON_MODE {
|
||||||
let mut symbol = ident.name.clone().into_token();
|
let mut symbol = ident.name.clone().into_token();
|
||||||
symbol.content = py_name.clone();
|
symbol.content = py_name.clone();
|
||||||
VarName::new(symbol)
|
VarName::new(symbol)
|
||||||
|
@ -571,7 +572,7 @@ impl ASTLowerer {
|
||||||
};
|
};
|
||||||
self.module.context.decls.insert(name, vi);
|
self.module.context.decls.insert(name, vi);
|
||||||
}
|
}
|
||||||
let new_ident = if cfg!(feature = "py_compat") {
|
let new_ident = if PYTHON_MODE {
|
||||||
let mut symbol = ident.name.clone().into_token();
|
let mut symbol = ident.name.clone().into_token();
|
||||||
symbol.content = py_name.clone();
|
symbol.content = py_name.clone();
|
||||||
Identifier::new(ident.vis.clone(), VarName::new(symbol))
|
Identifier::new(ident.vis.clone(), VarName::new(symbol))
|
||||||
|
@ -610,7 +611,7 @@ impl ASTLowerer {
|
||||||
if ident.is_raw() {
|
if ident.is_raw() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
let name = if cfg!(feature = "py_compat") {
|
let name = if PYTHON_MODE {
|
||||||
self.module
|
self.module
|
||||||
.context
|
.context
|
||||||
.erg_to_py_names
|
.erg_to_py_names
|
||||||
|
|
|
@ -550,6 +550,32 @@ impl LowerError {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn shadow_special_namespace_error(
|
||||||
|
input: Input,
|
||||||
|
errno: usize,
|
||||||
|
loc: Location,
|
||||||
|
caused_by: String,
|
||||||
|
name: &str,
|
||||||
|
) -> Self {
|
||||||
|
let name = StyledStr::new(readable_name(name), Some(WARN), Some(ATTR));
|
||||||
|
Self::new(
|
||||||
|
ErrorCore::new(
|
||||||
|
vec![SubMessage::only_loc(loc)],
|
||||||
|
switch_lang!(
|
||||||
|
"japanese" => format!("特殊名前空間{name}と同名の変数は定義できません"),
|
||||||
|
"simplified_chinese" => format!("不能定义与特殊命名空间{name}同名的变量"),
|
||||||
|
"traditional_chinese" => format!("不能定義與特殊命名空間{name}同名的變量"),
|
||||||
|
"english" => format!("cannot define variable with the same name as special namespace {name}"),
|
||||||
|
),
|
||||||
|
errno,
|
||||||
|
AssignError,
|
||||||
|
loc,
|
||||||
|
),
|
||||||
|
input,
|
||||||
|
caused_by,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn reassign_error(
|
pub fn reassign_error(
|
||||||
input: Input,
|
input: Input,
|
||||||
errno: usize,
|
errno: usize,
|
||||||
|
|
|
@ -4,17 +4,27 @@
|
||||||
.Hashable: ClassType
|
.Hashable: ClassType
|
||||||
.Sized: ClassType
|
.Sized: ClassType
|
||||||
.Callable: ClassType
|
.Callable: ClassType
|
||||||
|
.Callable.
|
||||||
|
__getitem__: (params: [Type; _], Type) -> Type
|
||||||
.Iterable: ClassType
|
.Iterable: ClassType
|
||||||
|
.Iterable.
|
||||||
|
__getitem__: Type -> Type
|
||||||
.Collection: ClassType
|
.Collection: ClassType
|
||||||
.Iterator: ClassType
|
.Iterator: ClassType
|
||||||
|
.Iterator.
|
||||||
|
__getitem__: Type -> Type
|
||||||
.Reversible: ClassType
|
.Reversible: ClassType
|
||||||
.Genertor: ClassType
|
.Genertor: ClassType
|
||||||
.Sequence: ClassType
|
.Sequence: ClassType
|
||||||
|
.Sequence.
|
||||||
|
__getitem__: Type -> Type
|
||||||
.MutableSqunce: ClassType
|
.MutableSqunce: ClassType
|
||||||
.ByteString: ClassType
|
.ByteString: ClassType
|
||||||
.Set: ClassType
|
.Set: ClassType
|
||||||
.MutableSet: ClassType
|
.MutableSet: ClassType
|
||||||
.Mapping: ClassType
|
.Mapping: ClassType
|
||||||
|
.Mapping.
|
||||||
|
__getitem__: (Type, Type) -> Type
|
||||||
.MutableMapping: ClassType
|
.MutableMapping: ClassType
|
||||||
.MappingView: ClassType
|
.MappingView: ClassType
|
||||||
.ItemsView: ClassType
|
.ItemsView: ClassType
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
use erg_common::config::{ErgConfig, ErgMode};
|
use erg_common::config::{ErgConfig, ErgMode};
|
||||||
|
use erg_common::consts::{ERG_MODE, PYTHON_MODE};
|
||||||
use erg_common::dict;
|
use erg_common::dict;
|
||||||
use erg_common::dict::Dict;
|
use erg_common::dict::Dict;
|
||||||
use erg_common::error::{Location, MultiErrorDisplay};
|
use erg_common::error::{Location, MultiErrorDisplay};
|
||||||
|
@ -280,7 +281,7 @@ impl ASTLowerer {
|
||||||
(false, false) => {
|
(false, false) => {
|
||||||
if let hir::Expr::TypeAsc(type_asc) = &elem {
|
if let hir::Expr::TypeAsc(type_asc) = &elem {
|
||||||
// e.g. [1, "a": Str or NoneType]
|
// e.g. [1, "a": Str or NoneType]
|
||||||
if !cfg!(feature = "py_compat")
|
if ERG_MODE
|
||||||
&& !self
|
&& !self
|
||||||
.module
|
.module
|
||||||
.context
|
.context
|
||||||
|
@ -288,7 +289,7 @@ impl ASTLowerer {
|
||||||
{
|
{
|
||||||
return Err(self.elem_err(&l, &r, &elem));
|
return Err(self.elem_err(&l, &r, &elem));
|
||||||
} // else(OK): e.g. [1, "a": Str or Int]
|
} // else(OK): e.g. [1, "a": Str or Int]
|
||||||
} else if !cfg!(feature = "py_compat") {
|
} else if ERG_MODE {
|
||||||
return Err(self.elem_err(&l, &r, &elem));
|
return Err(self.elem_err(&l, &r, &elem));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -399,7 +400,7 @@ impl ASTLowerer {
|
||||||
for elem in elems {
|
for elem in elems {
|
||||||
let elem = self.lower_expr(elem.expr)?;
|
let elem = self.lower_expr(elem.expr)?;
|
||||||
union = self.module.context.union(&union, elem.ref_t());
|
union = self.module.context.union(&union, elem.ref_t());
|
||||||
if !cfg!(feature = "py_compat") && union.is_union_type() {
|
if ERG_MODE && union.is_union_type() {
|
||||||
return Err(LowerErrors::from(LowerError::syntax_error(
|
return Err(LowerErrors::from(LowerError::syntax_error(
|
||||||
self.cfg.input.clone(),
|
self.cfg.input.clone(),
|
||||||
line!() as usize,
|
line!() as usize,
|
||||||
|
@ -515,7 +516,7 @@ impl ASTLowerer {
|
||||||
let key = self.lower_expr(kv.key)?;
|
let key = self.lower_expr(kv.key)?;
|
||||||
let value = self.lower_expr(kv.value)?;
|
let value = self.lower_expr(kv.value)?;
|
||||||
if let Some(popped_val_t) = union.insert(key.t(), value.t()) {
|
if let Some(popped_val_t) = union.insert(key.t(), value.t()) {
|
||||||
if cfg!(feature = "py_compat") {
|
if PYTHON_MODE {
|
||||||
let val_t = union.get_mut(key.ref_t()).unwrap();
|
let val_t = union.get_mut(key.ref_t()).unwrap();
|
||||||
*val_t = self.module.context.union(&mem::take(val_t), &popped_val_t);
|
*val_t = self.module.context.union(&mem::take(val_t), &popped_val_t);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1146,7 +1147,7 @@ impl ASTLowerer {
|
||||||
|
|
||||||
fn lower_lambda(&mut self, lambda: ast::Lambda) -> LowerResult<hir::Lambda> {
|
fn lower_lambda(&mut self, lambda: ast::Lambda) -> LowerResult<hir::Lambda> {
|
||||||
log!(info "entered {}({lambda})", fn_name!());
|
log!(info "entered {}({lambda})", fn_name!());
|
||||||
let in_statement = cfg!(feature = "py_compat")
|
let in_statement = PYTHON_MODE
|
||||||
&& self
|
&& self
|
||||||
.module
|
.module
|
||||||
.context
|
.context
|
||||||
|
@ -1335,7 +1336,17 @@ impl ASTLowerer {
|
||||||
} else {
|
} else {
|
||||||
Str::ever("<lambda>")
|
Str::ever("<lambda>")
|
||||||
};
|
};
|
||||||
if self
|
if ERG_MODE && (&name[..] == "module" || &name[..] == "global") {
|
||||||
|
return Err(LowerErrors::from(
|
||||||
|
LowerError::shadow_special_namespace_error(
|
||||||
|
self.cfg.input.clone(),
|
||||||
|
line!() as usize,
|
||||||
|
def.sig.loc(),
|
||||||
|
self.module.context.caused_by(),
|
||||||
|
&name,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
} else if self
|
||||||
.module
|
.module
|
||||||
.context
|
.context
|
||||||
.registered_info(&name, def.sig.is_const())
|
.registered_info(&name, def.sig.is_const())
|
||||||
|
|
|
@ -1437,15 +1437,14 @@ impl ConstSubscript {
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub enum ConstAccessor {
|
pub enum ConstAccessor {
|
||||||
Local(ConstIdentifier),
|
Local(ConstIdentifier),
|
||||||
SelfDot(ConstIdentifier),
|
|
||||||
Attr(ConstAttribute),
|
Attr(ConstAttribute),
|
||||||
TupleAttr(ConstTupleAttribute),
|
TupleAttr(ConstTupleAttribute),
|
||||||
Subscr(ConstSubscript),
|
Subscr(ConstSubscript),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_nested_display_for_enum!(ConstAccessor; Local, SelfDot, Attr, TupleAttr, Subscr);
|
impl_nested_display_for_enum!(ConstAccessor; Local, Attr, TupleAttr, Subscr);
|
||||||
impl_display_from_nested!(ConstAccessor);
|
impl_display_from_nested!(ConstAccessor);
|
||||||
impl_locational_for_enum!(ConstAccessor; Local, SelfDot, Attr, TupleAttr, Subscr);
|
impl_locational_for_enum!(ConstAccessor; Local, Attr, TupleAttr, Subscr);
|
||||||
|
|
||||||
impl ConstAccessor {
|
impl ConstAccessor {
|
||||||
pub const fn local(symbol: Token) -> Self {
|
pub const fn local(symbol: Token) -> Self {
|
||||||
|
@ -2165,31 +2164,31 @@ impl ConstArgs {
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct PolyTypeSpec {
|
pub struct PolyTypeSpec {
|
||||||
pub ident: Identifier,
|
pub acc: ConstAccessor,
|
||||||
pub args: ConstArgs, // args can be nested (e.g. Vec Vec Int)
|
pub args: ConstArgs, // args can be nested (e.g. Vec Vec Int)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for PolyTypeSpec {
|
impl fmt::Display for PolyTypeSpec {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "{}({})", self.ident, self.args)
|
write!(f, "{}({})", self.acc, self.args)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Locational for PolyTypeSpec {
|
impl Locational for PolyTypeSpec {
|
||||||
fn loc(&self) -> Location {
|
fn loc(&self) -> Location {
|
||||||
if let Some(last) = self.args.kw_args.last() {
|
if let Some(last) = self.args.kw_args.last() {
|
||||||
Location::concat(&self.ident, last)
|
Location::concat(&self.acc, last)
|
||||||
} else if let Some(last) = self.args.pos_args.last() {
|
} else if let Some(last) = self.args.pos_args.last() {
|
||||||
Location::concat(&self.ident, last)
|
Location::concat(&self.acc, last)
|
||||||
} else {
|
} else {
|
||||||
self.ident.loc()
|
self.acc.loc()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PolyTypeSpec {
|
impl PolyTypeSpec {
|
||||||
pub const fn new(ident: Identifier, args: ConstArgs) -> Self {
|
pub const fn new(acc: ConstAccessor, args: ConstArgs) -> Self {
|
||||||
Self { ident, args }
|
Self { acc, args }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2253,6 +2252,10 @@ impl PreDeclTypeSpec {
|
||||||
t,
|
t,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn poly(acc: ConstAccessor, args: ConstArgs) -> Self {
|
||||||
|
Self::Poly(PolyTypeSpec::new(acc, args))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
@ -2586,8 +2589,8 @@ impl TypeSpec {
|
||||||
Self::PreDeclTy(PreDeclTypeSpec::Mono(ident))
|
Self::PreDeclTy(PreDeclTypeSpec::Mono(ident))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn poly(ident: Identifier, args: ConstArgs) -> Self {
|
pub fn poly(acc: ConstAccessor, args: ConstArgs) -> Self {
|
||||||
Self::PreDeclTy(PreDeclTypeSpec::Poly(PolyTypeSpec::new(ident, args)))
|
Self::PreDeclTy(PreDeclTypeSpec::Poly(PolyTypeSpec::new(acc, args)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2632,11 +2635,11 @@ impl TypeSpecWithOp {
|
||||||
pub enum TypeBoundSpec {
|
pub enum TypeBoundSpec {
|
||||||
Omitted(VarName),
|
Omitted(VarName),
|
||||||
NonDefault {
|
NonDefault {
|
||||||
lhs: Token,
|
lhs: VarName,
|
||||||
spec: TypeSpecWithOp,
|
spec: TypeSpecWithOp,
|
||||||
},
|
},
|
||||||
WithDefault {
|
WithDefault {
|
||||||
lhs: Token,
|
lhs: VarName,
|
||||||
spec: Box<TypeSpecWithOp>,
|
spec: Box<TypeSpecWithOp>,
|
||||||
default: ConstExpr,
|
default: ConstExpr,
|
||||||
}, // e.g. S: Show := Str
|
}, // e.g. S: Show := Str
|
||||||
|
@ -2646,9 +2649,9 @@ impl NestedDisplay for TypeBoundSpec {
|
||||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
|
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Self::Omitted(name) => write!(f, "{name}"),
|
Self::Omitted(name) => write!(f, "{name}"),
|
||||||
Self::NonDefault { lhs, spec } => write!(f, "{}{spec}", lhs.content),
|
Self::NonDefault { lhs, spec } => write!(f, "{lhs} {spec}"),
|
||||||
Self::WithDefault { lhs, spec, default } => {
|
Self::WithDefault { lhs, spec, default } => {
|
||||||
write!(f, "{}{} := {}", lhs.content, spec, default)
|
write!(f, "{lhs} {spec} := {default}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2667,9 +2670,17 @@ impl Locational for TypeBoundSpec {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeBoundSpec {
|
impl TypeBoundSpec {
|
||||||
pub fn non_default(lhs: Token, spec: TypeSpecWithOp) -> Self {
|
pub fn non_default(lhs: VarName, spec: TypeSpecWithOp) -> Self {
|
||||||
Self::NonDefault { lhs, spec }
|
Self::NonDefault { lhs, spec }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn default(lhs: VarName, spec: TypeSpecWithOp, default: ConstExpr) -> Self {
|
||||||
|
Self::WithDefault {
|
||||||
|
lhs,
|
||||||
|
spec: Box::new(spec),
|
||||||
|
default,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
|
|
|
@ -348,7 +348,7 @@ impl Parser {
|
||||||
self.errs.push(err);
|
self.errs.push(err);
|
||||||
return Err(());
|
return Err(());
|
||||||
};
|
};
|
||||||
let bound = TypeBoundSpec::non_default(lhs.name.into_token(), tasc.t_spec);
|
let bound = TypeBoundSpec::non_default(lhs.name, tasc.t_spec);
|
||||||
Ok(bound)
|
Ok(bound)
|
||||||
}
|
}
|
||||||
Expr::Accessor(Accessor::Ident(ident)) => {
|
Expr::Accessor(Accessor::Ident(ident)) => {
|
||||||
|
|
|
@ -1887,11 +1887,7 @@ impl Parser {
|
||||||
let mut call_or_acc = self.try_reduce_acc_chain(acc, in_type_args)?;
|
let mut call_or_acc = self.try_reduce_acc_chain(acc, in_type_args)?;
|
||||||
while let Some(res) = self.opt_reduce_args(in_type_args) {
|
while let Some(res) = self.opt_reduce_args(in_type_args) {
|
||||||
let args = res.map_err(|_| self.stack_dec(fn_name!()))?;
|
let args = res.map_err(|_| self.stack_dec(fn_name!()))?;
|
||||||
let (receiver, attr_name) = match call_or_acc {
|
let call = call_or_acc.call(args);
|
||||||
Expr::Accessor(Accessor::Attr(attr)) => (*attr.obj, Some(attr.ident)),
|
|
||||||
other => (other, None),
|
|
||||||
};
|
|
||||||
let call = Call::new(receiver, attr_name, args);
|
|
||||||
call_or_acc = Expr::Call(call);
|
call_or_acc = Expr::Call(call);
|
||||||
}
|
}
|
||||||
debug_exit_info!(self);
|
debug_exit_info!(self);
|
||||||
|
|
|
@ -221,10 +221,15 @@ impl Parser {
|
||||||
let const_expr = Self::validate_const_expr(arg.expr)?;
|
let const_expr = Self::validate_const_expr(arg.expr)?;
|
||||||
kw_args.push(ConstKwArg::new(arg.keyword, const_expr));
|
kw_args.push(ConstKwArg::new(arg.keyword, const_expr));
|
||||||
}
|
}
|
||||||
Ok(PreDeclTypeSpec::Poly(PolyTypeSpec::new(
|
let acc = if let Some(attr) = call.attr_name {
|
||||||
ident,
|
ConstAccessor::attr(ConstExpr::Accessor(ConstAccessor::Local(ident)), attr)
|
||||||
|
} else {
|
||||||
|
ConstAccessor::Local(ident)
|
||||||
|
};
|
||||||
|
Ok(PreDeclTypeSpec::poly(
|
||||||
|
acc,
|
||||||
ConstArgs::new(pos_args, var_args, kw_args, paren),
|
ConstArgs::new(pos_args, var_args, kw_args, paren),
|
||||||
)))
|
))
|
||||||
}
|
}
|
||||||
other => {
|
other => {
|
||||||
let err = ParseError::simple_syntax_error(line!() as usize, other.loc());
|
let err = ParseError::simple_syntax_error(line!() as usize, other.loc());
|
||||||
|
|
|
@ -62,6 +62,40 @@ if x.is_zero(), do:
|
||||||
assert x == 0
|
assert x == 0
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Even when shadowing is performed, you can still refer to the outer variable by its "fully qualified name".
|
||||||
|
A fully qualified name is a form of name that explicitly specifies the namespace to which the variable belongs.
|
||||||
|
|
||||||
|
```erg
|
||||||
|
x = 0
|
||||||
|
if True, do: if
|
||||||
|
x = 1
|
||||||
|
assert x == 1
|
||||||
|
assert module::x == 0
|
||||||
|
|
||||||
|
C = Class()
|
||||||
|
x = 2
|
||||||
|
f() =
|
||||||
|
x = 3
|
||||||
|
assert C::x == 2
|
||||||
|
assert C::f::x == 3
|
||||||
|
```
|
||||||
|
|
||||||
|
Variables defined directly under a module belong to a special namespace called `module`. So you can refer to it as `module::x` and so on.
|
||||||
|
|
||||||
|
The special namespace includes `module`, which refers to the module itself, and `global`, which refers to the global namespace.
|
||||||
|
|
||||||
|
```erg
|
||||||
|
print! = None
|
||||||
|
|
||||||
|
global::print! "Hello, world!"
|
||||||
|
```
|
||||||
|
|
||||||
|
These namespaces cannot be shadowed. Thus, if you specify ``module::x``, ``global::print!``, etc., it will always point to the same object.
|
||||||
|
|
||||||
|
```erg,compile_fail
|
||||||
|
global = None # ERR, cannot shadow the global namespace
|
||||||
|
```
|
||||||
|
|
||||||
## Constants
|
## Constants
|
||||||
|
|
||||||
Constants are also a type of algebra. If you start an identifier with a capital letter, it is treated as a constant. They are called constants because once defined, they do not change.
|
Constants are also a type of algebra. If you start an identifier with a capital letter, it is treated as a constant. They are called constants because once defined, they do not change.
|
||||||
|
|
|
@ -68,6 +68,40 @@ if x.is_zero(), do:
|
||||||
assert x == 0
|
assert x == 0
|
||||||
```
|
```
|
||||||
|
|
||||||
|
シャドーイングが行われた場合でも、「完全修飾名」で外側の変数を参照することが出来ます。
|
||||||
|
完全修飾名とは、変数の属する名前空間を明示的に指定した形の名前のことです。
|
||||||
|
|
||||||
|
```erg
|
||||||
|
x = 0
|
||||||
|
if True, do:
|
||||||
|
x = 1
|
||||||
|
assert x == 1
|
||||||
|
assert module::x == 0
|
||||||
|
|
||||||
|
C = Class()
|
||||||
|
x = 2
|
||||||
|
f() =
|
||||||
|
x = 3
|
||||||
|
assert C::x == 2
|
||||||
|
assert C::f::x == 3
|
||||||
|
```
|
||||||
|
|
||||||
|
モジュール直下で定義された変数は、`module`という特殊な名前空間に属します。なので、`module::x`などのように参照できます。
|
||||||
|
|
||||||
|
特殊な名前空間には、モジュール自身を指す`module`と、グローバル名前空間を指す`global`があります。
|
||||||
|
|
||||||
|
```erg
|
||||||
|
print! = None
|
||||||
|
|
||||||
|
global::print! "Hello, world!"
|
||||||
|
```
|
||||||
|
|
||||||
|
これらの名前空間はシャドーイングすることが出来ません。よって、`module::x`や`global::print!`などと指定すれば、それは常に同じものを指します。
|
||||||
|
|
||||||
|
```erg,compile_fail
|
||||||
|
global = None # ERR, cannot shadow global namespace
|
||||||
|
```
|
||||||
|
|
||||||
## 定数
|
## 定数
|
||||||
|
|
||||||
定数も代数の一種です。識別子を大文字で始めると定数として扱われます。一度定義したら変わらないので、定数と呼ばれます。
|
定数も代数の一種です。識別子を大文字で始めると定数として扱われます。一度定義したら変わらないので、定数と呼ばれます。
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue