mirror of
https://github.com/erg-lang/erg.git
synced 2025-10-03 14:04:33 +00:00
Remove rust-defined python modules
This commit is contained in:
parent
d932249ec3
commit
e0d6b93abd
31 changed files with 451 additions and 327 deletions
|
@ -118,7 +118,7 @@ impl Input {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resolve(&self, path: &Path) -> Result<PathBuf, std::io::Error> {
|
pub fn local_resolve(&self, path: &Path) -> Result<PathBuf, std::io::Error> {
|
||||||
let mut dir = if let Self::File(mut path) = self.clone() {
|
let mut dir = if let Self::File(mut path) = self.clone() {
|
||||||
path.pop();
|
path.pop();
|
||||||
path
|
path
|
||||||
|
@ -127,10 +127,24 @@ impl Input {
|
||||||
};
|
};
|
||||||
dir.push(path);
|
dir.push(path);
|
||||||
dir.set_extension("er");
|
dir.set_extension("er");
|
||||||
dir.canonicalize().or_else(|_| {
|
dir.canonicalize()
|
||||||
dir.set_extension("d.er");
|
.or_else(|_| {
|
||||||
dir.canonicalize()
|
dir.pop();
|
||||||
})
|
dir.push(path);
|
||||||
|
dir.push("__init__.er"); // {path}/__init__.er
|
||||||
|
dir.canonicalize()
|
||||||
|
})
|
||||||
|
.or_else(|_| {
|
||||||
|
dir.pop(); // {path}
|
||||||
|
dir.set_extension("d.er");
|
||||||
|
dir.canonicalize()
|
||||||
|
})
|
||||||
|
.or_else(|_| {
|
||||||
|
dir.pop(); // {path}.d.er
|
||||||
|
dir.push(format!("{}.d", path.display())); // {path}.d
|
||||||
|
dir.push("__init__.d.er"); // {path}.d/__init__.d.er
|
||||||
|
dir.canonicalize()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ use erg_common::config::{ErgConfig, Input};
|
||||||
use erg_common::env::erg_std_path;
|
use erg_common::env::erg_std_path;
|
||||||
use erg_common::error::{ErrorDisplay, Location};
|
use erg_common::error::{ErrorDisplay, Location};
|
||||||
use erg_common::opcode::Opcode;
|
use erg_common::opcode::Opcode;
|
||||||
|
use erg_common::option_enum_unwrap;
|
||||||
use erg_common::traits::{Locational, Stream};
|
use erg_common::traits::{Locational, Stream};
|
||||||
use erg_common::Str;
|
use erg_common::Str;
|
||||||
use erg_common::{
|
use erg_common::{
|
||||||
|
@ -595,6 +596,10 @@ impl CodeGenerator {
|
||||||
log!(info "entered {} ({acc})", fn_name!());
|
log!(info "entered {} ({acc})", fn_name!());
|
||||||
match acc {
|
match acc {
|
||||||
Accessor::Ident(ident) => {
|
Accessor::Ident(ident) => {
|
||||||
|
if &ident.inspect()[..] == "#ModuleType" && !self.module_type_loaded {
|
||||||
|
self.load_module_type();
|
||||||
|
self.module_type_loaded = true;
|
||||||
|
}
|
||||||
self.emit_load_name_instr(ident);
|
self.emit_load_name_instr(ident);
|
||||||
}
|
}
|
||||||
Accessor::Attr(a) => {
|
Accessor::Attr(a) => {
|
||||||
|
@ -1250,6 +1255,7 @@ impl CodeGenerator {
|
||||||
|
|
||||||
fn emit_call(&mut self, call: Call) {
|
fn emit_call(&mut self, call: Call) {
|
||||||
log!(info "entered {} ({call})", fn_name!());
|
log!(info "entered {} ({call})", fn_name!());
|
||||||
|
// Python cannot distinguish at compile time between a method call and a attribute call
|
||||||
if let Some(attr_name) = call.attr_name {
|
if let Some(attr_name) = call.attr_name {
|
||||||
self.emit_call_method(*call.obj, attr_name, call.args);
|
self.emit_call_method(*call.obj, attr_name, call.args);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1275,11 +1281,7 @@ impl CodeGenerator {
|
||||||
"if" | "if!" => self.emit_if_instr(args),
|
"if" | "if!" => self.emit_if_instr(args),
|
||||||
"match" | "match!" => self.emit_match_instr(args, true),
|
"match" | "match!" => self.emit_match_instr(args, true),
|
||||||
"with!" => self.emit_with_instr(args),
|
"with!" => self.emit_with_instr(args),
|
||||||
"import" => {
|
"pyimport" | "py" => {
|
||||||
if !self.module_type_loaded {
|
|
||||||
self.load_module_type();
|
|
||||||
self.module_type_loaded = true;
|
|
||||||
}
|
|
||||||
self.emit_load_name_instr(local);
|
self.emit_load_name_instr(local);
|
||||||
self.emit_args(args, Name);
|
self.emit_args(args, Name);
|
||||||
}
|
}
|
||||||
|
@ -1445,6 +1447,33 @@ impl CodeGenerator {
|
||||||
self.stack_dec_n((1 + attrs_len + 0) - 1);
|
self.stack_dec_n((1 + attrs_len + 0) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_root(acc: &Accessor) -> Identifier {
|
||||||
|
match acc {
|
||||||
|
Accessor::Ident(ident) => ident.clone(),
|
||||||
|
Accessor::Attr(attr) => {
|
||||||
|
if let Expr::Accessor(acc) = attr.obj.as_ref() {
|
||||||
|
Self::get_root(acc)
|
||||||
|
} else {
|
||||||
|
todo!("{:?}", attr.obj)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn emit_import(&mut self, acc: Accessor) {
|
||||||
|
self.emit_load_const(0i32);
|
||||||
|
self.emit_load_const(ValueObj::None);
|
||||||
|
let full_name = Str::from(acc.show());
|
||||||
|
let name = self
|
||||||
|
.local_search(&full_name, Name)
|
||||||
|
.unwrap_or_else(|| self.register_name(full_name));
|
||||||
|
self.write_instr(IMPORT_NAME);
|
||||||
|
self.write_arg(name.idx as u8);
|
||||||
|
let root = Self::get_root(&acc);
|
||||||
|
self.emit_store_instr(root, Name);
|
||||||
|
self.stack_dec();
|
||||||
|
}
|
||||||
|
|
||||||
fn emit_expr(&mut self, expr: Expr) {
|
fn emit_expr(&mut self, expr: Expr) {
|
||||||
log!(info "entered {} ({expr})", fn_name!());
|
log!(info "entered {} ({expr})", fn_name!());
|
||||||
if expr.ln_begin().unwrap_or_else(|| panic!("{expr}")) > self.cur_block().prev_lineno {
|
if expr.ln_begin().unwrap_or_else(|| panic!("{expr}")) > self.cur_block().prev_lineno {
|
||||||
|
@ -1574,15 +1603,31 @@ impl CodeGenerator {
|
||||||
self.emit_load_const(code);
|
self.emit_load_const(code);
|
||||||
}
|
}
|
||||||
Expr::Compound(chunks) => {
|
Expr::Compound(chunks) => {
|
||||||
if !self.module_type_loaded {
|
let is_module_loading_chunks = chunks
|
||||||
|
.get(2)
|
||||||
|
.map(|chunk| {
|
||||||
|
option_enum_unwrap!(chunk, Expr::Call)
|
||||||
|
.map(|call| {
|
||||||
|
call.obj.show_acc().as_ref().map(|s| &s[..]) == Some("exec")
|
||||||
|
})
|
||||||
|
.unwrap_or(false)
|
||||||
|
})
|
||||||
|
.unwrap_or(false);
|
||||||
|
if !self.module_type_loaded && is_module_loading_chunks {
|
||||||
self.load_module_type();
|
self.load_module_type();
|
||||||
self.module_type_loaded = true;
|
self.module_type_loaded = true;
|
||||||
}
|
}
|
||||||
self.emit_frameless_block(chunks, vec![]);
|
for expr in chunks.into_iter() {
|
||||||
|
self.emit_expr(expr);
|
||||||
|
}
|
||||||
|
if is_module_loading_chunks {
|
||||||
|
self.stack_dec_n(2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Expr::TypeAsc(tasc) => {
|
Expr::TypeAsc(tasc) => {
|
||||||
self.emit_expr(*tasc.expr);
|
self.emit_expr(*tasc.expr);
|
||||||
}
|
}
|
||||||
|
Expr::Import(acc) => self.emit_import(acc),
|
||||||
other => {
|
other => {
|
||||||
CompileError::feature_error(self.cfg.input.clone(), other.loc(), "??", "".into())
|
CompileError::feature_error(self.cfg.input.clone(), other.loc(), "??", "".into())
|
||||||
.write_to_stderr();
|
.write_to_stderr();
|
||||||
|
|
|
@ -1047,8 +1047,12 @@ impl Context {
|
||||||
);
|
);
|
||||||
generic_module.register_trait(g_module_t.clone(), generic_module_eq);
|
generic_module.register_trait(g_module_t.clone(), generic_module_eq);
|
||||||
let module_t = module(mono_q_tp("Path"));
|
let module_t = module(mono_q_tp("Path"));
|
||||||
|
let py_module_t = py_module(mono_q_tp("Path"));
|
||||||
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("PyModule", vec![PS::named_nd("Path", Str)], 2);
|
||||||
|
py_module.register_superclass(g_module_t.clone(), &generic_module);
|
||||||
/* Array */
|
/* Array */
|
||||||
let mut array_ =
|
let mut array_ =
|
||||||
Self::builtin_poly_class("Array", vec![PS::t_nd("T"), PS::named_nd("N", Nat)], 10);
|
Self::builtin_poly_class("Array", vec![PS::t_nd("T"), PS::named_nd("N", Nat)], 10);
|
||||||
|
@ -1536,7 +1540,8 @@ impl Context {
|
||||||
Const,
|
Const,
|
||||||
Some("ModuleType"),
|
Some("ModuleType"),
|
||||||
);
|
);
|
||||||
self.register_builtin_type(module_t, module, Private, Const, Some("Module"));
|
self.register_builtin_type(module_t, module, Private, Const, Some("ModuleType"));
|
||||||
|
self.register_builtin_type(py_module_t, py_module, Private, Const, Some("ModuleType"));
|
||||||
self.register_builtin_type(arr_t, array_, Private, Const, Some("list"));
|
self.register_builtin_type(arr_t, array_, Private, Const, Some("list"));
|
||||||
self.register_builtin_type(set_t, set_, Private, Const, Some("set"));
|
self.register_builtin_type(set_t, set_, Private, Const, Some("set"));
|
||||||
self.register_builtin_type(g_dict_t, generic_dict, Private, Const, Some("dict"));
|
self.register_builtin_type(g_dict_t, generic_dict, Private, Const, Some("dict"));
|
||||||
|
@ -1708,7 +1713,7 @@ impl Context {
|
||||||
let t_pyimport = nd_func(
|
let t_pyimport = nd_func(
|
||||||
vec![anon(tp_enum(Str, set! {mono_q_tp("Path")}))],
|
vec![anon(tp_enum(Str, set! {mono_q_tp("Path")}))],
|
||||||
None,
|
None,
|
||||||
module(mono_q_tp("Path")),
|
py_module(mono_q_tp("Path")),
|
||||||
);
|
);
|
||||||
let t_pyimport = quant(t_pyimport, set! {static_instance("Path", Str)});
|
let t_pyimport = quant(t_pyimport, set! {static_instance("Path", Str)});
|
||||||
let t_quit = func(vec![], None, vec![kw("code", Int)], NoneType);
|
let t_quit = func(vec![], None, vec![kw("code", Int)], NoneType);
|
||||||
|
|
|
@ -3,9 +3,5 @@ pub mod importlib;
|
||||||
pub mod io;
|
pub mod io;
|
||||||
pub mod math;
|
pub mod math;
|
||||||
pub mod os;
|
pub mod os;
|
||||||
pub mod random;
|
|
||||||
pub mod re;
|
|
||||||
pub mod socket;
|
pub mod socket;
|
||||||
pub mod sys;
|
pub mod sys;
|
||||||
pub mod time;
|
|
||||||
pub mod urllib;
|
|
||||||
|
|
|
@ -1,49 +0,0 @@
|
||||||
use erg_common::set;
|
|
||||||
use erg_common::vis::Visibility;
|
|
||||||
|
|
||||||
use crate::ty::constructors::{
|
|
||||||
kw, mono, mono_q, nd_proc, poly, proc, quant, static_instance, ty_tp,
|
|
||||||
};
|
|
||||||
use crate::ty::Type;
|
|
||||||
use Type::*;
|
|
||||||
|
|
||||||
use crate::context::Context;
|
|
||||||
use crate::varinfo::Mutability;
|
|
||||||
use Mutability::*;
|
|
||||||
use Visibility::*;
|
|
||||||
|
|
||||||
impl Context {
|
|
||||||
pub(crate) fn init_py_random_mod() -> Self {
|
|
||||||
let mut random = Context::builtin_module("random", 10);
|
|
||||||
random.register_builtin_py_impl(
|
|
||||||
"seed!",
|
|
||||||
proc(
|
|
||||||
vec![],
|
|
||||||
None,
|
|
||||||
vec![
|
|
||||||
kw("a", mono("Num")), // TODO: NoneType, int, float, str, bytes, bytearray
|
|
||||||
kw("version", Int),
|
|
||||||
],
|
|
||||||
NoneType,
|
|
||||||
),
|
|
||||||
Immutable,
|
|
||||||
Public,
|
|
||||||
Some("seed"),
|
|
||||||
);
|
|
||||||
random.register_builtin_py_impl(
|
|
||||||
"randint!",
|
|
||||||
nd_proc(vec![kw("a", Int), kw("b", Int)], None, Int),
|
|
||||||
Immutable,
|
|
||||||
Public,
|
|
||||||
Some("randint"),
|
|
||||||
);
|
|
||||||
let t = nd_proc(
|
|
||||||
vec![kw("seq", poly("Seq", vec![ty_tp(mono_q("T"))]))],
|
|
||||||
None,
|
|
||||||
mono_q("T"),
|
|
||||||
);
|
|
||||||
let t = quant(t, set! {static_instance("T", Type)});
|
|
||||||
random.register_builtin_py_impl("choice!", t, Immutable, Public, Some("choice"));
|
|
||||||
random
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
use erg_common::vis::Visibility;
|
|
||||||
|
|
||||||
use crate::ty::constructors::{func, kw};
|
|
||||||
use crate::ty::Type;
|
|
||||||
use Type::*;
|
|
||||||
|
|
||||||
use crate::context::Context;
|
|
||||||
use crate::varinfo::Mutability;
|
|
||||||
use Mutability::*;
|
|
||||||
use Visibility::*;
|
|
||||||
|
|
||||||
impl Context {
|
|
||||||
pub(crate) fn init_py_re_mod() -> Self {
|
|
||||||
let mut re = Context::builtin_module("re", 10);
|
|
||||||
re.register_builtin_impl(
|
|
||||||
"sub",
|
|
||||||
func(
|
|
||||||
vec![kw("pattern", Str), kw("repl", Str), kw("string", Str)],
|
|
||||||
None,
|
|
||||||
vec![kw("count", Nat)],
|
|
||||||
Str,
|
|
||||||
),
|
|
||||||
Immutable,
|
|
||||||
Public,
|
|
||||||
);
|
|
||||||
re
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
use erg_common::vis::Visibility;
|
|
||||||
|
|
||||||
use crate::ty::constructors::{proc0, proc1};
|
|
||||||
use crate::ty::Type;
|
|
||||||
use Type::*;
|
|
||||||
|
|
||||||
use crate::context::Context;
|
|
||||||
use crate::varinfo::Mutability;
|
|
||||||
use Mutability::*;
|
|
||||||
use Visibility::*;
|
|
||||||
|
|
||||||
impl Context {
|
|
||||||
pub(crate) fn init_py_time_mod() -> Self {
|
|
||||||
let mut time = Context::builtin_module("time", 15);
|
|
||||||
time.register_builtin_py_impl(
|
|
||||||
"sleep!",
|
|
||||||
proc1(Float, NoneType),
|
|
||||||
Immutable,
|
|
||||||
Public,
|
|
||||||
Some("sleep"),
|
|
||||||
);
|
|
||||||
time.register_builtin_py_impl("time!", proc0(Float), Immutable, Public, Some("time"));
|
|
||||||
time
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,54 +0,0 @@
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
use erg_common::vis::Visibility;
|
|
||||||
|
|
||||||
use crate::ty::constructors::{kw, module_from_path, mono, or, proc};
|
|
||||||
use crate::ty::Type;
|
|
||||||
use Type::*;
|
|
||||||
|
|
||||||
use crate::context::Context;
|
|
||||||
use crate::mod_cache::SharedModuleCache;
|
|
||||||
use crate::varinfo::Mutability;
|
|
||||||
use Mutability::*;
|
|
||||||
use Visibility::*;
|
|
||||||
|
|
||||||
impl Context {
|
|
||||||
pub(crate) fn init_py_urllib_mod() -> Self {
|
|
||||||
let mut urllib = Context::builtin_module("urllib", 4);
|
|
||||||
urllib.py_mod_cache = Some(SharedModuleCache::new());
|
|
||||||
let mut request_class = Context::builtin_mono_class("Request", 5);
|
|
||||||
request_class.register_builtin_impl("data", mono("Bytes"), Immutable, Public);
|
|
||||||
urllib.register_builtin_type(
|
|
||||||
mono("urllib.request.Request"),
|
|
||||||
request_class,
|
|
||||||
Public,
|
|
||||||
Const,
|
|
||||||
Some("urllib.request.Request"),
|
|
||||||
);
|
|
||||||
urllib.register_builtin_impl("request", module_from_path("request"), Immutable, Public);
|
|
||||||
let mut request = Context::builtin_module("urllib.request", 15);
|
|
||||||
let t = proc(
|
|
||||||
vec![kw("url", or(Str, mono("urllib.request.Request")))],
|
|
||||||
None,
|
|
||||||
vec![
|
|
||||||
kw("data", or(mono("Bytes"), NoneType)),
|
|
||||||
kw("timeout", or(Nat, NoneType)),
|
|
||||||
],
|
|
||||||
mono("http.client.HTTPResponse"),
|
|
||||||
);
|
|
||||||
request.register_builtin_py_impl("urlopen!", t, Immutable, Public, Some("urlopen"));
|
|
||||||
urllib.register_builtin_impl("parse", module_from_path("parse"), Immutable, Public);
|
|
||||||
let parse = Context::builtin_module("urllib.parse", 15);
|
|
||||||
urllib
|
|
||||||
.py_mod_cache
|
|
||||||
.as_ref()
|
|
||||||
.unwrap()
|
|
||||||
.register(PathBuf::from("request"), None, request);
|
|
||||||
urllib
|
|
||||||
.py_mod_cache
|
|
||||||
.as_ref()
|
|
||||||
.unwrap()
|
|
||||||
.register(PathBuf::from("parse"), None, parse);
|
|
||||||
urllib
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -17,7 +17,7 @@ use ast::VarName;
|
||||||
use erg_parser::ast::{self, Identifier};
|
use erg_parser::ast::{self, Identifier};
|
||||||
use erg_parser::token::Token;
|
use erg_parser::token::Token;
|
||||||
|
|
||||||
use crate::ty::constructors::{anon, free_var, func, module, mono, poly, proj, subr_t, v_enum};
|
use crate::ty::constructors::{anon, free_var, func, mono, poly, proj, subr_t};
|
||||||
use crate::ty::free::Constraint;
|
use crate::ty::free::Constraint;
|
||||||
use crate::ty::typaram::TyParam;
|
use crate::ty::typaram::TyParam;
|
||||||
use crate::ty::value::{GenTypeObj, TypeObj, ValueObj};
|
use crate::ty::value::{GenTypeObj, TypeObj, ValueObj};
|
||||||
|
@ -116,7 +116,7 @@ impl Context {
|
||||||
self.locals.get_key_value(name)
|
self.locals.get_key_value(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_singular_ctx(
|
pub(crate) fn get_singular_ctx_by_hir_expr(
|
||||||
&self,
|
&self,
|
||||||
obj: &hir::Expr,
|
obj: &hir::Expr,
|
||||||
namespace: &Str,
|
namespace: &Str,
|
||||||
|
@ -127,9 +127,9 @@ impl Context {
|
||||||
}
|
}
|
||||||
hir::Expr::Accessor(hir::Accessor::Attr(attr)) => {
|
hir::Expr::Accessor(hir::Accessor::Attr(attr)) => {
|
||||||
// REVIEW: 両方singularとは限らない?
|
// REVIEW: 両方singularとは限らない?
|
||||||
let ctx = self.get_singular_ctx(&attr.obj, namespace)?;
|
let ctx = self.get_singular_ctx_by_hir_expr(&attr.obj, namespace)?;
|
||||||
let attr = hir::Expr::Accessor(hir::Accessor::Ident(attr.ident.clone()));
|
let attr = hir::Expr::Accessor(hir::Accessor::Ident(attr.ident.clone()));
|
||||||
ctx.get_singular_ctx(&attr, namespace)
|
ctx.get_singular_ctx_by_hir_expr(&attr, namespace)
|
||||||
}
|
}
|
||||||
// TODO: change error
|
// TODO: change error
|
||||||
_ => Err(TyCheckError::no_var_error(
|
_ => Err(TyCheckError::no_var_error(
|
||||||
|
@ -180,6 +180,32 @@ impl Context {
|
||||||
.ok_or(err)
|
.ok_or(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn get_singular_ctx(
|
||||||
|
&self,
|
||||||
|
obj: &ast::Expr,
|
||||||
|
namespace: &Str,
|
||||||
|
) -> SingleTyCheckResult<&Context> {
|
||||||
|
match obj {
|
||||||
|
ast::Expr::Accessor(ast::Accessor::Ident(ident)) => {
|
||||||
|
self.get_singular_ctx_by_ident(ident, namespace)
|
||||||
|
}
|
||||||
|
ast::Expr::Accessor(ast::Accessor::Attr(attr)) => {
|
||||||
|
// REVIEW: 両方singularとは限らない?
|
||||||
|
let ctx = self.get_singular_ctx(&attr.obj, namespace)?;
|
||||||
|
let attr = ast::Expr::Accessor(ast::Accessor::Ident(attr.ident.clone()));
|
||||||
|
ctx.get_singular_ctx(&attr, namespace)
|
||||||
|
}
|
||||||
|
_ => Err(TyCheckError::no_var_error(
|
||||||
|
self.cfg.input.clone(),
|
||||||
|
line!() as usize,
|
||||||
|
obj.loc(),
|
||||||
|
self.caused_by(),
|
||||||
|
&obj.to_string(),
|
||||||
|
None,
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn get_mut_singular_ctx(
|
pub(crate) fn get_mut_singular_ctx(
|
||||||
&mut self,
|
&mut self,
|
||||||
obj: &ast::Expr,
|
obj: &ast::Expr,
|
||||||
|
@ -291,7 +317,7 @@ impl Context {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_import_call_t(
|
/*fn get_import_call_t(
|
||||||
&self,
|
&self,
|
||||||
pos_args: &[hir::PosArg],
|
pos_args: &[hir::PosArg],
|
||||||
kw_args: &[hir::KwArg],
|
kw_args: &[hir::KwArg],
|
||||||
|
@ -346,7 +372,7 @@ impl Context {
|
||||||
py_name: Some(Str::ever("__import__")),
|
py_name: Some(Str::ever("__import__")),
|
||||||
..VarInfo::default()
|
..VarInfo::default()
|
||||||
})
|
})
|
||||||
}
|
}*/
|
||||||
|
|
||||||
pub(crate) fn rec_get_var_info(
|
pub(crate) fn rec_get_var_info(
|
||||||
&self,
|
&self,
|
||||||
|
@ -430,7 +456,7 @@ impl Context {
|
||||||
return Err(e);
|
return Err(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Ok(singular_ctx) = self.get_singular_ctx(obj, namespace) {
|
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) {
|
match singular_ctx.rec_get_var_info(ident, AccessKind::Attr, input, namespace) {
|
||||||
Ok(vi) => {
|
Ok(vi) => {
|
||||||
return Ok(vi);
|
return Ok(vi);
|
||||||
|
@ -608,7 +634,7 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Ok(singular_ctx) = self.get_singular_ctx(obj, namespace) {
|
if let Ok(singular_ctx) = self.get_singular_ctx_by_hir_expr(obj, namespace) {
|
||||||
if let Some(vi) = singular_ctx
|
if let Some(vi) = singular_ctx
|
||||||
.locals
|
.locals
|
||||||
.get(attr_name.inspect())
|
.get(attr_name.inspect())
|
||||||
|
@ -1133,13 +1159,14 @@ impl Context {
|
||||||
) -> TyCheckResult<VarInfo> {
|
) -> TyCheckResult<VarInfo> {
|
||||||
if let hir::Expr::Accessor(hir::Accessor::Ident(local)) = obj {
|
if let hir::Expr::Accessor(hir::Accessor::Ident(local)) = obj {
|
||||||
if local.vis().is_private() {
|
if local.vis().is_private() {
|
||||||
|
#[allow(clippy::single_match)]
|
||||||
match &local.inspect()[..] {
|
match &local.inspect()[..] {
|
||||||
"match" => {
|
"match" => {
|
||||||
return self.get_match_call_t(pos_args, kw_args);
|
return self.get_match_call_t(pos_args, kw_args);
|
||||||
}
|
}
|
||||||
"import" | "pyimport" | "py" => {
|
/*"import" | "pyimport" | "py" => {
|
||||||
return self.get_import_call_t(pos_args, kw_args);
|
return self.get_import_call_t(pos_args, kw_args);
|
||||||
}
|
}*/
|
||||||
// handle assert casting
|
// handle assert casting
|
||||||
/*"assert" => {
|
/*"assert" => {
|
||||||
if let Some(arg) = pos_args.first() {
|
if let Some(arg) = pos_args.first() {
|
||||||
|
@ -1263,7 +1290,7 @@ impl Context {
|
||||||
obj: &hir::Expr,
|
obj: &hir::Expr,
|
||||||
name: &str,
|
name: &str,
|
||||||
) -> Option<&'a str> {
|
) -> Option<&'a str> {
|
||||||
if let Ok(ctx) = self.get_singular_ctx(obj, &self.name) {
|
if let Ok(ctx) = self.get_singular_ctx_by_hir_expr(obj, &self.name) {
|
||||||
if let Some(name) = ctx.get_similar_name(name) {
|
if let Some(name) = ctx.get_similar_name(name) {
|
||||||
return Some(name);
|
return Some(name);
|
||||||
}
|
}
|
||||||
|
@ -1707,13 +1734,19 @@ impl Context {
|
||||||
|
|
||||||
// TODO: erg std
|
// TODO: erg std
|
||||||
pub(crate) fn resolve_path(&self, path: &Path) -> PathBuf {
|
pub(crate) fn resolve_path(&self, path: &Path) -> PathBuf {
|
||||||
if let Ok(path) = self.cfg.input.resolve(path) {
|
if let Ok(path) = self.cfg.input.local_resolve(path) {
|
||||||
path
|
path
|
||||||
} else if let Ok(path) = erg_pystd_path()
|
} else if let Ok(path) = erg_pystd_path()
|
||||||
.join(format!("{}.d.er", path.display()))
|
.join(format!("{}.d.er", path.display()))
|
||||||
.canonicalize()
|
.canonicalize()
|
||||||
{
|
{
|
||||||
path
|
path
|
||||||
|
} else if let Ok(path) = erg_pystd_path()
|
||||||
|
.join(format!("{}.d", path.display()))
|
||||||
|
.join("__init__.d.er")
|
||||||
|
.canonicalize()
|
||||||
|
{
|
||||||
|
path
|
||||||
} else {
|
} else {
|
||||||
PathBuf::from(format!("<builtins>.{}", path.display()))
|
PathBuf::from(format!("<builtins>.{}", path.display()))
|
||||||
}
|
}
|
||||||
|
@ -1722,21 +1755,20 @@ 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> {
|
||||||
let t = self.get_var_info(name).map(|(_, vi)| vi.t.clone()).ok()?;
|
let t = self.get_var_info(name).map(|(_, vi)| vi.t.clone()).ok()?;
|
||||||
match t {
|
if t.is_module() {
|
||||||
Type::Poly { name, mut params } if &name[..] == "Module" => {
|
let path =
|
||||||
let path =
|
option_enum_unwrap!(t.typarams().remove(0), TyParam::Value:(ValueObj::Str:(_)))?;
|
||||||
option_enum_unwrap!(params.remove(0), TyParam::Value:(ValueObj::Str:(_)))?;
|
let path = self.resolve_path(Path::new(&path[..]));
|
||||||
let path = self.resolve_path(Path::new(&path[..]));
|
self.mod_cache
|
||||||
self.mod_cache
|
.as_ref()
|
||||||
.as_ref()
|
.and_then(|cache| cache.ref_ctx(&path))
|
||||||
.and_then(|cache| cache.ref_ctx(&path))
|
.or_else(|| {
|
||||||
.or_else(|| {
|
self.py_mod_cache
|
||||||
self.py_mod_cache
|
.as_ref()
|
||||||
.as_ref()
|
.and_then(|cache| cache.ref_ctx(&path))
|
||||||
.and_then(|cache| cache.ref_ctx(&path))
|
})
|
||||||
})
|
} else {
|
||||||
}
|
None
|
||||||
_ => None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -637,7 +637,23 @@ impl Context {
|
||||||
ast::PreDeclTypeSpec::Simple(simple) => {
|
ast::PreDeclTypeSpec::Simple(simple) => {
|
||||||
self.instantiate_simple_t(simple, opt_decl_t, tmp_tv_ctx)
|
self.instantiate_simple_t(simple, opt_decl_t, tmp_tv_ctx)
|
||||||
}
|
}
|
||||||
_ => todo!(),
|
ast::PreDeclTypeSpec::Attr { namespace, t } => {
|
||||||
|
let ctx = self.get_singular_ctx(namespace.as_ref(), &self.name)?;
|
||||||
|
if let Some((typ, _)) = ctx.rec_get_type(t.ident.inspect()) {
|
||||||
|
// TODO: visibility check
|
||||||
|
Ok(typ.clone())
|
||||||
|
} else {
|
||||||
|
Err(TyCheckErrors::from(TyCheckError::no_var_error(
|
||||||
|
self.cfg.input.clone(),
|
||||||
|
line!() as usize,
|
||||||
|
t.loc(),
|
||||||
|
self.caused_by(),
|
||||||
|
t.ident.inspect(),
|
||||||
|
self.get_similar_name(t.ident.inspect()),
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
other => todo!("{other}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -647,7 +663,7 @@ impl Context {
|
||||||
opt_decl_t: Option<&ParamTy>,
|
opt_decl_t: Option<&ParamTy>,
|
||||||
tmp_tv_ctx: Option<&TyVarInstContext>,
|
tmp_tv_ctx: Option<&TyVarInstContext>,
|
||||||
) -> TyCheckResult<Type> {
|
) -> TyCheckResult<Type> {
|
||||||
match &simple.name.inspect()[..] {
|
match &simple.ident.inspect()[..] {
|
||||||
"_" | "Obj" => Ok(Type::Obj),
|
"_" | "Obj" => Ok(Type::Obj),
|
||||||
"Nat" => Ok(Type::Nat),
|
"Nat" => Ok(Type::Nat),
|
||||||
"Int" => Ok(Type::Int),
|
"Int" => Ok(Type::Int),
|
||||||
|
|
|
@ -275,24 +275,6 @@ pub enum RegistrationMode {
|
||||||
Normal,
|
Normal,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Some Erg functions require additional operation by the compiler.
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
||||||
pub enum OperationKind {
|
|
||||||
Import,
|
|
||||||
PyImport,
|
|
||||||
Del,
|
|
||||||
AssertCast,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl OperationKind {
|
|
||||||
pub const fn is_erg_import(&self) -> bool {
|
|
||||||
matches!(self, Self::Import)
|
|
||||||
}
|
|
||||||
pub const fn is_py_import(&self) -> bool {
|
|
||||||
matches!(self, Self::PyImport)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub struct ContextInfo {
|
pub struct ContextInfo {
|
||||||
mod_id: usize,
|
mod_id: usize,
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
use std::option::Option;
|
use std::option::Option;
|
||||||
use std::path::PathBuf;
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use crate::ty::free::HasLevel;
|
use erg_common::config::ErgConfig;
|
||||||
use erg_common::config::{ErgConfig, Input};
|
|
||||||
use erg_common::env::erg_pystd_path;
|
|
||||||
use erg_common::levenshtein::get_similar_name;
|
use erg_common::levenshtein::get_similar_name;
|
||||||
use erg_common::python_util::BUILTIN_PYTHON_MODS;
|
use erg_common::python_util::BUILTIN_PYTHON_MODS;
|
||||||
use erg_common::set::Set;
|
use erg_common::set::Set;
|
||||||
|
@ -12,11 +10,11 @@ use erg_common::vis::Visibility;
|
||||||
use erg_common::Str;
|
use erg_common::Str;
|
||||||
use erg_common::{enum_unwrap, get_hash, log, option_enum_unwrap, set};
|
use erg_common::{enum_unwrap, get_hash, log, option_enum_unwrap, set};
|
||||||
|
|
||||||
use ast::{DefId, Identifier, VarName};
|
use ast::{Decorator, DefId, Identifier, OperationKind, VarName};
|
||||||
use erg_parser::ast::{self, Decorator};
|
use erg_parser::ast;
|
||||||
|
|
||||||
use crate::ty::constructors::{free_var, func, func1, proc, ref_, ref_mut, v_enum};
|
use crate::ty::constructors::{free_var, func, func1, proc, ref_, ref_mut, v_enum};
|
||||||
use crate::ty::free::{Constraint, Cyclicity, FreeKind};
|
use crate::ty::free::{Constraint, Cyclicity, FreeKind, HasLevel};
|
||||||
use crate::ty::value::{GenTypeObj, TypeKind, TypeObj, ValueObj};
|
use crate::ty::value::{GenTypeObj, TypeKind, TypeObj, ValueObj};
|
||||||
use crate::ty::{HasType, ParamTy, SubrType, Type};
|
use crate::ty::{HasType, ParamTy, SubrType, Type};
|
||||||
|
|
||||||
|
@ -37,7 +35,6 @@ use RegistrationMode::*;
|
||||||
use Visibility::*;
|
use Visibility::*;
|
||||||
|
|
||||||
use super::instantiate::TyVarInstContext;
|
use super::instantiate::TyVarInstContext;
|
||||||
use super::OperationKind;
|
|
||||||
|
|
||||||
impl Context {
|
impl Context {
|
||||||
/// If it is a constant that is defined, there must be no variable of the same name defined across all scopes
|
/// If it is a constant that is defined, there must be no variable of the same name defined across all scopes
|
||||||
|
@ -1041,14 +1038,7 @@ impl Context {
|
||||||
mod_cache: &SharedModuleCache,
|
mod_cache: &SharedModuleCache,
|
||||||
py_mod_cache: &SharedModuleCache,
|
py_mod_cache: &SharedModuleCache,
|
||||||
) -> CompileResult<PathBuf> {
|
) -> CompileResult<PathBuf> {
|
||||||
let mut dir = if let Input::File(mut path) = self.cfg.input.clone() {
|
let path = match self.cfg.input.local_resolve(Path::new(&__name__[..])) {
|
||||||
path.pop();
|
|
||||||
path
|
|
||||||
} else {
|
|
||||||
PathBuf::new()
|
|
||||||
};
|
|
||||||
dir.push(format!("{__name__}.er"));
|
|
||||||
let path = match dir.canonicalize() {
|
|
||||||
Ok(path) => path,
|
Ok(path) => path,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
let err = TyCheckErrors::from(TyCheckError::import_error(
|
let err = TyCheckErrors::from(TyCheckError::import_error(
|
||||||
|
@ -1118,14 +1108,6 @@ impl Context {
|
||||||
py_mod_cache.register(builtin_path.clone(), None, Self::init_py_os_mod());
|
py_mod_cache.register(builtin_path.clone(), None, Self::init_py_os_mod());
|
||||||
Ok(builtin_path)
|
Ok(builtin_path)
|
||||||
}
|
}
|
||||||
"random" => {
|
|
||||||
py_mod_cache.register(builtin_path.clone(), None, Self::init_py_random_mod());
|
|
||||||
Ok(builtin_path)
|
|
||||||
}
|
|
||||||
"re" => {
|
|
||||||
py_mod_cache.register(builtin_path.clone(), None, Self::init_py_re_mod());
|
|
||||||
Ok(builtin_path)
|
|
||||||
}
|
|
||||||
"socket" => {
|
"socket" => {
|
||||||
py_mod_cache.register(builtin_path.clone(), None, Self::init_py_socket_mod());
|
py_mod_cache.register(builtin_path.clone(), None, Self::init_py_socket_mod());
|
||||||
Ok(builtin_path)
|
Ok(builtin_path)
|
||||||
|
@ -1134,14 +1116,6 @@ impl Context {
|
||||||
py_mod_cache.register(builtin_path.clone(), None, Self::init_py_sys_mod());
|
py_mod_cache.register(builtin_path.clone(), None, Self::init_py_sys_mod());
|
||||||
Ok(builtin_path)
|
Ok(builtin_path)
|
||||||
}
|
}
|
||||||
"time" => {
|
|
||||||
py_mod_cache.register(builtin_path.clone(), None, Self::init_py_time_mod());
|
|
||||||
Ok(builtin_path)
|
|
||||||
}
|
|
||||||
"urllib" => {
|
|
||||||
py_mod_cache.register(builtin_path.clone(), None, Self::init_py_urllib_mod());
|
|
||||||
Ok(builtin_path)
|
|
||||||
}
|
|
||||||
_ => self.import_py_mod(mod_name),
|
_ => self.import_py_mod(mod_name),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1150,27 +1124,12 @@ impl Context {
|
||||||
get_similar_name(BUILTIN_PYTHON_MODS.into_iter(), name).map(Str::rc)
|
get_similar_name(BUILTIN_PYTHON_MODS.into_iter(), name).map(Str::rc)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_decl_in_pystd(__name__: &str) -> std::io::Result<PathBuf> {
|
|
||||||
let mut as_std_path = erg_pystd_path().join(__name__);
|
|
||||||
as_std_path.set_extension("d.er");
|
|
||||||
as_std_path.canonicalize()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn import_py_mod(&self, mod_name: &Literal) -> CompileResult<PathBuf> {
|
fn import_py_mod(&self, mod_name: &Literal) -> CompileResult<PathBuf> {
|
||||||
let __name__ = enum_unwrap!(mod_name.value.clone(), ValueObj::Str);
|
let __name__ = enum_unwrap!(mod_name.value.clone(), ValueObj::Str);
|
||||||
let mod_cache = self.mod_cache.as_ref().unwrap();
|
let mod_cache = self.mod_cache.as_ref().unwrap();
|
||||||
let py_mod_cache = self.py_mod_cache.as_ref().unwrap();
|
let py_mod_cache = self.py_mod_cache.as_ref().unwrap();
|
||||||
let mut dir = if let Input::File(mut path) = self.cfg.input.clone() {
|
let path = self.resolve_path(Path::new(&__name__[..]));
|
||||||
path.pop();
|
let path = match path.canonicalize() {
|
||||||
path
|
|
||||||
} else {
|
|
||||||
PathBuf::new()
|
|
||||||
};
|
|
||||||
dir.push(format!("{__name__}.d.er"));
|
|
||||||
let path = match dir
|
|
||||||
.canonicalize()
|
|
||||||
.or_else(|_| Self::find_decl_in_pystd(&__name__))
|
|
||||||
{
|
|
||||||
Ok(path) => path,
|
Ok(path) => path,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
let err = TyCheckError::import_error(
|
let err = TyCheckError::import_error(
|
||||||
|
|
|
@ -892,6 +892,7 @@ impl Context {
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
hir::Expr::Import(_) => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,9 @@ use erg_common::{
|
||||||
impl_nested_display_for_enum, impl_stream_for_wrapper,
|
impl_nested_display_for_enum, impl_stream_for_wrapper,
|
||||||
};
|
};
|
||||||
|
|
||||||
use erg_parser::ast::{fmt_lines, DefId, DefKind, NonDefaultParamSignature, TypeSpec, VarName};
|
use erg_parser::ast::{
|
||||||
|
fmt_lines, DefId, DefKind, NonDefaultParamSignature, OperationKind, TypeSpec, VarName,
|
||||||
|
};
|
||||||
use erg_parser::token::{Token, TokenKind};
|
use erg_parser::token::{Token, TokenKind};
|
||||||
|
|
||||||
use crate::ty::constructors::{array_t, dict_t, set_t, tuple_t};
|
use crate::ty::constructors::{array_t, dict_t, set_t, tuple_t};
|
||||||
|
@ -21,7 +23,6 @@ use crate::ty::value::{TypeKind, ValueObj};
|
||||||
use crate::ty::{HasType, Type};
|
use crate::ty::{HasType, Type};
|
||||||
|
|
||||||
use crate::context::eval::type_from_token_kind;
|
use crate::context::eval::type_from_token_kind;
|
||||||
use crate::context::OperationKind;
|
|
||||||
use crate::error::readable_name;
|
use crate::error::readable_name;
|
||||||
use crate::varinfo::VarInfo;
|
use crate::varinfo::VarInfo;
|
||||||
use crate::{impl_t, impl_t_for_enum};
|
use crate::{impl_t, impl_t_for_enum};
|
||||||
|
@ -70,6 +71,16 @@ impl Literal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Literal {
|
||||||
|
pub fn new(value: ValueObj, token: Token) -> Self {
|
||||||
|
Self {
|
||||||
|
t: value.t(),
|
||||||
|
value,
|
||||||
|
token,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct PosArg {
|
pub struct PosArg {
|
||||||
pub expr: Expr,
|
pub expr: Expr,
|
||||||
|
@ -1789,12 +1800,13 @@ pub enum Expr {
|
||||||
TypeAsc(TypeAscription),
|
TypeAsc(TypeAscription),
|
||||||
Code(Block), // code object
|
Code(Block), // code object
|
||||||
Compound(Block), // compound statement
|
Compound(Block), // compound statement
|
||||||
|
Import(Accessor),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_nested_display_for_chunk_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def, ClassDef, AttrDef, Code, Compound, TypeAsc, Set);
|
impl_nested_display_for_chunk_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def, ClassDef, AttrDef, Code, Compound, TypeAsc, Set, Import);
|
||||||
impl_display_from_nested!(Expr);
|
impl_display_from_nested!(Expr);
|
||||||
impl_locational_for_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def, ClassDef, AttrDef, Code, Compound, TypeAsc, Set);
|
impl_locational_for_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def, ClassDef, AttrDef, Code, Compound, TypeAsc, Set, Import);
|
||||||
impl_t_for_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def, ClassDef, AttrDef, Code, Compound, TypeAsc, Set);
|
impl_t_for_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def, ClassDef, AttrDef, Code, Compound, TypeAsc, Set, Import);
|
||||||
|
|
||||||
impl Default for Expr {
|
impl Default for Expr {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
|
|
1
compiler/erg_compiler/lib/pystd/http.d/__init__.d.er
Normal file
1
compiler/erg_compiler/lib/pystd/http.d/__init__.d.er
Normal file
|
@ -0,0 +1 @@
|
||||||
|
.client = pyimport "./client"
|
1
compiler/erg_compiler/lib/pystd/http.d/client.d.er
Normal file
1
compiler/erg_compiler/lib/pystd/http.d/client.d.er
Normal file
|
@ -0,0 +1 @@
|
||||||
|
.HTTPResponse: ClassType
|
3
compiler/erg_compiler/lib/pystd/random.d.er
Normal file
3
compiler/erg_compiler/lib/pystd/random.d.er
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
.seed!: (a := Num, version := Int) => NoneType
|
||||||
|
.randint!: (a: Int, b: Int) => Int
|
||||||
|
.choice!: |T: Type, S <: Seq(T)|(seq: S) => T
|
1
compiler/erg_compiler/lib/pystd/re.d.er
Normal file
1
compiler/erg_compiler/lib/pystd/re.d.er
Normal file
|
@ -0,0 +1 @@
|
||||||
|
.sub: (pattern: Str, repl: Str, string: Str, count := Nat) -> Str
|
2
compiler/erg_compiler/lib/pystd/time.d.er
Normal file
2
compiler/erg_compiler/lib/pystd/time.d.er
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
.sleep!: Float => NoneType
|
||||||
|
.time!: () => Float
|
2
compiler/erg_compiler/lib/pystd/urllib.d/__init__.d.er
Normal file
2
compiler/erg_compiler/lib/pystd/urllib.d/__init__.d.er
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
.parse = pyimport "./parse"
|
||||||
|
.request = pyimport "./request"
|
0
compiler/erg_compiler/lib/pystd/urllib.d/parse.d.er
Normal file
0
compiler/erg_compiler/lib/pystd/urllib.d/parse.d.er
Normal file
5
compiler/erg_compiler/lib/pystd/urllib.d/request.d.er
Normal file
5
compiler/erg_compiler/lib/pystd/urllib.d/request.d.er
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
http = pyimport "http"
|
||||||
|
|
||||||
|
.Request: ClassType
|
||||||
|
.Request.data: Bytes
|
||||||
|
.urlopen!: (url: Str or .Request, data: Bytes or NoneType := NoneType, timeout: Nat or NoneType := NoneType) -> http.client.HTTPResponse
|
|
@ -7,7 +7,7 @@ use erg_common::traits::{Locational, Stream};
|
||||||
use erg_common::Str;
|
use erg_common::Str;
|
||||||
use erg_common::{enum_unwrap, log};
|
use erg_common::{enum_unwrap, log};
|
||||||
|
|
||||||
use erg_parser::ast::DefId;
|
use erg_parser::ast::{DefId, OperationKind};
|
||||||
use erg_parser::token::{Token, TokenKind};
|
use erg_parser::token::{Token, TokenKind};
|
||||||
|
|
||||||
use crate::ty::free::fresh_varname;
|
use crate::ty::free::fresh_varname;
|
||||||
|
@ -15,7 +15,6 @@ use crate::ty::typaram::TyParam;
|
||||||
use crate::ty::value::ValueObj;
|
use crate::ty::value::ValueObj;
|
||||||
use crate::ty::{HasType, Type};
|
use crate::ty::{HasType, Type};
|
||||||
|
|
||||||
use crate::context::OperationKind;
|
|
||||||
use crate::hir::*;
|
use crate::hir::*;
|
||||||
use crate::mod_cache::SharedModuleCache;
|
use crate::mod_cache::SharedModuleCache;
|
||||||
|
|
||||||
|
@ -34,19 +33,141 @@ impl<'a> Linker<'a> {
|
||||||
for chunk in main.module.iter_mut() {
|
for chunk in main.module.iter_mut() {
|
||||||
self.replace_import(chunk);
|
self.replace_import(chunk);
|
||||||
}
|
}
|
||||||
|
for chunk in main.module.iter_mut() {
|
||||||
|
self.resolve_pymod_path(chunk);
|
||||||
|
}
|
||||||
log!(info "linked: {main}");
|
log!(info "linked: {main}");
|
||||||
main
|
main
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// ```erg
|
||||||
|
/// urllib = pyimport "urllib"
|
||||||
|
/// urllib.request.urlopen! "https://example.com"
|
||||||
|
/// ```
|
||||||
|
/// ↓
|
||||||
|
/// ```python
|
||||||
|
/// urllib = __import__("urllib.request")
|
||||||
|
/// import urllib.request
|
||||||
|
/// urllib.request.urlopen("https://example.com")
|
||||||
|
/// ```
|
||||||
|
fn resolve_pymod_path(&self, expr: &mut Expr) {
|
||||||
|
match expr {
|
||||||
|
Expr::Lit(_) => {}
|
||||||
|
Expr::Accessor(acc) => {
|
||||||
|
if matches!(acc, Accessor::Attr(_)) && acc.ref_t().is_py_module() {
|
||||||
|
let import = Expr::Import(acc.clone());
|
||||||
|
*expr = Expr::Compound(Block::new(vec![import, mem::take(expr)]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Expr::Array(array) => match array {
|
||||||
|
Array::Normal(arr) => {
|
||||||
|
for elem in arr.elems.pos_args.iter_mut() {
|
||||||
|
self.resolve_pymod_path(&mut elem.expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Array::WithLength(arr) => {
|
||||||
|
self.resolve_pymod_path(&mut arr.elem);
|
||||||
|
self.resolve_pymod_path(&mut arr.len);
|
||||||
|
}
|
||||||
|
_ => todo!(),
|
||||||
|
},
|
||||||
|
Expr::Tuple(tuple) => match tuple {
|
||||||
|
Tuple::Normal(tup) => {
|
||||||
|
for elem in tup.elems.pos_args.iter_mut() {
|
||||||
|
self.resolve_pymod_path(&mut elem.expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Expr::Set(set) => match set {
|
||||||
|
Set::Normal(st) => {
|
||||||
|
for elem in st.elems.pos_args.iter_mut() {
|
||||||
|
self.resolve_pymod_path(&mut elem.expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Set::WithLength(st) => {
|
||||||
|
self.resolve_pymod_path(&mut st.elem);
|
||||||
|
self.resolve_pymod_path(&mut st.len);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Expr::Dict(dict) => match dict {
|
||||||
|
Dict::Normal(dic) => {
|
||||||
|
for elem in dic.kvs.iter_mut() {
|
||||||
|
self.resolve_pymod_path(&mut elem.key);
|
||||||
|
self.resolve_pymod_path(&mut elem.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
other => todo!("{other}"),
|
||||||
|
},
|
||||||
|
Expr::Record(record) => {
|
||||||
|
for attr in record.attrs.iter_mut() {
|
||||||
|
for chunk in attr.body.block.iter_mut() {
|
||||||
|
self.resolve_pymod_path(chunk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Expr::BinOp(binop) => {
|
||||||
|
self.resolve_pymod_path(&mut binop.lhs);
|
||||||
|
self.resolve_pymod_path(&mut binop.rhs);
|
||||||
|
}
|
||||||
|
Expr::UnaryOp(unaryop) => {
|
||||||
|
self.resolve_pymod_path(&mut unaryop.expr);
|
||||||
|
}
|
||||||
|
Expr::Call(call) => {
|
||||||
|
self.resolve_pymod_path(&mut call.obj);
|
||||||
|
for arg in call.args.pos_args.iter_mut() {
|
||||||
|
self.resolve_pymod_path(&mut arg.expr);
|
||||||
|
}
|
||||||
|
for arg in call.args.kw_args.iter_mut() {
|
||||||
|
self.resolve_pymod_path(&mut arg.expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Expr::Decl(_decl) => {}
|
||||||
|
Expr::Def(def) => {
|
||||||
|
for chunk in def.body.block.iter_mut() {
|
||||||
|
self.resolve_pymod_path(chunk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Expr::Lambda(lambda) => {
|
||||||
|
for chunk in lambda.body.iter_mut() {
|
||||||
|
self.resolve_pymod_path(chunk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Expr::ClassDef(class_def) => {
|
||||||
|
for def in class_def.methods.iter_mut() {
|
||||||
|
self.resolve_pymod_path(def);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Expr::AttrDef(attr_def) => {
|
||||||
|
// REVIEW:
|
||||||
|
for chunk in attr_def.block.iter_mut() {
|
||||||
|
self.resolve_pymod_path(chunk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Expr::TypeAsc(tasc) => self.resolve_pymod_path(&mut tasc.expr),
|
||||||
|
Expr::Code(chunks) | Expr::Compound(chunks) => {
|
||||||
|
for chunk in chunks.iter_mut() {
|
||||||
|
self.resolve_pymod_path(chunk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Expr::Import(_) => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn replace_import(&self, expr: &mut Expr) {
|
fn replace_import(&self, expr: &mut Expr) {
|
||||||
match expr {
|
match expr {
|
||||||
Expr::Lit(_) => {}
|
Expr::Lit(_) => {}
|
||||||
Expr::Accessor(acc) => match acc {
|
Expr::Accessor(acc) => {
|
||||||
Accessor::Attr(attr) => {
|
/*if acc.ref_t().is_py_module() {
|
||||||
self.replace_import(&mut attr.obj);
|
let import = Expr::Import(acc.clone());
|
||||||
|
*expr = Expr::Compound(Block::new(vec![import, mem::take(expr)]));
|
||||||
|
}*/
|
||||||
|
match acc {
|
||||||
|
Accessor::Attr(attr) => {
|
||||||
|
self.replace_import(&mut attr.obj);
|
||||||
|
}
|
||||||
|
Accessor::Ident(_) => {}
|
||||||
}
|
}
|
||||||
Accessor::Ident(_) => {}
|
}
|
||||||
},
|
|
||||||
Expr::Array(array) => match array {
|
Expr::Array(array) => match array {
|
||||||
Array::Normal(arr) => {
|
Array::Normal(arr) => {
|
||||||
for elem in arr.elems.pos_args.iter_mut() {
|
for elem in arr.elems.pos_args.iter_mut() {
|
||||||
|
@ -108,6 +229,7 @@ impl<'a> Linker<'a> {
|
||||||
self.replace_py_import(expr);
|
self.replace_py_import(expr);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
self.replace_import(&mut call.obj);
|
||||||
for arg in call.args.pos_args.iter_mut() {
|
for arg in call.args.pos_args.iter_mut() {
|
||||||
self.replace_import(&mut arg.expr);
|
self.replace_import(&mut arg.expr);
|
||||||
}
|
}
|
||||||
|
@ -144,6 +266,7 @@ impl<'a> Linker<'a> {
|
||||||
self.replace_import(chunk);
|
self.replace_import(chunk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Expr::Import(_) => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,7 +286,7 @@ impl<'a> Linker<'a> {
|
||||||
let path =
|
let path =
|
||||||
enum_unwrap!(expr.ref_t().typarams().remove(0), TyParam::Value:(ValueObj::Str:(_)));
|
enum_unwrap!(expr.ref_t().typarams().remove(0), TyParam::Value:(ValueObj::Str:(_)));
|
||||||
let path = Path::new(&path[..]);
|
let path = Path::new(&path[..]);
|
||||||
let path = self.cfg.input.resolve(path).unwrap();
|
let path = self.cfg.input.local_resolve(path).unwrap();
|
||||||
// In the case of REPL, entries cannot be used up
|
// In the case of REPL, entries cannot be used up
|
||||||
let hir = if self.cfg.input.is_repl() {
|
let hir = if self.cfg.input.is_repl() {
|
||||||
self.mod_cache
|
self.mod_cache
|
||||||
|
|
|
@ -13,7 +13,7 @@ use erg_common::vis::Visibility;
|
||||||
use erg_common::{enum_unwrap, fmt_option, fn_name, get_hash, log, switch_lang, Str};
|
use erg_common::{enum_unwrap, fmt_option, fn_name, get_hash, log, switch_lang, Str};
|
||||||
|
|
||||||
use erg_parser::ast;
|
use erg_parser::ast;
|
||||||
use erg_parser::ast::AST;
|
use erg_parser::ast::{OperationKind, AST};
|
||||||
use erg_parser::build_ast::ASTBuilder;
|
use erg_parser::build_ast::ASTBuilder;
|
||||||
use erg_parser::token::{Token, TokenKind};
|
use erg_parser::token::{Token, TokenKind};
|
||||||
use erg_parser::Parser;
|
use erg_parser::Parser;
|
||||||
|
@ -27,9 +27,7 @@ use crate::ty::value::{GenTypeObj, TypeKind, TypeObj, ValueObj};
|
||||||
use crate::ty::{HasType, ParamTy, Type};
|
use crate::ty::{HasType, ParamTy, Type};
|
||||||
|
|
||||||
use crate::context::instantiate::TyVarInstContext;
|
use crate::context::instantiate::TyVarInstContext;
|
||||||
use crate::context::{
|
use crate::context::{ClassDefType, Context, ContextKind, RegistrationMode, TraitInstance};
|
||||||
ClassDefType, Context, ContextKind, OperationKind, RegistrationMode, TraitInstance,
|
|
||||||
};
|
|
||||||
use crate::error::{
|
use crate::error::{
|
||||||
CompileError, CompileErrors, LowerError, LowerErrors, LowerResult, LowerWarnings,
|
CompileError, CompileErrors, LowerError, LowerErrors, LowerResult, LowerWarnings,
|
||||||
SingleLowerResult,
|
SingleLowerResult,
|
||||||
|
@ -1455,7 +1453,7 @@ impl ASTLowerer {
|
||||||
Ok(hir::Block::new(hir_block))
|
Ok(hir::Block::new(hir_block))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn declare_var_alias(
|
fn declare_or_import_var(
|
||||||
&mut self,
|
&mut self,
|
||||||
sig: ast::VarSignature,
|
sig: ast::VarSignature,
|
||||||
mut body: ast::DefBody,
|
mut body: ast::DefBody,
|
||||||
|
@ -1470,11 +1468,13 @@ impl ASTLowerer {
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
let chunk = self.declare_chunk(body.block.remove(0))?;
|
let chunk = self.declare_chunk(body.block.remove(0))?;
|
||||||
let acc = enum_unwrap!(
|
let py_name = if let hir::Expr::TypeAsc(tasc) = &chunk {
|
||||||
enum_unwrap!(&chunk, hir::Expr::TypeAsc).expr.as_ref(),
|
enum_unwrap!(tasc.expr.as_ref(), hir::Expr::Accessor)
|
||||||
hir::Expr::Accessor
|
.local_name()
|
||||||
);
|
.map(Str::rc)
|
||||||
let py_name = acc.local_name().map(Str::rc);
|
} else {
|
||||||
|
sig.inspect().cloned()
|
||||||
|
};
|
||||||
let block = hir::Block::new(vec![chunk]);
|
let block = hir::Block::new(vec![chunk]);
|
||||||
let found_body_t = block.ref_t();
|
let found_body_t = block.ref_t();
|
||||||
let ident = match &sig.pat {
|
let ident = match &sig.pat {
|
||||||
|
@ -1489,7 +1489,7 @@ impl ASTLowerer {
|
||||||
Ok(hir::Def::new(hir::Signature::Var(sig), body))
|
Ok(hir::Def::new(hir::Signature::Var(sig), body))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn declare_alias(&mut self, def: ast::Def) -> LowerResult<hir::Def> {
|
fn declare_alias_or_import(&mut self, def: ast::Def) -> LowerResult<hir::Def> {
|
||||||
log!(info "entered {}({})", fn_name!(), def.sig);
|
log!(info "entered {}({})", fn_name!(), def.sig);
|
||||||
let name = if let Some(name) = def.sig.name_as_str() {
|
let name = if let Some(name) = def.sig.name_as_str() {
|
||||||
name.clone()
|
name.clone()
|
||||||
|
@ -1510,11 +1510,19 @@ impl ASTLowerer {
|
||||||
&name,
|
&name,
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
#[allow(clippy::let_and_return)]
|
||||||
let res = match def.sig {
|
let res = match def.sig {
|
||||||
ast::Signature::Subr(_sig) => todo!(),
|
ast::Signature::Subr(sig) => {
|
||||||
ast::Signature::Var(sig) => self.declare_var_alias(sig, def.body),
|
return Err(LowerErrors::from(LowerError::declare_error(
|
||||||
|
self.cfg.input.clone(),
|
||||||
|
line!() as usize,
|
||||||
|
sig.loc(),
|
||||||
|
self.ctx.caused_by(),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
ast::Signature::Var(sig) => self.declare_or_import_var(sig, def.body),
|
||||||
};
|
};
|
||||||
self.pop_append_errs();
|
// self.pop_append_errs();
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1636,7 +1644,7 @@ impl ASTLowerer {
|
||||||
fn declare_chunk(&mut self, expr: ast::Expr) -> LowerResult<hir::Expr> {
|
fn declare_chunk(&mut self, expr: ast::Expr) -> LowerResult<hir::Expr> {
|
||||||
log!(info "entered {}", fn_name!());
|
log!(info "entered {}", fn_name!());
|
||||||
match expr {
|
match expr {
|
||||||
ast::Expr::Def(def) => Ok(hir::Expr::Def(self.declare_alias(def)?)),
|
ast::Expr::Def(def) => Ok(hir::Expr::Def(self.declare_alias_or_import(def)?)),
|
||||||
ast::Expr::ClassDef(defs) => Err(LowerErrors::from(LowerError::feature_error(
|
ast::Expr::ClassDef(defs) => Err(LowerErrors::from(LowerError::feature_error(
|
||||||
self.cfg.input.clone(),
|
self.cfg.input.clone(),
|
||||||
defs.loc(),
|
defs.loc(),
|
||||||
|
@ -1644,6 +1652,14 @@ impl ASTLowerer {
|
||||||
self.ctx.caused_by(),
|
self.ctx.caused_by(),
|
||||||
))),
|
))),
|
||||||
ast::Expr::TypeAsc(tasc) => Ok(hir::Expr::TypeAsc(self.declare_ident(tasc)?)),
|
ast::Expr::TypeAsc(tasc) => Ok(hir::Expr::TypeAsc(self.declare_ident(tasc)?)),
|
||||||
|
ast::Expr::Call(call)
|
||||||
|
if call
|
||||||
|
.additional_operation()
|
||||||
|
.map(|op| op.is_import())
|
||||||
|
.unwrap_or(false) =>
|
||||||
|
{
|
||||||
|
Ok(hir::Expr::Call(self.lower_call(call)?))
|
||||||
|
}
|
||||||
other => Err(LowerErrors::from(LowerError::declare_error(
|
other => Err(LowerErrors::from(LowerError::declare_error(
|
||||||
self.cfg.input.clone(),
|
self.cfg.input.clone(),
|
||||||
line!() as usize,
|
line!() as usize,
|
||||||
|
|
|
@ -58,12 +58,12 @@ impl Reorderer {
|
||||||
}
|
}
|
||||||
Expr::Methods(methods) => match &methods.class {
|
Expr::Methods(methods) => match &methods.class {
|
||||||
TypeSpec::PreDeclTy(PreDeclTypeSpec::Simple(simple)) => {
|
TypeSpec::PreDeclTy(PreDeclTypeSpec::Simple(simple)) => {
|
||||||
self.link_methods(simple.name.inspect().clone(), &mut new, methods)
|
self.link_methods(simple.ident.inspect().clone(), &mut new, methods)
|
||||||
}
|
}
|
||||||
TypeSpec::TypeApp { spec, .. } => {
|
TypeSpec::TypeApp { spec, .. } => {
|
||||||
if let TypeSpec::PreDeclTy(PreDeclTypeSpec::Simple(simple)) = spec.as_ref()
|
if let TypeSpec::PreDeclTy(PreDeclTypeSpec::Simple(simple)) = spec.as_ref()
|
||||||
{
|
{
|
||||||
self.link_methods(simple.name.inspect().clone(), &mut new, methods)
|
self.link_methods(simple.ident.inspect().clone(), &mut new, methods)
|
||||||
} else {
|
} else {
|
||||||
let similar_name = self
|
let similar_name = self
|
||||||
.def_root_pos_map
|
.def_root_pos_map
|
||||||
|
|
|
@ -64,6 +64,11 @@ pub fn module(path: TyParam) -> Type {
|
||||||
poly("Module", vec![path])
|
poly("Module", vec![path])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn py_module(path: TyParam) -> Type {
|
||||||
|
poly("PyModule", vec![path])
|
||||||
|
}
|
||||||
|
|
||||||
pub fn module_from_path<P: Into<PathBuf>>(path: P) -> Type {
|
pub fn module_from_path<P: Into<PathBuf>>(path: P) -> Type {
|
||||||
let s = ValueObj::Str(Str::rc(path.into().to_str().unwrap()));
|
let s = ValueObj::Str(Str::rc(path.into().to_str().unwrap()));
|
||||||
module(TyParam::Value(s))
|
module(TyParam::Value(s))
|
||||||
|
|
|
@ -1800,6 +1800,24 @@ impl Type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_module(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_module(),
|
||||||
|
Self::Refinement(refine) => refine.t.is_module(),
|
||||||
|
Self::Poly { name, .. } => &name[..] == "PyModule" || &name[..] == "Module",
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_py_module(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_py_module(),
|
||||||
|
Self::Refinement(refine) => refine.t.is_py_module(),
|
||||||
|
Self::Poly { name, .. } => &name[..] == "PyModule",
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_quantified(&self) -> bool {
|
pub fn is_quantified(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_quantified(),
|
Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_quantified(),
|
||||||
|
|
|
@ -667,7 +667,7 @@ impl TyParam {
|
||||||
Self::MonoQVar(_) | Self::PolyQVar { .. } => true,
|
Self::MonoQVar(_) | Self::PolyQVar { .. } => true,
|
||||||
Self::FreeVar(fv) => {
|
Self::FreeVar(fv) => {
|
||||||
if fv.is_unbound() {
|
if fv.is_unbound() {
|
||||||
true
|
false
|
||||||
} else {
|
} else {
|
||||||
fv.crack().has_qvar()
|
fv.crack().has_qvar()
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,27 @@ use erg_common::{fmt_vec_split_with, Str};
|
||||||
|
|
||||||
use crate::token::{Token, TokenKind};
|
use crate::token::{Token, TokenKind};
|
||||||
|
|
||||||
|
/// Some Erg functions require additional operation by the compiler.
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub enum OperationKind {
|
||||||
|
Import,
|
||||||
|
PyImport,
|
||||||
|
Del,
|
||||||
|
AssertCast,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OperationKind {
|
||||||
|
pub const fn is_erg_import(&self) -> bool {
|
||||||
|
matches!(self, Self::Import)
|
||||||
|
}
|
||||||
|
pub const fn is_py_import(&self) -> bool {
|
||||||
|
matches!(self, Self::PyImport)
|
||||||
|
}
|
||||||
|
pub const fn is_import(&self) -> bool {
|
||||||
|
matches!(self, Self::Import | Self::PyImport)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn fmt_lines<'a, T: NestedDisplay + 'a>(
|
pub fn fmt_lines<'a, T: NestedDisplay + 'a>(
|
||||||
mut iter: impl Iterator<Item = &'a T>,
|
mut iter: impl Iterator<Item = &'a T>,
|
||||||
f: &mut fmt::Formatter<'_>,
|
f: &mut fmt::Formatter<'_>,
|
||||||
|
@ -985,6 +1006,15 @@ impl Call {
|
||||||
.and_then(|pred| option_enum_unwrap!(pred, Expr::BinOp))
|
.and_then(|pred| option_enum_unwrap!(pred, Expr::BinOp))
|
||||||
.map(|bin| bin.args[1].as_ref())
|
.map(|bin| bin.args[1].as_ref())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn additional_operation(&self) -> Option<OperationKind> {
|
||||||
|
self.obj.get_name().and_then(|s| match &s[..] {
|
||||||
|
"import" => Some(OperationKind::Import),
|
||||||
|
"pyimport" | "py" => Some(OperationKind::PyImport),
|
||||||
|
"Del" => Some(OperationKind::Del),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// e.g. `Data::{x = 1; y = 2}`
|
/// e.g. `Data::{x = 1; y = 2}`
|
||||||
|
@ -1471,16 +1501,16 @@ impl ConstArgs {
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct SimpleTypeSpec {
|
pub struct SimpleTypeSpec {
|
||||||
pub name: VarName,
|
pub ident: Identifier,
|
||||||
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 SimpleTypeSpec {
|
impl fmt::Display for SimpleTypeSpec {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
if self.args.is_empty() {
|
if self.args.is_empty() {
|
||||||
write!(f, "{}", self.name)
|
write!(f, "{}", self.ident)
|
||||||
} else {
|
} else {
|
||||||
write!(f, "{}{}", self.name, self.args)
|
write!(f, "{}{}", self.ident, self.args)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1488,18 +1518,18 @@ impl fmt::Display for SimpleTypeSpec {
|
||||||
impl Locational for SimpleTypeSpec {
|
impl Locational for SimpleTypeSpec {
|
||||||
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.name, last)
|
Location::concat(&self.ident, last)
|
||||||
} else if let Some(last) = self.args.pos_args.last() {
|
} else if let Some(last) = self.args.pos_args.last() {
|
||||||
Location::concat(&self.name, last)
|
Location::concat(&self.ident, last)
|
||||||
} else {
|
} else {
|
||||||
self.name.loc()
|
self.ident.loc()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SimpleTypeSpec {
|
impl SimpleTypeSpec {
|
||||||
pub const fn new(name: VarName, args: ConstArgs) -> Self {
|
pub const fn new(ident: Identifier, args: ConstArgs) -> Self {
|
||||||
Self { name, args }
|
Self { ident, args }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1515,12 +1545,12 @@ impl SimpleTypeSpec {
|
||||||
pub enum PreDeclTypeSpec {
|
pub enum PreDeclTypeSpec {
|
||||||
Simple(SimpleTypeSpec),
|
Simple(SimpleTypeSpec),
|
||||||
Attr {
|
Attr {
|
||||||
namespace: Vec<VarName>,
|
namespace: Box<Expr>,
|
||||||
t: SimpleTypeSpec,
|
t: SimpleTypeSpec,
|
||||||
},
|
},
|
||||||
Subscr {
|
Subscr {
|
||||||
namespace: Vec<VarName>,
|
namespace: Box<Expr>,
|
||||||
name: VarName,
|
ident: Identifier,
|
||||||
index: Token,
|
index: Token,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -1528,17 +1558,15 @@ pub enum PreDeclTypeSpec {
|
||||||
impl fmt::Display for PreDeclTypeSpec {
|
impl fmt::Display for PreDeclTypeSpec {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
PreDeclTypeSpec::Simple(ts) => write!(f, "{}", ts),
|
PreDeclTypeSpec::Simple(ts) => write!(f, "{ts}"),
|
||||||
PreDeclTypeSpec::Attr { namespace, t } => {
|
PreDeclTypeSpec::Attr { namespace, t } => {
|
||||||
write!(f, "{}.{}", namespace.join("."), t)
|
write!(f, "{namespace}{t}")
|
||||||
}
|
}
|
||||||
PreDeclTypeSpec::Subscr {
|
PreDeclTypeSpec::Subscr {
|
||||||
namespace,
|
namespace,
|
||||||
name,
|
ident,
|
||||||
index,
|
index,
|
||||||
} => {
|
} => write!(f, "{namespace}{ident}[{index}]"),
|
||||||
write!(f, "{}.{}[{}]", namespace.join("."), name, index)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1547,10 +1575,10 @@ impl Locational for PreDeclTypeSpec {
|
||||||
fn loc(&self) -> Location {
|
fn loc(&self) -> Location {
|
||||||
match self {
|
match self {
|
||||||
Self::Simple(s) => s.loc(),
|
Self::Simple(s) => s.loc(),
|
||||||
Self::Attr { namespace, t } => Location::concat(&namespace[0], t),
|
Self::Attr { namespace, t } => Location::concat(namespace.as_ref(), t),
|
||||||
Self::Subscr {
|
Self::Subscr {
|
||||||
namespace, index, ..
|
namespace, index, ..
|
||||||
} => Location::concat(&namespace[0], index),
|
} => Location::concat(namespace.as_ref(), index),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2780,17 +2780,26 @@ impl Parser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ident_to_type_spec(ident: Identifier) -> SimpleTypeSpec {
|
||||||
|
SimpleTypeSpec::new(ident, ConstArgs::empty())
|
||||||
|
}
|
||||||
|
|
||||||
fn accessor_to_type_spec(accessor: Accessor) -> Result<TypeSpec, ParseError> {
|
fn accessor_to_type_spec(accessor: Accessor) -> Result<TypeSpec, ParseError> {
|
||||||
let t_spec = match accessor {
|
let t_spec = match accessor {
|
||||||
Accessor::Ident(ident) => {
|
Accessor::Ident(ident) => {
|
||||||
let predecl =
|
let predecl = PreDeclTypeSpec::Simple(Self::ident_to_type_spec(ident));
|
||||||
PreDeclTypeSpec::Simple(SimpleTypeSpec::new(ident.name, ConstArgs::empty()));
|
|
||||||
TypeSpec::PreDeclTy(predecl)
|
TypeSpec::PreDeclTy(predecl)
|
||||||
}
|
}
|
||||||
Accessor::TypeApp(tapp) => {
|
Accessor::TypeApp(tapp) => {
|
||||||
let spec = Self::expr_to_type_spec(*tapp.obj)?;
|
let spec = Self::expr_to_type_spec(*tapp.obj)?;
|
||||||
TypeSpec::type_app(spec, tapp.type_args)
|
TypeSpec::type_app(spec, tapp.type_args)
|
||||||
}
|
}
|
||||||
|
Accessor::Attr(attr) => {
|
||||||
|
let namespace = attr.obj;
|
||||||
|
let t = Self::ident_to_type_spec(attr.ident);
|
||||||
|
let predecl = PreDeclTypeSpec::Attr { namespace, t };
|
||||||
|
TypeSpec::PreDeclTy(predecl)
|
||||||
|
}
|
||||||
other => {
|
other => {
|
||||||
let err = ParseError::simple_syntax_error(line!() as usize, other.loc());
|
let err = ParseError::simple_syntax_error(line!() as usize, other.loc());
|
||||||
return Err(err);
|
return Err(err);
|
||||||
|
@ -2814,7 +2823,7 @@ impl Parser {
|
||||||
kw_args.push(ConstKwArg::new(arg.keyword, const_expr));
|
kw_args.push(ConstKwArg::new(arg.keyword, const_expr));
|
||||||
}
|
}
|
||||||
Ok(PreDeclTypeSpec::Simple(SimpleTypeSpec::new(
|
Ok(PreDeclTypeSpec::Simple(SimpleTypeSpec::new(
|
||||||
ident.name,
|
ident,
|
||||||
ConstArgs::new(pos_args, kw_args, paren),
|
ConstArgs::new(pos_args, kw_args, paren),
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
|
@ -2831,9 +2840,11 @@ impl Parser {
|
||||||
(ParamPattern::VarName(name), Some(t_spec_with_op)) => {
|
(ParamPattern::VarName(name), Some(t_spec_with_op)) => {
|
||||||
ParamTySpec::new(Some(name.into_token()), t_spec_with_op.t_spec)
|
ParamTySpec::new(Some(name.into_token()), t_spec_with_op.t_spec)
|
||||||
}
|
}
|
||||||
(ParamPattern::VarName(name), None) => ParamTySpec::anonymous(TypeSpec::PreDeclTy(
|
(ParamPattern::VarName(name), None) => {
|
||||||
PreDeclTypeSpec::Simple(SimpleTypeSpec::new(name, ConstArgs::empty())),
|
ParamTySpec::anonymous(TypeSpec::PreDeclTy(PreDeclTypeSpec::Simple(
|
||||||
)),
|
SimpleTypeSpec::new(Identifier::new(None, name), ConstArgs::empty()),
|
||||||
|
)))
|
||||||
|
}
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
};
|
};
|
||||||
non_defaults.push(param);
|
non_defaults.push(param);
|
||||||
|
@ -2849,7 +2860,7 @@ impl Parser {
|
||||||
}
|
}
|
||||||
(ParamPattern::VarName(name), None) => {
|
(ParamPattern::VarName(name), None) => {
|
||||||
ParamTySpec::anonymous(TypeSpec::PreDeclTy(PreDeclTypeSpec::Simple(
|
ParamTySpec::anonymous(TypeSpec::PreDeclTy(PreDeclTypeSpec::Simple(
|
||||||
SimpleTypeSpec::new(name, ConstArgs::empty()),
|
SimpleTypeSpec::new(Identifier::new(None, name), ConstArgs::empty()),
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
math = pyimport "math"
|
math = pyimport "math"
|
||||||
sys = pyimport "sys"
|
sys = pyimport "sys"
|
||||||
sub = pyimport "subprocess"
|
sub = pyimport "subprocess"
|
||||||
|
urllib = pyimport "urllib"
|
||||||
|
|
||||||
print! math.pi
|
print! math.pi
|
||||||
|
print! urllib.request.urlopen!("https://example.com")
|
||||||
discard sub.run! ["echo", "hello"], shell := True
|
discard sub.run! ["echo", "hello"], shell := True
|
||||||
sys.exit 111
|
sys.exit 111
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue