mirror of
https://github.com/erg-lang/erg.git
synced 2025-08-03 10:23:20 +00:00
Fix visibility bugs
This commit is contained in:
parent
c96fe956a5
commit
3895d29669
12 changed files with 372 additions and 488 deletions
|
@ -18,7 +18,7 @@ use erg_parser::ast::DefId;
|
|||
use erg_type::codeobj::{CodeObj, CodeObjFlags};
|
||||
use Opcode::*;
|
||||
|
||||
use erg_parser::ast::{Identifier, ParamPattern, ParamSignature, Params, VarName};
|
||||
use erg_parser::ast::{ParamPattern, ParamSignature, Params, VarName};
|
||||
use erg_parser::token::{Token, TokenKind};
|
||||
|
||||
use erg_type::free::fresh_varname;
|
||||
|
@ -32,11 +32,18 @@ use crate::error::{CompileError, CompileErrors, CompileResult};
|
|||
use crate::hir::AttrDef;
|
||||
use crate::hir::Attribute;
|
||||
use crate::hir::{
|
||||
Accessor, Args, Array, Block, Call, ClassDef, DefBody, Expr, Literal, Local, PosArg, Signature,
|
||||
SubrSignature, Tuple, VarSignature, HIR,
|
||||
Accessor, Args, Array, Block, Call, ClassDef, DefBody, Expr, Identifier, Literal, PosArg,
|
||||
Signature, SubrSignature, Tuple, VarSignature, HIR,
|
||||
};
|
||||
use AccessKind::*;
|
||||
|
||||
fn is_python_special(name: &str) -> bool {
|
||||
match name {
|
||||
"__call__" | "__init__" => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_python_global(name: &str) -> bool {
|
||||
match name {
|
||||
"ArithmeticError"
|
||||
|
@ -214,11 +221,17 @@ fn convert_to_python_attr(class: &str, uniq_obj_name: Option<&str>, name: Str) -
|
|||
}
|
||||
}
|
||||
|
||||
fn escape_attr(class: &str, uniq_obj_name: Option<&str>, name: Str) -> Str {
|
||||
let mut name = convert_to_python_attr(class, uniq_obj_name, name).to_string();
|
||||
fn escape_attr(class: &str, uniq_obj_name: Option<&str>, ident: Identifier) -> Str {
|
||||
let vis = ident.vis();
|
||||
let mut name =
|
||||
convert_to_python_attr(class, uniq_obj_name, ident.name.into_token().content).to_string();
|
||||
name = name.replace('!', "__erg_proc__");
|
||||
name = name.replace('$', "__erg_shared__");
|
||||
Str::rc(&name)
|
||||
if vis.is_public() || is_python_global(&name) || is_python_special(&name) {
|
||||
Str::from(name)
|
||||
} else {
|
||||
Str::from("::".to_string() + &name)
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_to_python_name(name: Str) -> Str {
|
||||
|
@ -254,7 +267,7 @@ fn escape_name(ident: Identifier) -> Str {
|
|||
let mut name = convert_to_python_name(ident.name.into_token().content).to_string();
|
||||
name = name.replace('!', "__erg_proc__");
|
||||
name = name.replace('$', "__erg_shared__");
|
||||
if vis.is_public() || is_python_global(&name) {
|
||||
if vis.is_public() || is_python_global(&name) || is_python_special(&name) {
|
||||
Str::from(name)
|
||||
} else {
|
||||
Str::from("::".to_string() + &name)
|
||||
|
@ -500,9 +513,8 @@ impl CodeGenerator {
|
|||
Some(StoreLoadKind::Global)
|
||||
}
|
||||
|
||||
fn register_name(&mut self, ident: Identifier) -> Name {
|
||||
fn register_name(&mut self, name: Str) -> Name {
|
||||
let current_is_toplevel = self.cur_block() == self.toplevel_block();
|
||||
let name = escape_name(ident);
|
||||
match self.rec_search(&name) {
|
||||
Some(st @ (StoreLoadKind::Local | StoreLoadKind::Global)) => {
|
||||
let st = if current_is_toplevel {
|
||||
|
@ -533,25 +545,22 @@ impl CodeGenerator {
|
|||
}
|
||||
}
|
||||
|
||||
fn register_attr(&mut self, class: &str, uniq_obj_name: Option<&str>, name: Str) -> Name {
|
||||
let name = Str::rc(name.split('.').last().unwrap());
|
||||
let name = escape_attr(class, uniq_obj_name, name);
|
||||
fn register_attr(&mut self, name: Str) -> Name {
|
||||
self.mut_cur_block_codeobj().names.push(name);
|
||||
Name::local(self.cur_block_codeobj().names.len() - 1)
|
||||
}
|
||||
|
||||
fn register_method(&mut self, class: &str, uniq_obj_name: Option<&str>, name: Str) -> Name {
|
||||
let name = Str::rc(name.split('.').last().unwrap());
|
||||
let name = escape_attr(class, uniq_obj_name, name);
|
||||
fn register_method(&mut self, name: Str) -> Name {
|
||||
self.mut_cur_block_codeobj().names.push(name);
|
||||
Name::local(self.cur_block_codeobj().names.len() - 1)
|
||||
}
|
||||
|
||||
fn emit_load_name_instr(&mut self, ident: Identifier) -> CompileResult<()> {
|
||||
log!(info "entered {}", fn_name!());
|
||||
let escaped = escape_name(ident);
|
||||
let name = self
|
||||
.local_search(ident.inspect(), Name)
|
||||
.unwrap_or_else(|| self.register_name(ident));
|
||||
.local_search(&escaped, Name)
|
||||
.unwrap_or_else(|| self.register_name(escaped));
|
||||
let instr = match name.kind {
|
||||
StoreLoadKind::Fast | StoreLoadKind::FastConst => Opcode::LOAD_FAST,
|
||||
StoreLoadKind::Global | StoreLoadKind::GlobalConst => Opcode::LOAD_GLOBAL,
|
||||
|
@ -566,9 +575,10 @@ impl CodeGenerator {
|
|||
|
||||
fn emit_import_name_instr(&mut self, ident: Identifier) -> CompileResult<()> {
|
||||
log!(info "entered {}", fn_name!());
|
||||
let escaped = escape_name(ident);
|
||||
let name = self
|
||||
.local_search(ident.inspect(), Name)
|
||||
.unwrap_or_else(|| self.register_name(ident));
|
||||
.local_search(&escaped, Name)
|
||||
.unwrap_or_else(|| self.register_name(escaped));
|
||||
self.write_instr(IMPORT_NAME);
|
||||
self.write_arg(name.idx as u8);
|
||||
self.stack_dec(); // (level + from_list) -> module object
|
||||
|
@ -577,9 +587,10 @@ impl CodeGenerator {
|
|||
|
||||
fn emit_import_from_instr(&mut self, ident: Identifier) -> CompileResult<()> {
|
||||
log!(info "entered {}", fn_name!());
|
||||
let escaped = escape_name(ident);
|
||||
let name = self
|
||||
.local_search(ident.inspect(), Name)
|
||||
.unwrap_or_else(|| self.register_name(ident));
|
||||
.local_search(&escaped, Name)
|
||||
.unwrap_or_else(|| self.register_name(escaped));
|
||||
self.write_instr(IMPORT_FROM);
|
||||
self.write_arg(name.idx as u8);
|
||||
// self.stack_inc(); (module object) -> attribute
|
||||
|
@ -590,12 +601,13 @@ impl CodeGenerator {
|
|||
&mut self,
|
||||
class: &str,
|
||||
uniq_obj_name: Option<&str>,
|
||||
name: Str,
|
||||
ident: Identifier,
|
||||
) -> CompileResult<()> {
|
||||
log!(info "entered {} ({class}.{name})", fn_name!());
|
||||
log!(info "entered {} ({class}{ident})", fn_name!());
|
||||
let escaped = escape_attr(class, uniq_obj_name, ident);
|
||||
let name = self
|
||||
.local_search(&name, Attr)
|
||||
.unwrap_or_else(|| self.register_attr(class, uniq_obj_name, name));
|
||||
.local_search(&escaped, Attr)
|
||||
.unwrap_or_else(|| self.register_attr(escaped));
|
||||
let instr = match name.kind {
|
||||
StoreLoadKind::Fast | StoreLoadKind::FastConst => Opcode::LOAD_FAST,
|
||||
StoreLoadKind::Global | StoreLoadKind::GlobalConst => Opcode::LOAD_GLOBAL,
|
||||
|
@ -611,12 +623,13 @@ impl CodeGenerator {
|
|||
&mut self,
|
||||
class: &str,
|
||||
uniq_obj_name: Option<&str>,
|
||||
name: Str,
|
||||
ident: Identifier,
|
||||
) -> CompileResult<()> {
|
||||
log!(info "entered {} ({class}.{name})", fn_name!());
|
||||
log!(info "entered {} ({class}{ident})", fn_name!());
|
||||
let escaped = escape_attr(class, uniq_obj_name, ident);
|
||||
let name = self
|
||||
.local_search(&name, Method)
|
||||
.unwrap_or_else(|| self.register_method(class, uniq_obj_name, name));
|
||||
.local_search(&escaped, Method)
|
||||
.unwrap_or_else(|| self.register_method(escaped));
|
||||
let instr = match name.kind {
|
||||
StoreLoadKind::Fast | StoreLoadKind::FastConst => Opcode::LOAD_FAST,
|
||||
StoreLoadKind::Global | StoreLoadKind::GlobalConst => Opcode::LOAD_GLOBAL,
|
||||
|
@ -630,15 +643,14 @@ impl CodeGenerator {
|
|||
|
||||
fn emit_store_instr(&mut self, ident: Identifier, acc_kind: AccessKind) {
|
||||
log!(info "entered {} ({ident})", fn_name!());
|
||||
let name = self
|
||||
.local_search(ident.inspect(), acc_kind)
|
||||
.unwrap_or_else(|| {
|
||||
if acc_kind.is_local() {
|
||||
self.register_name(ident)
|
||||
} else {
|
||||
self.register_attr("", None, ident.inspect().clone())
|
||||
}
|
||||
});
|
||||
let escaped = escape_name(ident);
|
||||
let name = self.local_search(&escaped, acc_kind).unwrap_or_else(|| {
|
||||
if acc_kind.is_local() {
|
||||
self.register_name(escaped)
|
||||
} else {
|
||||
self.register_attr(escaped)
|
||||
}
|
||||
});
|
||||
let instr = match name.kind {
|
||||
StoreLoadKind::Fast => Opcode::STORE_FAST,
|
||||
StoreLoadKind::FastConst => Opcode::ERG_STORE_FAST_IMMUT,
|
||||
|
@ -668,18 +680,12 @@ impl CodeGenerator {
|
|||
fn store_acc(&mut self, acc: Accessor) {
|
||||
log!(info "entered {} ({acc})", fn_name!());
|
||||
match acc {
|
||||
Accessor::Local(local) => {
|
||||
self.emit_store_instr(Identifier::new(None, VarName::new(local.name)), Name);
|
||||
}
|
||||
Accessor::Public(public) => {
|
||||
self.emit_store_instr(
|
||||
Identifier::new(Some(public.dot), VarName::new(public.name)),
|
||||
Name,
|
||||
);
|
||||
Accessor::Ident(ident) => {
|
||||
self.emit_store_instr(ident, Name);
|
||||
}
|
||||
Accessor::Attr(attr) => {
|
||||
self.codegen_expr(*attr.obj);
|
||||
self.emit_store_instr(Identifier::new(None, VarName::new(attr.name)), Attr);
|
||||
self.emit_store_instr(attr.ident, Attr);
|
||||
}
|
||||
acc => todo!("store: {acc}"),
|
||||
}
|
||||
|
@ -728,7 +734,8 @@ impl CodeGenerator {
|
|||
.iter()
|
||||
.map(|p| p.inspect().map(|s| &s[..]).unwrap_or("_")),
|
||||
)
|
||||
.map(|s| self.get_cached(s))
|
||||
.map(|s| format!("::{s}"))
|
||||
.map(|s| self.get_cached(&s))
|
||||
.collect()
|
||||
}
|
||||
|
||||
|
@ -938,7 +945,7 @@ impl CodeGenerator {
|
|||
let mut pop_jump_points = vec![];
|
||||
match pat {
|
||||
ParamPattern::VarName(name) => {
|
||||
let ident = Identifier::new(None, name);
|
||||
let ident = Identifier::bare(None, name);
|
||||
self.emit_store_instr(ident, AccessKind::Name);
|
||||
}
|
||||
ParamPattern::Lit(lit) => {
|
||||
|
@ -993,8 +1000,8 @@ impl CodeGenerator {
|
|||
self.emit_call_method(*call.obj, method_name, call.args);
|
||||
} else {
|
||||
match *call.obj {
|
||||
Expr::Accessor(Accessor::Local(local)) => {
|
||||
self.emit_call_local(local, call.args).unwrap()
|
||||
Expr::Accessor(Accessor::Ident(ident)) if ident.vis().is_private() => {
|
||||
self.emit_call_local(ident, call.args).unwrap()
|
||||
}
|
||||
other => {
|
||||
self.codegen_expr(other);
|
||||
|
@ -1004,7 +1011,7 @@ impl CodeGenerator {
|
|||
}
|
||||
}
|
||||
|
||||
fn emit_call_local(&mut self, local: Local, args: Args) -> CompileResult<()> {
|
||||
fn emit_call_local(&mut self, local: Identifier, args: Args) -> CompileResult<()> {
|
||||
log!(info "entered {}", fn_name!());
|
||||
match &local.inspect()[..] {
|
||||
"assert" => self.emit_assert_instr(args),
|
||||
|
@ -1013,9 +1020,7 @@ impl CodeGenerator {
|
|||
"if" | "if!" => self.emit_if_instr(args),
|
||||
"match" | "match!" => self.emit_match_instr(args, true),
|
||||
_ => {
|
||||
let name = VarName::new(local.name);
|
||||
let ident = Identifier::new(None, name);
|
||||
self.emit_load_name_instr(ident).unwrap_or_else(|e| {
|
||||
self.emit_load_name_instr(local).unwrap_or_else(|e| {
|
||||
self.errs.push(e);
|
||||
});
|
||||
self.emit_args(args, Name);
|
||||
|
@ -1032,14 +1037,10 @@ impl CodeGenerator {
|
|||
let class = obj.ref_t().name(); // これは必ずmethodのあるクラスになっている
|
||||
let uniq_obj_name = obj.__name__().map(Str::rc);
|
||||
self.codegen_expr(obj);
|
||||
self.emit_load_method_instr(
|
||||
&class,
|
||||
uniq_obj_name.as_ref().map(|s| &s[..]),
|
||||
method_name.name.into_token().content,
|
||||
)
|
||||
.unwrap_or_else(|err| {
|
||||
self.errs.push(err);
|
||||
});
|
||||
self.emit_load_method_instr(&class, uniq_obj_name.as_ref().map(|s| &s[..]), method_name)
|
||||
.unwrap_or_else(|err| {
|
||||
self.errs.push(err);
|
||||
});
|
||||
self.emit_args(args, Method);
|
||||
}
|
||||
|
||||
|
@ -1361,14 +1362,7 @@ impl CodeGenerator {
|
|||
fn codegen_acc(&mut self, acc: Accessor) {
|
||||
log!(info "entered {} ({acc})", fn_name!());
|
||||
match acc {
|
||||
Accessor::Local(local) => {
|
||||
self.emit_load_name_instr(Identifier::new(None, VarName::new(local.name)))
|
||||
.unwrap_or_else(|err| {
|
||||
self.errs.push(err);
|
||||
});
|
||||
}
|
||||
Accessor::Public(public) => {
|
||||
let ident = Identifier::new(Some(public.dot), VarName::new(public.name));
|
||||
Accessor::Ident(ident) => {
|
||||
self.emit_load_name_instr(ident).unwrap_or_else(|err| {
|
||||
self.errs.push(err);
|
||||
});
|
||||
|
@ -1377,14 +1371,10 @@ impl CodeGenerator {
|
|||
let class = a.obj.ref_t().name();
|
||||
let uniq_obj_name = a.obj.__name__().map(Str::rc);
|
||||
self.codegen_expr(*a.obj);
|
||||
self.emit_load_attr_instr(
|
||||
&class,
|
||||
uniq_obj_name.as_ref().map(|s| &s[..]),
|
||||
a.name.content.clone(),
|
||||
)
|
||||
.unwrap_or_else(|err| {
|
||||
self.errs.push(err);
|
||||
});
|
||||
self.emit_load_attr_instr(&class, uniq_obj_name.as_ref().map(|s| &s[..]), a.ident)
|
||||
.unwrap_or_else(|err| {
|
||||
self.errs.push(err);
|
||||
});
|
||||
}
|
||||
Accessor::TupleAttr(t_attr) => {
|
||||
self.codegen_expr(*t_attr.obj);
|
||||
|
@ -1516,26 +1506,32 @@ impl CodeGenerator {
|
|||
let subr_sig = SubrSignature::new(ident, params.clone(), __new__.clone());
|
||||
let mut attrs = vec![];
|
||||
match __new__.non_default_params().unwrap()[0].typ() {
|
||||
// namedtupleは仕様上::xなどの名前を使えない
|
||||
// {x = Int; y = Int}
|
||||
// self.x = %x.x; self.y = %x.y
|
||||
// => self::x = %x.x; self::y = %x.y
|
||||
// {.x = Int; .y = Int}
|
||||
// => self.x = %x.x; self.y = %x.y
|
||||
Type::Record(rec) => {
|
||||
for field in rec.keys() {
|
||||
let obj = Expr::Accessor(Accessor::local(
|
||||
Token::symbol_with_line(¶m_name[..], line),
|
||||
Type::Failure,
|
||||
));
|
||||
let obj =
|
||||
Expr::Accessor(Accessor::private_with_line(Str::from(¶m_name), line));
|
||||
let expr = Expr::Accessor(Accessor::Attr(Attribute::new(
|
||||
obj,
|
||||
Token::symbol(&field.symbol[..]),
|
||||
Identifier::bare(
|
||||
Some(Token::dummy()),
|
||||
VarName::from_str(field.symbol.clone()),
|
||||
),
|
||||
Type::Failure,
|
||||
)));
|
||||
let obj = Expr::Accessor(Accessor::local(
|
||||
Token::symbol_with_line("self", line),
|
||||
Type::Failure,
|
||||
));
|
||||
let obj = Expr::Accessor(Accessor::private_with_line(Str::ever("self"), line));
|
||||
let dot = if field.vis.is_private() {
|
||||
None
|
||||
} else {
|
||||
Some(Token::dummy())
|
||||
};
|
||||
let attr = Accessor::Attr(Attribute::new(
|
||||
obj,
|
||||
Token::symbol(&field.symbol[..]),
|
||||
Identifier::bare(dot, VarName::from_str(field.symbol.clone())),
|
||||
Type::Failure,
|
||||
));
|
||||
let attr_def = AttrDef::new(attr, Block::new(vec![expr]));
|
||||
|
@ -1569,17 +1565,14 @@ impl CodeGenerator {
|
|||
Params::new(vec![param], None, vec![], None),
|
||||
__new__.clone(),
|
||||
);
|
||||
let arg = PosArg::new(Expr::Accessor(Accessor::local(
|
||||
Token::symbol_with_line(¶m_name[..], line),
|
||||
Type::Failure,
|
||||
let arg = PosArg::new(Expr::Accessor(Accessor::private_with_line(
|
||||
Str::from(param_name),
|
||||
line,
|
||||
)));
|
||||
let class = Expr::Accessor(Accessor::local(
|
||||
Token::symbol_with_line(class_name, line),
|
||||
Type::Failure,
|
||||
));
|
||||
let class = Expr::Accessor(Accessor::private_with_line(class_name.clone(), line));
|
||||
let class_new = Expr::Accessor(Accessor::attr(
|
||||
class,
|
||||
Token::symbol_with_line("__new__", line),
|
||||
Identifier::bare(None, VarName::from_str_and_line(Str::ever("__new__"), line)),
|
||||
Type::Failure,
|
||||
));
|
||||
let call = Expr::Call(Call::new(
|
||||
|
|
|
@ -166,17 +166,17 @@ impl SubstContext {
|
|||
impl Context {
|
||||
fn eval_const_acc(&self, acc: &Accessor) -> EvalResult<ValueObj> {
|
||||
match acc {
|
||||
Accessor::Local(local) => {
|
||||
if let Some(val) = self.rec_get_const_obj(local.inspect()) {
|
||||
Accessor::Ident(ident) => {
|
||||
if let Some(val) = self.rec_get_const_obj(ident.inspect()) {
|
||||
Ok(val.clone())
|
||||
} else {
|
||||
if local.is_const() {
|
||||
if ident.is_const() {
|
||||
Err(EvalError::no_var_error(
|
||||
line!() as usize,
|
||||
local.loc(),
|
||||
ident.loc(),
|
||||
self.caused_by(),
|
||||
local.inspect(),
|
||||
self.get_similar_name(local.inspect()),
|
||||
ident.inspect(),
|
||||
self.get_similar_name(ident.inspect()),
|
||||
))
|
||||
} else {
|
||||
Err(EvalError::not_const_expr(
|
||||
|
@ -232,22 +232,22 @@ impl Context {
|
|||
fn eval_const_call(&self, call: &Call, __name__: Option<&Str>) -> EvalResult<ValueObj> {
|
||||
if let Expr::Accessor(acc) = call.obj.as_ref() {
|
||||
match acc {
|
||||
Accessor::Local(name) => {
|
||||
Accessor::Ident(ident) => {
|
||||
let obj =
|
||||
self.rec_get_const_obj(&name.inspect())
|
||||
self.rec_get_const_obj(&ident.inspect())
|
||||
.ok_or(EvalError::no_var_error(
|
||||
line!() as usize,
|
||||
name.loc(),
|
||||
ident.loc(),
|
||||
self.caused_by(),
|
||||
name.inspect(),
|
||||
self.get_similar_name(name.inspect()),
|
||||
ident.inspect(),
|
||||
self.get_similar_name(ident.inspect()),
|
||||
))?;
|
||||
let subr = option_enum_unwrap!(obj, ValueObj::Subr)
|
||||
.ok_or(EvalError::type_mismatch_error(
|
||||
line!() as usize,
|
||||
name.loc(),
|
||||
ident.loc(),
|
||||
self.caused_by(),
|
||||
name.inspect(),
|
||||
ident.inspect(),
|
||||
&mono("Subroutine"),
|
||||
&obj.t(),
|
||||
None,
|
||||
|
@ -258,7 +258,6 @@ impl Context {
|
|||
}
|
||||
Accessor::Attr(_attr) => todo!(),
|
||||
Accessor::TupleAttr(_attr) => todo!(),
|
||||
Accessor::Public(_name) => todo!(),
|
||||
Accessor::Subscr(_subscr) => todo!(),
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -91,17 +91,17 @@ impl Context {
|
|||
namespace: &Str,
|
||||
) -> TyCheckResult<&Context> {
|
||||
match obj {
|
||||
hir::Expr::Accessor(hir::Accessor::Local(name)) => {
|
||||
hir::Expr::Accessor(hir::Accessor::Ident(ident)) => {
|
||||
if kind == Some(ContextKind::Module) {
|
||||
if let Some(ctx) = self.rec_get_mod(name.inspect()) {
|
||||
if let Some(ctx) = self.rec_get_mod(ident.inspect()) {
|
||||
Ok(ctx)
|
||||
} else {
|
||||
Err(TyCheckError::no_var_error(
|
||||
line!() as usize,
|
||||
obj.loc(),
|
||||
namespace.clone(),
|
||||
name.inspect(),
|
||||
self.get_similar_name(name.inspect()),
|
||||
ident.inspect(),
|
||||
self.get_similar_name(ident.inspect()),
|
||||
))
|
||||
}
|
||||
} else {
|
||||
|
@ -197,34 +197,20 @@ impl Context {
|
|||
None
|
||||
}
|
||||
|
||||
pub(crate) fn rec_get_var_t(
|
||||
&self,
|
||||
name: &Token,
|
||||
vis: Visibility,
|
||||
namespace: &Str,
|
||||
) -> TyCheckResult<Type> {
|
||||
if let Some(vi) = self.get_current_scope_var(&name.inspect()[..]) {
|
||||
if vi.vis == vis {
|
||||
Ok(vi.t())
|
||||
} else {
|
||||
Err(TyCheckError::visibility_error(
|
||||
line!() as usize,
|
||||
name.loc(),
|
||||
namespace.clone(),
|
||||
name.inspect(),
|
||||
vi.vis,
|
||||
))
|
||||
}
|
||||
pub(crate) fn rec_get_var_t(&self, ident: &Identifier, namespace: &Str) -> TyCheckResult<Type> {
|
||||
if let Some(vi) = self.get_current_scope_var(&ident.inspect()[..]) {
|
||||
// self.validate_visibility(ident, vi, self)?;
|
||||
Ok(vi.t())
|
||||
} else {
|
||||
if let Some(parent) = self.outer.as_ref() {
|
||||
return parent.rec_get_var_t(name, vis, namespace);
|
||||
return parent.rec_get_var_t(ident, namespace);
|
||||
}
|
||||
Err(TyCheckError::no_var_error(
|
||||
line!() as usize,
|
||||
name.loc(),
|
||||
ident.loc(),
|
||||
namespace.clone(),
|
||||
name.inspect(),
|
||||
self.get_similar_name(name.inspect()),
|
||||
ident.inspect(),
|
||||
self.get_similar_name(ident.inspect()),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
@ -232,11 +218,12 @@ impl Context {
|
|||
pub(crate) fn rec_get_attr_t(
|
||||
&self,
|
||||
obj: &hir::Expr,
|
||||
name: &Token,
|
||||
ident: &Identifier,
|
||||
namespace: &Str,
|
||||
) -> TyCheckResult<Type> {
|
||||
let self_t = obj.t();
|
||||
match self.get_attr_t_from_attributive_t(obj, &self_t, name, namespace) {
|
||||
let name = ident.name.token();
|
||||
match self.get_attr_t_from_attributive_t(obj, &self_t, ident, namespace) {
|
||||
Ok(t) => {
|
||||
return Ok(t);
|
||||
}
|
||||
|
@ -245,17 +232,22 @@ impl Context {
|
|||
return Err(e);
|
||||
}
|
||||
}
|
||||
if let Some(singular_ctx) = self.rec_get_singular_ctx(obj) {
|
||||
if let Ok(t) = singular_ctx.rec_get_var_t(ident, namespace) {
|
||||
return Ok(t);
|
||||
}
|
||||
}
|
||||
for (_, ctx) in self
|
||||
.rec_get_nominal_super_type_ctxs(&self_t)
|
||||
.ok_or_else(|| todo!())?
|
||||
{
|
||||
if let Ok(t) = ctx.rec_get_var_t(name, Public, namespace) {
|
||||
if let Ok(t) = ctx.rec_get_var_t(ident, namespace) {
|
||||
return Ok(t);
|
||||
}
|
||||
}
|
||||
// TODO: dependent type widening
|
||||
if let Some(parent) = self.outer.as_ref() {
|
||||
parent.rec_get_attr_t(obj, name, namespace)
|
||||
parent.rec_get_attr_t(obj, ident, namespace)
|
||||
} else {
|
||||
Err(TyCheckError::no_attr_error(
|
||||
line!() as usize,
|
||||
|
@ -272,53 +264,56 @@ impl Context {
|
|||
&self,
|
||||
obj: &hir::Expr,
|
||||
t: &Type,
|
||||
name: &Token,
|
||||
ident: &Identifier,
|
||||
namespace: &Str,
|
||||
) -> TyCheckResult<Type> {
|
||||
match t {
|
||||
Type::FreeVar(fv) if fv.is_linked() => {
|
||||
self.get_attr_t_from_attributive_t(obj, &fv.crack(), name, namespace)
|
||||
self.get_attr_t_from_attributive_t(obj, &fv.crack(), ident, namespace)
|
||||
}
|
||||
Type::FreeVar(fv) => {
|
||||
let sup = fv.get_sup().unwrap();
|
||||
self.get_attr_t_from_attributive_t(obj, &sup, name, namespace)
|
||||
self.get_attr_t_from_attributive_t(obj, &sup, ident, namespace)
|
||||
}
|
||||
Type::Ref(t) => self.get_attr_t_from_attributive_t(obj, t, name, namespace),
|
||||
Type::Ref(t) => self.get_attr_t_from_attributive_t(obj, t, ident, namespace),
|
||||
Type::RefMut { before, .. } => {
|
||||
self.get_attr_t_from_attributive_t(obj, before, name, namespace)
|
||||
self.get_attr_t_from_attributive_t(obj, before, ident, namespace)
|
||||
}
|
||||
Type::Refinement(refine) => {
|
||||
self.get_attr_t_from_attributive_t(obj, &refine.t, name, namespace)
|
||||
self.get_attr_t_from_attributive_t(obj, &refine.t, ident, namespace)
|
||||
}
|
||||
Type::Record(record) => {
|
||||
// REVIEW: `rec.get(name.inspect())` returns None (Borrow<Str> is implemented for Field). Why?
|
||||
if let Some(attr) = record.get(&Field::new(Public, name.inspect().clone())) {
|
||||
if let Some(attr) = record.get(&Field::new(Public, ident.inspect().clone())) {
|
||||
Ok(attr.clone())
|
||||
} else {
|
||||
let t = Type::Record(record.clone());
|
||||
Err(TyCheckError::no_attr_error(
|
||||
line!() as usize,
|
||||
name.loc(),
|
||||
ident.loc(),
|
||||
namespace.clone(),
|
||||
&t,
|
||||
name.inspect(),
|
||||
self.get_similar_attr(&t, name.inspect()),
|
||||
ident.inspect(),
|
||||
self.get_similar_attr(&t, ident.inspect()),
|
||||
))
|
||||
}
|
||||
}
|
||||
Module => {
|
||||
let mod_ctx = self.get_context(obj, Some(ContextKind::Module), namespace)?;
|
||||
let t = mod_ctx.rec_get_var_t(name, Public, namespace)?;
|
||||
let t = mod_ctx.rec_get_var_t(ident, namespace)?;
|
||||
Ok(t)
|
||||
}
|
||||
other => {
|
||||
if let Some(v) = self.rec_get_const_obj(&other.name()) {
|
||||
match v {
|
||||
ValueObj::Type(TypeObj::Generated(gen)) => self
|
||||
.get_gen_t_require_attr_t(gen, &name.inspect()[..])
|
||||
.get_gen_t_require_attr_t(gen, &ident.inspect()[..])
|
||||
.map(|t| t.clone())
|
||||
.ok_or(TyCheckError::dummy(line!() as usize)),
|
||||
ValueObj::Type(TypeObj::Builtin(t)) => todo!("{t}"),
|
||||
ValueObj::Type(TypeObj::Builtin(_t)) => {
|
||||
// FIXME:
|
||||
Err(TyCheckError::dummy(line!() as usize))
|
||||
}
|
||||
other => todo!("{other}"),
|
||||
}
|
||||
} else {
|
||||
|
@ -421,8 +416,9 @@ impl Context {
|
|||
&& self
|
||||
.outer
|
||||
.as_ref()
|
||||
.map(|outer| outer.name.split("::").last().unwrap_or(&outer.name))
|
||||
.map(|name| name != &ctx.name[..])
|
||||
// TODO: also split with `.`
|
||||
.map(|outer| outer.name.split("::"))
|
||||
.map(|mut names| names.all(|name| name != &ctx.name[..]))
|
||||
.unwrap_or(true)
|
||||
{
|
||||
Err(TyCheckError::visibility_error(
|
||||
|
@ -446,14 +442,17 @@ impl Context {
|
|||
erg_common::debug_power_assert!(args.len() == 2);
|
||||
let cont = binop_to_dname(op.inspect());
|
||||
let symbol = Token::new(op.kind, Str::rc(cont), op.lineno, op.col_begin);
|
||||
let t = self.rec_get_var_t(&symbol, Private, namespace)?;
|
||||
let op = hir::Expr::Accessor(hir::Accessor::local(symbol, t));
|
||||
let t = self.rec_get_var_t(
|
||||
&Identifier::new(None, VarName::new(symbol.clone())),
|
||||
namespace,
|
||||
)?;
|
||||
let op = hir::Expr::Accessor(hir::Accessor::private(symbol, t));
|
||||
self.get_call_t(&op, &None, args, &[], namespace)
|
||||
.map_err(|e| {
|
||||
let op = enum_unwrap!(op, hir::Expr::Accessor:(hir::Accessor::Local:(_)));
|
||||
let op = enum_unwrap!(op, hir::Expr::Accessor:(hir::Accessor::Ident:(_)));
|
||||
let lhs = args[0].expr.clone();
|
||||
let rhs = args[1].expr.clone();
|
||||
let bin = hir::BinOp::new(op.name, lhs, rhs, op.t);
|
||||
let bin = hir::BinOp::new(op.name.into_token(), lhs, rhs, op.t.clone());
|
||||
// HACK: dname.loc()はダミーLocationしか返さないので、エラーならop.loc()で上書きする
|
||||
let core = ErrorCore::new(
|
||||
e.core.errno,
|
||||
|
@ -475,13 +474,16 @@ impl Context {
|
|||
erg_common::debug_power_assert!(args.len() == 1);
|
||||
let cont = unaryop_to_dname(op.inspect());
|
||||
let symbol = Token::new(op.kind, Str::rc(cont), op.lineno, op.col_begin);
|
||||
let t = self.rec_get_var_t(&symbol, Private, namespace)?;
|
||||
let op = hir::Expr::Accessor(hir::Accessor::local(symbol, t));
|
||||
let t = self.rec_get_var_t(
|
||||
&Identifier::new(None, VarName::new(symbol.clone())),
|
||||
namespace,
|
||||
)?;
|
||||
let op = hir::Expr::Accessor(hir::Accessor::private(symbol, t));
|
||||
self.get_call_t(&op, &None, args, &[], namespace)
|
||||
.map_err(|e| {
|
||||
let op = enum_unwrap!(op, hir::Expr::Accessor:(hir::Accessor::Local:(_)));
|
||||
let op = enum_unwrap!(op, hir::Expr::Accessor:(hir::Accessor::Ident:(_)));
|
||||
let expr = args[0].expr.clone();
|
||||
let unary = hir::UnaryOp::new(op.name, expr, op.t);
|
||||
let unary = hir::UnaryOp::new(op.name.into_token(), expr, op.t.clone());
|
||||
let core = ErrorCore::new(
|
||||
e.core.errno,
|
||||
e.core.kind,
|
||||
|
@ -655,7 +657,7 @@ impl Context {
|
|||
let callee = if let Some(ident) = method_name {
|
||||
let attr = hir::Attribute::new(
|
||||
obj.clone(),
|
||||
ident.name.clone().into_token(),
|
||||
hir::Identifier::bare(ident.dot.clone(), ident.name.clone()),
|
||||
Type::Uninited,
|
||||
);
|
||||
let acc = hir::Expr::Accessor(hir::Accessor::Attr(attr));
|
||||
|
@ -886,7 +888,9 @@ impl Context {
|
|||
namespace: &Str,
|
||||
) -> TyCheckResult<Type> {
|
||||
match obj {
|
||||
hir::Expr::Accessor(hir::Accessor::Local(local)) if &local.inspect()[..] == "match" => {
|
||||
hir::Expr::Accessor(hir::Accessor::Ident(local))
|
||||
if local.vis().is_private() && &local.inspect()[..] == "match" =>
|
||||
{
|
||||
return self.get_match_call_t(pos_args, kw_args);
|
||||
}
|
||||
_ => {}
|
||||
|
|
|
@ -109,7 +109,7 @@ impl Context {
|
|||
.decorators
|
||||
.iter()
|
||||
.filter_map(|deco| match &deco.0 {
|
||||
ast::Expr::Accessor(ast::Accessor::Local(local)) if local.is_const() => {
|
||||
ast::Expr::Accessor(ast::Accessor::Ident(local)) if local.is_const() => {
|
||||
Some(local.inspect().clone())
|
||||
}
|
||||
_ => None,
|
||||
|
@ -428,7 +428,7 @@ impl Context {
|
|||
.decorators
|
||||
.iter()
|
||||
.filter_map(|deco| match &deco.0 {
|
||||
ast::Expr::Accessor(ast::Accessor::Local(local)) if local.is_const() => {
|
||||
ast::Expr::Accessor(ast::Accessor::Ident(local)) if local.is_const() => {
|
||||
Some(local.inspect().clone())
|
||||
}
|
||||
_ => None,
|
||||
|
|
|
@ -371,7 +371,7 @@ impl Context {
|
|||
self.deref_expr_t(&mut subscr.obj)?;
|
||||
self.deref_expr_t(&mut subscr.index)?;
|
||||
}
|
||||
hir::Accessor::Local(_) | hir::Accessor::Public(_) => {}
|
||||
hir::Accessor::Ident(_) => {}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -259,10 +259,10 @@ impl SideEffectChecker {
|
|||
Expr::Lambda(lambda) => lambda.is_procedural(),
|
||||
// 引数がproceduralでも関数呼び出しなら副作用なし
|
||||
Expr::Call(call) => self.is_procedural(&call.obj),
|
||||
Expr::Accessor(Accessor::Local(local)) => local.name.is_procedural(),
|
||||
Expr::Accessor(Accessor::Ident(ident)) => ident.name.is_procedural(),
|
||||
// procedural: x.y! (e.g. Array.sample!)
|
||||
// !procedural: !x.y
|
||||
Expr::Accessor(Accessor::Attr(attr)) => attr.name.is_procedural(),
|
||||
Expr::Accessor(Accessor::Attr(attr)) => attr.ident.is_procedural(),
|
||||
Expr::Accessor(_) => todo!(),
|
||||
_ => false,
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ use erg_common::{
|
|||
impl_stream_for_wrapper,
|
||||
};
|
||||
|
||||
use erg_parser::ast::{fmt_lines, DefId, Identifier, Params, TypeSpec};
|
||||
use erg_parser::ast::{fmt_lines, DefId, Params, TypeSpec, VarName};
|
||||
use erg_parser::token::{Token, TokenKind};
|
||||
|
||||
use erg_type::constructors::{array, tuple};
|
||||
|
@ -286,84 +286,55 @@ impl Args {
|
|||
}
|
||||
}
|
||||
|
||||
/// represents local variables
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Local {
|
||||
pub name: Token,
|
||||
/// オブジェクト自身の名前
|
||||
__name__: Option<Str>,
|
||||
pub(crate) t: Type,
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct Identifier {
|
||||
pub dot: Option<Token>,
|
||||
pub name: VarName,
|
||||
pub __name__: Option<Str>,
|
||||
pub t: Type,
|
||||
}
|
||||
|
||||
impl NestedDisplay for Local {
|
||||
impl NestedDisplay for Identifier {
|
||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
|
||||
let __name__ = if let Some(__name__) = self.__name__() {
|
||||
format!("(__name__ = {__name__})")
|
||||
} else {
|
||||
"".to_string()
|
||||
};
|
||||
write!(f, "{} (: {}){}", self.name.content, self.t, __name__)
|
||||
match &self.dot {
|
||||
Some(_dot) => {
|
||||
write!(f, ".{}", self.name)?;
|
||||
}
|
||||
None => {
|
||||
write!(f, "::{}", self.name)?;
|
||||
}
|
||||
}
|
||||
if let Some(__name__) = &self.__name__ {
|
||||
write!(f, "(__name__: {})", __name__)?;
|
||||
}
|
||||
if self.t != Type::Uninited {
|
||||
write!(f, "(: {})", self.t)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl_display_from_nested!(Local);
|
||||
impl_t!(Local);
|
||||
impl_display_from_nested!(Identifier);
|
||||
impl_t!(Identifier);
|
||||
|
||||
impl Locational for Local {
|
||||
#[inline]
|
||||
impl Locational for Identifier {
|
||||
fn loc(&self) -> Location {
|
||||
self.name.loc()
|
||||
}
|
||||
}
|
||||
|
||||
impl Local {
|
||||
pub const fn new(name: Token, __name__: Option<Str>, t: Type) -> Self {
|
||||
Self { name, __name__, t }
|
||||
}
|
||||
|
||||
// &strにするとクローンしたいときにアロケーションコストがかかるので&Strのままで
|
||||
#[inline]
|
||||
pub fn inspect(&self) -> &Str {
|
||||
&self.name.content
|
||||
}
|
||||
|
||||
pub const fn __name__(&self) -> Option<&Str> {
|
||||
self.__name__.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Public {
|
||||
pub dot: Token,
|
||||
pub name: Token,
|
||||
/// オブジェクト自身の名前
|
||||
__name__: Option<Str>,
|
||||
t: Type,
|
||||
}
|
||||
|
||||
impl NestedDisplay for Public {
|
||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
|
||||
let __name__ = if let Some(__name__) = self.__name__() {
|
||||
format!("(__name__ = {__name__})")
|
||||
if let Some(dot) = &self.dot {
|
||||
Location::concat(dot, &self.name)
|
||||
} else {
|
||||
"".to_string()
|
||||
};
|
||||
write!(f, ".{} (: {}){}", self.name.content, self.t, __name__)
|
||||
self.name.loc()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_display_from_nested!(Public);
|
||||
impl_t!(Public);
|
||||
|
||||
impl Locational for Public {
|
||||
#[inline]
|
||||
fn loc(&self) -> Location {
|
||||
Location::concat(&self.dot, &self.name)
|
||||
impl From<&Identifier> for Field {
|
||||
fn from(ident: &Identifier) -> Self {
|
||||
Self::new(ident.vis(), ident.inspect().clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl Public {
|
||||
pub const fn new(dot: Token, name: Token, __name__: Option<Str>, t: Type) -> Self {
|
||||
impl Identifier {
|
||||
pub const fn new(dot: Option<Token>, name: VarName, __name__: Option<Str>, t: Type) -> Self {
|
||||
Self {
|
||||
dot,
|
||||
name,
|
||||
|
@ -372,43 +343,75 @@ impl Public {
|
|||
}
|
||||
}
|
||||
|
||||
// &strにするとクローンしたいときにアロケーションコストがかかるので&Strのままで
|
||||
#[inline]
|
||||
pub fn inspect(&self) -> &Str {
|
||||
&self.name.content
|
||||
pub fn public(name: &'static str) -> Self {
|
||||
Self::bare(
|
||||
Some(Token::from_str(TokenKind::Dot, ".")),
|
||||
VarName::from_static(name),
|
||||
)
|
||||
}
|
||||
|
||||
pub const fn __name__(&self) -> Option<&Str> {
|
||||
self.__name__.as_ref()
|
||||
pub fn private(name: Str) -> Self {
|
||||
Self::bare(None, VarName::from_str(name))
|
||||
}
|
||||
|
||||
pub fn private_with_line(name: Str, line: usize) -> Self {
|
||||
Self::bare(None, VarName::from_str_and_line(name, line))
|
||||
}
|
||||
|
||||
pub fn public_with_line(dot: Token, name: Str, line: usize) -> Self {
|
||||
Self::bare(Some(dot), VarName::from_str_and_line(name, line))
|
||||
}
|
||||
|
||||
pub const fn bare(dot: Option<Token>, name: VarName) -> Self {
|
||||
Self::new(dot, name, None, Type::Uninited)
|
||||
}
|
||||
|
||||
pub fn is_const(&self) -> bool {
|
||||
self.name.is_const()
|
||||
}
|
||||
|
||||
pub const fn vis(&self) -> Visibility {
|
||||
match &self.dot {
|
||||
Some(_) => Visibility::Public,
|
||||
None => Visibility::Private,
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn inspect(&self) -> &Str {
|
||||
&self.name.inspect()
|
||||
}
|
||||
|
||||
pub fn is_procedural(&self) -> bool {
|
||||
self.name.is_procedural()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Attribute {
|
||||
pub obj: Box<Expr>,
|
||||
pub name: Token,
|
||||
pub ident: Identifier,
|
||||
t: Type,
|
||||
}
|
||||
|
||||
impl NestedDisplay for Attribute {
|
||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
|
||||
if self.t != Type::Uninited {
|
||||
write!(f, "({}).{}(: {})", self.obj, self.name.content, self.t)
|
||||
write!(f, "({}){}(: {})", self.obj, self.ident, self.t)
|
||||
} else {
|
||||
write!(f, "({}).{}", self.obj, self.name.content)
|
||||
write!(f, "({}){}", self.obj, self.ident)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_display_from_nested!(Attribute);
|
||||
impl_locational!(Attribute, obj, name);
|
||||
impl_locational!(Attribute, obj, ident);
|
||||
impl_t!(Attribute);
|
||||
|
||||
impl Attribute {
|
||||
pub fn new(obj: Expr, name: Token, t: Type) -> Self {
|
||||
pub fn new(obj: Expr, ident: Identifier, t: Type) -> Self {
|
||||
Self {
|
||||
obj: Box::new(obj),
|
||||
name,
|
||||
ident,
|
||||
t,
|
||||
}
|
||||
}
|
||||
|
@ -471,29 +474,32 @@ impl Subscript {
|
|||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Accessor {
|
||||
Local(Local),
|
||||
Public(Public),
|
||||
Ident(Identifier),
|
||||
Attr(Attribute),
|
||||
TupleAttr(TupleAttribute),
|
||||
Subscr(Subscript),
|
||||
}
|
||||
|
||||
impl_nested_display_for_enum!(Accessor; Local, Public, Attr, TupleAttr, Subscr);
|
||||
impl_nested_display_for_enum!(Accessor; Ident, Attr, TupleAttr, Subscr);
|
||||
impl_display_from_nested!(Accessor);
|
||||
impl_locational_for_enum!(Accessor; Local, Public, Attr, TupleAttr, Subscr);
|
||||
impl_t_for_enum!(Accessor; Local, Public, Attr, TupleAttr, Subscr);
|
||||
impl_locational_for_enum!(Accessor; Ident, Attr, TupleAttr, Subscr);
|
||||
impl_t_for_enum!(Accessor; Ident, Attr, TupleAttr, Subscr);
|
||||
|
||||
impl Accessor {
|
||||
pub const fn local(symbol: Token, t: Type) -> Self {
|
||||
Self::Local(Local::new(symbol, None, t))
|
||||
pub fn private_with_line(name: Str, line: usize) -> Self {
|
||||
Self::Ident(Identifier::private_with_line(name, line))
|
||||
}
|
||||
|
||||
pub const fn public(dot: Token, name: Token, t: Type) -> Self {
|
||||
Self::Public(Public::new(dot, name, None, t))
|
||||
pub fn public_with_line(name: Str, line: usize) -> Self {
|
||||
Self::Ident(Identifier::public_with_line(Token::dummy(), name, line))
|
||||
}
|
||||
|
||||
pub fn attr(obj: Expr, name: Token, t: Type) -> Self {
|
||||
Self::Attr(Attribute::new(obj, name, t))
|
||||
pub const fn private(name: Token, t: Type) -> Self {
|
||||
Self::Ident(Identifier::new(None, VarName::new(name), None, t))
|
||||
}
|
||||
|
||||
pub fn attr(obj: Expr, ident: Identifier, t: Type) -> Self {
|
||||
Self::Attr(Attribute::new(obj, ident, t))
|
||||
}
|
||||
|
||||
pub fn subscr(obj: Expr, index: Expr, t: Type) -> Self {
|
||||
|
@ -502,14 +508,13 @@ impl Accessor {
|
|||
|
||||
pub fn show(&self) -> String {
|
||||
match self {
|
||||
Self::Local(local) => readable_name(local.inspect()).to_string(),
|
||||
Self::Public(public) => readable_name(public.inspect()).to_string(),
|
||||
Self::Ident(ident) => readable_name(ident.inspect()).to_string(),
|
||||
Self::Attr(attr) => {
|
||||
attr.obj
|
||||
.show_acc()
|
||||
.unwrap_or_else(|| attr.obj.ref_t().to_string())
|
||||
+ "."
|
||||
+ readable_name(attr.name.inspect())
|
||||
+ "." // TODO: visibility
|
||||
+ readable_name(attr.ident.inspect())
|
||||
}
|
||||
Self::TupleAttr(t_attr) => {
|
||||
t_attr
|
||||
|
@ -526,8 +531,7 @@ impl Accessor {
|
|||
// 参照するオブジェクト自体が持っている固有の名前
|
||||
pub fn __name__(&self) -> Option<&str> {
|
||||
match self {
|
||||
Self::Local(local) => local.__name__().map(|s| &s[..]),
|
||||
Self::Public(public) => public.__name__().map(|s| &s[..]),
|
||||
Self::Ident(ident) => ident.__name__.as_ref().map(|s| &s[..]),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -1260,19 +1264,6 @@ impl DefBody {
|
|||
pub const fn new(op: Token, block: Block, id: DefId) -> Self {
|
||||
Self { op, block, id }
|
||||
}
|
||||
|
||||
pub fn is_type(&self) -> bool {
|
||||
match self.block.first().unwrap() {
|
||||
Expr::Call(call) => {
|
||||
if let Expr::Accessor(Accessor::Local(local)) = call.obj.as_ref() {
|
||||
&local.inspect()[..] == "Type"
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
|
|
@ -271,7 +271,7 @@ impl ASTLowerer {
|
|||
fn lower_acc(&mut self, acc: ast::Accessor) -> LowerResult<hir::Accessor> {
|
||||
log!(info "entered {}({acc})", fn_name!());
|
||||
match acc {
|
||||
ast::Accessor::Local(local) => {
|
||||
/*ast::Accessor::Local(local) => {
|
||||
// `match` is an untypable special form
|
||||
// `match`は型付け不可能な特殊形式
|
||||
let (t, __name__) = if &local.inspect()[..] == "match" {
|
||||
|
@ -279,29 +279,23 @@ impl ASTLowerer {
|
|||
} else {
|
||||
(
|
||||
self.ctx
|
||||
.rec_get_var_t(&local.symbol, Private, &self.ctx.name)?,
|
||||
.rec_get_var_t(&local.symbol, &self.ctx.name)?,
|
||||
self.ctx.get_local_uniq_obj_name(&local.symbol),
|
||||
)
|
||||
};
|
||||
let acc = hir::Accessor::Local(hir::Local::new(local.symbol, __name__, t));
|
||||
Ok(acc)
|
||||
}
|
||||
ast::Accessor::Public(public) => {
|
||||
let (t, __name__) = (
|
||||
self.ctx
|
||||
.rec_get_var_t(&public.symbol, Public, &self.ctx.name)?,
|
||||
self.ctx.get_local_uniq_obj_name(&public.symbol),
|
||||
);
|
||||
let public = hir::Public::new(public.dot, public.symbol, __name__, t);
|
||||
let acc = hir::Accessor::Public(public);
|
||||
}*/
|
||||
ast::Accessor::Ident(ident) => {
|
||||
let ident = self.lower_ident(ident)?;
|
||||
let acc = hir::Accessor::Ident(ident);
|
||||
Ok(acc)
|
||||
}
|
||||
ast::Accessor::Attr(attr) => {
|
||||
let obj = self.lower_expr(*attr.obj)?;
|
||||
let t = self
|
||||
.ctx
|
||||
.rec_get_attr_t(&obj, &attr.name.symbol, &self.ctx.name)?;
|
||||
let acc = hir::Accessor::Attr(hir::Attribute::new(obj, attr.name.symbol, t));
|
||||
let t = self.ctx.rec_get_attr_t(&obj, &attr.ident, &self.ctx.name)?;
|
||||
let ident = hir::Identifier::bare(attr.ident.dot, attr.ident.name);
|
||||
let acc = hir::Accessor::Attr(hir::Attribute::new(obj, ident, t));
|
||||
Ok(acc)
|
||||
}
|
||||
ast::Accessor::TupleAttr(t_attr) => {
|
||||
|
@ -329,6 +323,19 @@ impl ASTLowerer {
|
|||
}
|
||||
}
|
||||
|
||||
fn lower_ident(&self, ident: ast::Identifier) -> LowerResult<hir::Identifier> {
|
||||
let (t, __name__) = if ident.vis().is_private() && &ident.inspect()[..] == "match" {
|
||||
(Type::Failure, None)
|
||||
} else {
|
||||
(
|
||||
self.ctx.rec_get_var_t(&ident, &self.ctx.name)?,
|
||||
self.ctx.get_local_uniq_obj_name(ident.name.token()),
|
||||
)
|
||||
};
|
||||
let ident = hir::Identifier::new(ident.dot, ident.name, __name__, t);
|
||||
Ok(ident)
|
||||
}
|
||||
|
||||
fn lower_bin(&mut self, bin: ast::BinOp) -> LowerResult<hir::BinOp> {
|
||||
log!(info "entered {}({bin})", fn_name!());
|
||||
let mut args = bin.args.into_iter();
|
||||
|
@ -376,7 +383,17 @@ impl ASTLowerer {
|
|||
&hir_args.kw_args,
|
||||
&self.ctx.name,
|
||||
)?;
|
||||
Ok(hir::Call::new(obj, call.method_name, hir_args, sig_t))
|
||||
let method_name = if let Some(method_name) = call.method_name {
|
||||
Some(hir::Identifier::new(
|
||||
method_name.dot,
|
||||
method_name.name,
|
||||
None,
|
||||
Type::Uninited,
|
||||
))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Ok(hir::Call::new(obj, method_name, hir_args, sig_t))
|
||||
}
|
||||
|
||||
fn lower_pack(&mut self, pack: ast::DataPack) -> LowerResult<hir::Call> {
|
||||
|
@ -406,6 +423,7 @@ impl ASTLowerer {
|
|||
&self.ctx.name,
|
||||
)?;
|
||||
let args = hir::Args::new(args, None, vec![], None);
|
||||
let method_name = hir::Identifier::bare(method_name.dot, method_name.name);
|
||||
Ok(hir::Call::new(class, Some(method_name), args, sig_t))
|
||||
}
|
||||
|
||||
|
@ -540,7 +558,8 @@ impl ASTLowerer {
|
|||
}
|
||||
_other => {}
|
||||
}
|
||||
let sig = hir::VarSignature::new(ident.clone(), found_body_t.clone());
|
||||
let ident = hir::Identifier::bare(ident.dot.clone(), ident.name.clone());
|
||||
let sig = hir::VarSignature::new(ident, found_body_t.clone());
|
||||
let body = hir::DefBody::new(body.op, block, body.id);
|
||||
Ok(hir::Def::new(hir::Signature::Var(sig), body))
|
||||
}
|
||||
|
@ -579,7 +598,8 @@ impl ASTLowerer {
|
|||
.as_mut()
|
||||
.unwrap()
|
||||
.assign_subr(&sig, id, found_body_t)?;
|
||||
let sig = hir::SubrSignature::new(sig.ident, sig.params, t);
|
||||
let ident = hir::Identifier::bare(sig.ident.dot, sig.ident.name);
|
||||
let sig = hir::SubrSignature::new(ident, sig.params, t);
|
||||
let body = hir::DefBody::new(body.op, block, body.id);
|
||||
Ok(hir::Def::new(hir::Signature::Subr(sig), body))
|
||||
}
|
||||
|
|
|
@ -186,26 +186,15 @@ impl OwnershipChecker {
|
|||
|
||||
fn check_acc(&mut self, acc: &Accessor, ownership: Ownership) {
|
||||
match acc {
|
||||
Accessor::Local(local) => {
|
||||
self.check_if_dropped(local.inspect(), local.loc());
|
||||
Accessor::Ident(ident) => {
|
||||
self.check_if_dropped(ident.inspect(), ident.loc());
|
||||
if acc.ref_t().is_mut() && ownership.is_owned() {
|
||||
log!(
|
||||
"drop: {} (in {})",
|
||||
local.inspect(),
|
||||
local.ln_begin().unwrap_or(0)
|
||||
ident.inspect(),
|
||||
ident.ln_begin().unwrap_or(0)
|
||||
);
|
||||
self.drop(local.inspect(), acc.loc());
|
||||
}
|
||||
}
|
||||
Accessor::Public(public) => {
|
||||
self.check_if_dropped(public.inspect(), public.loc());
|
||||
if acc.ref_t().is_mut() && ownership.is_owned() {
|
||||
log!(
|
||||
"drop: {} (in {})",
|
||||
public.inspect(),
|
||||
public.ln_begin().unwrap_or(0)
|
||||
);
|
||||
self.drop(public.inspect(), acc.loc());
|
||||
self.drop(ident.inspect(), acc.loc());
|
||||
}
|
||||
}
|
||||
Accessor::Attr(attr) => {
|
||||
|
|
|
@ -226,107 +226,26 @@ impl Args {
|
|||
}
|
||||
}
|
||||
|
||||
/// represents a local (private) variable
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct Local {
|
||||
pub symbol: Token,
|
||||
}
|
||||
|
||||
impl NestedDisplay for Local {
|
||||
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, _level: usize) -> std::fmt::Result {
|
||||
write!(f, "{}", self.symbol.content)
|
||||
}
|
||||
}
|
||||
|
||||
impl_display_from_nested!(Local);
|
||||
impl_locational!(Local, symbol);
|
||||
|
||||
impl Local {
|
||||
pub const fn new(symbol: Token) -> Self {
|
||||
Self { symbol }
|
||||
}
|
||||
|
||||
pub fn static_dummy(name: &'static str) -> Self {
|
||||
Self::new(Token::static_symbol(name))
|
||||
}
|
||||
|
||||
pub fn dummy(name: &str) -> Self {
|
||||
Self::new(Token::symbol(name))
|
||||
}
|
||||
|
||||
pub fn dummy_with_line(name: &str, line: usize) -> Self {
|
||||
Self::new(Token::new(TokenKind::Symbol, Str::rc(name), line, 0))
|
||||
}
|
||||
|
||||
// &strにするとクローンしたいときにアロケーションコストがかかるので&Strのままで
|
||||
pub const fn inspect(&self) -> &Str {
|
||||
&self.symbol.content
|
||||
}
|
||||
|
||||
pub fn is_const(&self) -> bool {
|
||||
self.symbol.inspect().chars().next().unwrap().is_uppercase()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct Public {
|
||||
pub dot: Token,
|
||||
pub symbol: Token,
|
||||
}
|
||||
|
||||
impl NestedDisplay for Public {
|
||||
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, _level: usize) -> std::fmt::Result {
|
||||
write!(f, ".{}", self.symbol.content)
|
||||
}
|
||||
}
|
||||
|
||||
impl_display_from_nested!(Public);
|
||||
impl_locational!(Public, dot, symbol);
|
||||
|
||||
impl Public {
|
||||
pub const fn new(dot: Token, symbol: Token) -> Self {
|
||||
Self { dot, symbol }
|
||||
}
|
||||
|
||||
pub fn dummy(name: &'static str) -> Self {
|
||||
Self::new(
|
||||
Token::from_str(TokenKind::Dot, "."),
|
||||
Token::from_str(TokenKind::Symbol, name),
|
||||
)
|
||||
}
|
||||
|
||||
// &strにするとクローンしたいときにアロケーションコストがかかるので&Strのままで
|
||||
pub const fn inspect(&self) -> &Str {
|
||||
&self.symbol.content
|
||||
}
|
||||
|
||||
pub fn is_const(&self) -> bool {
|
||||
self.symbol.inspect().chars().next().unwrap().is_uppercase()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct Attribute {
|
||||
pub obj: Box<Expr>,
|
||||
pub vis: Token,
|
||||
pub name: Local,
|
||||
pub ident: Identifier,
|
||||
}
|
||||
|
||||
impl NestedDisplay for Attribute {
|
||||
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, _level: usize) -> std::fmt::Result {
|
||||
write!(f, "({}){}{}", self.obj, self.vis.inspect(), self.name)
|
||||
write!(f, "({}){}", self.obj, self.ident)
|
||||
}
|
||||
}
|
||||
|
||||
impl_display_from_nested!(Attribute);
|
||||
impl_locational!(Attribute, obj, name);
|
||||
impl_locational!(Attribute, obj, ident);
|
||||
|
||||
impl Attribute {
|
||||
pub fn new(obj: Expr, vis: Token, name: Local) -> Self {
|
||||
pub fn new(obj: Expr, ident: Identifier) -> Self {
|
||||
Self {
|
||||
obj: Box::new(obj),
|
||||
vis,
|
||||
name,
|
||||
ident,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -382,28 +301,27 @@ impl Subscript {
|
|||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum Accessor {
|
||||
Local(Local),
|
||||
Public(Public),
|
||||
Ident(Identifier),
|
||||
Attr(Attribute),
|
||||
TupleAttr(TupleAttribute),
|
||||
Subscr(Subscript),
|
||||
}
|
||||
|
||||
impl_nested_display_for_enum!(Accessor; Local, Public, Attr, TupleAttr, Subscr);
|
||||
impl_nested_display_for_enum!(Accessor; Ident, Attr, TupleAttr, Subscr);
|
||||
impl_display_from_nested!(Accessor);
|
||||
impl_locational_for_enum!(Accessor; Local, Public, Attr, TupleAttr, Subscr);
|
||||
impl_locational_for_enum!(Accessor; Ident Attr, TupleAttr, Subscr);
|
||||
|
||||
impl Accessor {
|
||||
pub const fn local(symbol: Token) -> Self {
|
||||
Self::Local(Local::new(symbol))
|
||||
Self::Ident(Identifier::new(None, VarName::new(symbol)))
|
||||
}
|
||||
|
||||
pub const fn public(dot: Token, symbol: Token) -> Self {
|
||||
Self::Public(Public::new(dot, symbol))
|
||||
Self::Ident(Identifier::new(Some(dot), VarName::new(symbol)))
|
||||
}
|
||||
|
||||
pub fn attr(obj: Expr, vis: Token, name: Local) -> Self {
|
||||
Self::Attr(Attribute::new(obj, vis, name))
|
||||
pub fn attr(obj: Expr, ident: Identifier) -> Self {
|
||||
Self::Attr(Attribute::new(obj, ident))
|
||||
}
|
||||
|
||||
pub fn tuple_attr(obj: Expr, index: Literal) -> Self {
|
||||
|
@ -416,19 +334,17 @@ impl Accessor {
|
|||
|
||||
pub const fn name(&self) -> Option<&Str> {
|
||||
match self {
|
||||
Self::Local(local) => Some(local.inspect()),
|
||||
Self::Public(local) => Some(local.inspect()),
|
||||
Self::Ident(ident) => Some(ident.inspect()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_const(&self) -> bool {
|
||||
match self {
|
||||
Self::Local(local) => local.is_const(),
|
||||
Self::Public(public) => public.is_const(),
|
||||
Self::Ident(ident) => ident.is_const(),
|
||||
Self::Subscr(subscr) => subscr.obj.is_const_acc(),
|
||||
Self::TupleAttr(attr) => attr.obj.is_const_acc(),
|
||||
Self::Attr(attr) => attr.obj.is_const_acc() && attr.name.is_const(),
|
||||
Self::Attr(attr) => attr.obj.is_const_acc() && attr.ident.is_const(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -494,7 +410,7 @@ pub struct ArrayComprehension {
|
|||
pub l_sqbr: Token,
|
||||
pub r_sqbr: Token,
|
||||
pub elem: Box<Expr>,
|
||||
pub generators: Vec<(Local, Expr)>,
|
||||
pub generators: Vec<(Identifier, Expr)>,
|
||||
pub guards: Vec<Expr>,
|
||||
}
|
||||
|
||||
|
@ -522,7 +438,7 @@ impl ArrayComprehension {
|
|||
l_sqbr: Token,
|
||||
r_sqbr: Token,
|
||||
elem: Expr,
|
||||
generators: Vec<(Local, Expr)>,
|
||||
generators: Vec<(Identifier, Expr)>,
|
||||
guards: Vec<Expr>,
|
||||
) -> Self {
|
||||
Self {
|
||||
|
@ -1773,8 +1689,8 @@ pub struct Identifier {
|
|||
pub name: VarName,
|
||||
}
|
||||
|
||||
impl fmt::Display for Identifier {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
impl NestedDisplay for Identifier {
|
||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
|
||||
match &self.dot {
|
||||
Some(_dot) => write!(f, ".{}", self.name),
|
||||
None => write!(f, "::{}", self.name),
|
||||
|
@ -1782,6 +1698,8 @@ impl fmt::Display for Identifier {
|
|||
}
|
||||
}
|
||||
|
||||
impl_display_from_nested!(Identifier);
|
||||
|
||||
impl Locational for Identifier {
|
||||
fn loc(&self) -> Location {
|
||||
if let Some(dot) = &self.dot {
|
||||
|
|
|
@ -12,7 +12,7 @@ use erg_common::{enum_unwrap, get_hash, set};
|
|||
|
||||
use crate::ast::{
|
||||
Accessor, Args, Array, BinOp, Block, Call, DataPack, Def, DefBody, DefId, Expr, Identifier,
|
||||
KwArg, Lambda, LambdaSignature, Literal, Local, Methods, Module, NormalArray, NormalRecord,
|
||||
KwArg, Lambda, LambdaSignature, Literal, Methods, Module, NormalArray, NormalRecord,
|
||||
NormalTuple, ParamPattern, ParamSignature, Params, PosArg, Record, RecordAttrs,
|
||||
ShortenedRecord, Signature, SubrSignature, Tuple, TypeAscription, TypeBoundSpecs, TypeSpec,
|
||||
UnaryOp, VarName, VarPattern, VarRecordAttr, VarSignature,
|
||||
|
@ -79,7 +79,7 @@ impl Desugarer {
|
|||
} else {
|
||||
self.gen_match_call(previous, def)
|
||||
};
|
||||
let param_name = enum_unwrap!(&call.args.pos_args().iter().next().unwrap().expr, Expr::Accessor:(Accessor::Local:(_))).inspect();
|
||||
let param_name = enum_unwrap!(&call.args.pos_args().iter().next().unwrap().expr, Expr::Accessor:(Accessor::Ident:(_))).inspect();
|
||||
// FIXME: multiple params
|
||||
let param = VarName::new(Token::new(
|
||||
TokenKind::Symbol,
|
||||
|
@ -279,12 +279,12 @@ impl Desugarer {
|
|||
Accessor::subscr(obj, Expr::Lit(Literal::nat(n, sig.ln_begin().unwrap())))
|
||||
}
|
||||
BufIndex::Record(attr) => {
|
||||
let ident = Identifier::new(
|
||||
Some(Token::from_str(TokenKind::Dot, ".")),
|
||||
VarName::new(Token::symbol_with_line(attr, sig.ln_begin().unwrap())),
|
||||
);
|
||||
// TODO: visibility
|
||||
Accessor::attr(
|
||||
obj,
|
||||
Token::from_str(TokenKind::Dot, "."),
|
||||
Local::dummy_with_line(attr, sig.ln_begin().unwrap()),
|
||||
)
|
||||
Accessor::attr(obj, ident)
|
||||
}
|
||||
};
|
||||
let id = DefId(get_hash(&(&acc, buf_name)));
|
||||
|
|
|
@ -56,7 +56,7 @@ pub enum ArrayInner {
|
|||
WithLength(PosArg, Expr),
|
||||
Comprehension {
|
||||
elem: PosArg,
|
||||
generators: Vec<(Local, Expr)>,
|
||||
generators: Vec<(Identifier, Expr)>,
|
||||
guards: Vec<Expr>,
|
||||
},
|
||||
}
|
||||
|
@ -408,8 +408,8 @@ impl Parser {
|
|||
let token = self.lpop();
|
||||
match token.kind {
|
||||
Symbol => {
|
||||
let attr = Local::new(token);
|
||||
acc = Accessor::attr(Expr::Accessor(acc), vis, attr);
|
||||
let ident = Identifier::new(Some(vis), VarName::new(token));
|
||||
acc = Accessor::attr(Expr::Accessor(acc), ident);
|
||||
}
|
||||
NatLit => {
|
||||
let attr = Literal::from(token);
|
||||
|
@ -434,8 +434,8 @@ impl Parser {
|
|||
let token = self.lpop();
|
||||
match token.kind {
|
||||
Symbol => {
|
||||
let attr = Local::new(token);
|
||||
acc = Accessor::attr(Expr::Accessor(acc), vis, attr);
|
||||
let ident = Identifier::new(None, VarName::new(token));
|
||||
acc = Accessor::attr(Expr::Accessor(acc), ident);
|
||||
}
|
||||
// DataPack
|
||||
LBrace => {
|
||||
|
@ -492,8 +492,8 @@ impl Parser {
|
|||
fn validate_const_expr(&mut self, expr: Expr) -> ParseResult<ConstExpr> {
|
||||
match expr {
|
||||
Expr::Lit(l) => Ok(ConstExpr::Lit(l)),
|
||||
Expr::Accessor(Accessor::Local(local)) => {
|
||||
let local = ConstLocal::new(local.symbol);
|
||||
Expr::Accessor(Accessor::Ident(local)) => {
|
||||
let local = ConstLocal::new(local.name.into_token());
|
||||
Ok(ConstExpr::Accessor(ConstAccessor::Local(local)))
|
||||
}
|
||||
// TODO: App, Array, Record, BinOp, UnaryOp,
|
||||
|
@ -744,8 +744,8 @@ impl Parser {
|
|||
// TODO: type specification
|
||||
debug_power_assert!(self.cur_is(Walrus));
|
||||
self.skip();
|
||||
let kw = if let Accessor::Local(n) = acc {
|
||||
n.symbol
|
||||
let kw = if let Accessor::Ident(n) = acc {
|
||||
n.name.into_token()
|
||||
} else {
|
||||
self.next_expr();
|
||||
self.level -= 1;
|
||||
|
@ -789,8 +789,8 @@ impl Parser {
|
|||
let acc = self.try_reduce_acc().map_err(|_| self.stack_dec())?;
|
||||
debug_power_assert!(self.cur_is(Walrus));
|
||||
self.skip();
|
||||
let keyword = if let Accessor::Local(n) = acc {
|
||||
n.symbol
|
||||
let keyword = if let Accessor::Ident(n) = acc {
|
||||
n.name.into_token()
|
||||
} else {
|
||||
self.next_expr();
|
||||
self.level -= 1;
|
||||
|
@ -984,7 +984,8 @@ impl Parser {
|
|||
let call = Call::new(obj, Some(ident), args);
|
||||
stack.push(ExprOrOp::Expr(Expr::Call(call)));
|
||||
} else {
|
||||
let acc = Accessor::attr(obj, vis, Local::new(symbol));
|
||||
let ident = Identifier::new(None, VarName::new(symbol));
|
||||
let acc = Accessor::attr(obj, ident);
|
||||
stack.push(ExprOrOp::Expr(Expr::Accessor(acc)));
|
||||
}
|
||||
}
|
||||
|
@ -1043,7 +1044,8 @@ impl Parser {
|
|||
let call = Call::new(obj, Some(ident), args);
|
||||
stack.push(ExprOrOp::Expr(Expr::Call(call)));
|
||||
} else {
|
||||
let acc = Accessor::attr(obj, vis, Local::new(symbol));
|
||||
let ident = Identifier::new(Some(vis), VarName::new(symbol));
|
||||
let acc = Accessor::attr(obj, ident);
|
||||
stack.push(ExprOrOp::Expr(Expr::Accessor(acc)));
|
||||
}
|
||||
}
|
||||
|
@ -1198,7 +1200,8 @@ impl Parser {
|
|||
let call = Call::new(obj, Some(ident), args);
|
||||
stack.push(ExprOrOp::Expr(Expr::Call(call)));
|
||||
} else {
|
||||
let acc = Accessor::attr(obj, vis, Local::new(symbol));
|
||||
let ident = Identifier::new(Some(vis), VarName::new(symbol));
|
||||
let acc = Accessor::attr(obj, ident);
|
||||
stack.push(ExprOrOp::Expr(Expr::Accessor(acc)));
|
||||
}
|
||||
}
|
||||
|
@ -1385,23 +1388,8 @@ impl Parser {
|
|||
if let Some(res) = self.opt_reduce_args() {
|
||||
let args = res.map_err(|_| self.stack_dec())?;
|
||||
let (obj, method_name) = match acc {
|
||||
Accessor::Attr(attr) => {
|
||||
if attr.vis.is(Dot) {
|
||||
(
|
||||
*attr.obj,
|
||||
Some(Identifier::new(
|
||||
Some(attr.vis),
|
||||
VarName::new(attr.name.symbol),
|
||||
)),
|
||||
)
|
||||
} else {
|
||||
(
|
||||
*attr.obj,
|
||||
Some(Identifier::new(None, VarName::new(attr.name.symbol))),
|
||||
)
|
||||
}
|
||||
}
|
||||
Accessor::Local(local) => (Expr::Accessor(Accessor::Local(local)), None),
|
||||
Accessor::Attr(attr) => (*attr.obj, Some(attr.ident)),
|
||||
Accessor::Ident(ident) => (Expr::Accessor(Accessor::Ident(ident)), None),
|
||||
_ => todo!(),
|
||||
};
|
||||
let call = Call::new(obj, method_name, args);
|
||||
|
@ -1547,10 +1535,7 @@ impl Parser {
|
|||
) -> ParseResult<ShortenedRecord> {
|
||||
debug_call_info!(self);
|
||||
let first = match first {
|
||||
Accessor::Local(local) => Identifier::new(None, VarName::new(local.symbol)),
|
||||
Accessor::Public(public) => {
|
||||
Identifier::new(Some(public.dot), VarName::new(public.symbol))
|
||||
}
|
||||
Accessor::Ident(ident) => ident,
|
||||
other => todo!("{other}"), // syntax error
|
||||
};
|
||||
let mut idents = vec![first];
|
||||
|
@ -1577,10 +1562,7 @@ impl Parser {
|
|||
Some(_) => {
|
||||
let acc = self.try_reduce_acc().map_err(|_| self.stack_dec())?;
|
||||
let acc = match acc {
|
||||
Accessor::Local(local) => Identifier::new(None, VarName::new(local.symbol)),
|
||||
Accessor::Public(public) => {
|
||||
Identifier::new(Some(public.dot), VarName::new(public.symbol))
|
||||
}
|
||||
Accessor::Ident(ident) => ident,
|
||||
other => todo!("{other}"), // syntax error
|
||||
};
|
||||
idents.push(acc);
|
||||
|
@ -1716,16 +1698,8 @@ impl Parser {
|
|||
fn convert_accessor_to_var_sig(&mut self, _accessor: Accessor) -> ParseResult<VarSignature> {
|
||||
debug_call_info!(self);
|
||||
match _accessor {
|
||||
Accessor::Local(local) => {
|
||||
let pat = VarPattern::Ident(Identifier::new(None, VarName::new(local.symbol)));
|
||||
self.level -= 1;
|
||||
Ok(VarSignature::new(pat, None))
|
||||
}
|
||||
Accessor::Public(public) => {
|
||||
let pat = VarPattern::Ident(Identifier::new(
|
||||
Some(public.dot),
|
||||
VarName::new(public.symbol),
|
||||
));
|
||||
Accessor::Ident(ident) => {
|
||||
let pat = VarPattern::Ident(ident);
|
||||
self.level -= 1;
|
||||
Ok(VarSignature::new(pat, None))
|
||||
}
|
||||
|
@ -1866,10 +1840,7 @@ impl Parser {
|
|||
fn convert_accessor_to_ident(&mut self, _accessor: Accessor) -> ParseResult<Identifier> {
|
||||
debug_call_info!(self);
|
||||
let ident = match _accessor {
|
||||
Accessor::Local(local) => Identifier::new(None, VarName::new(local.symbol)),
|
||||
Accessor::Public(public) => {
|
||||
Identifier::new(Some(public.dot), VarName::new(public.symbol))
|
||||
}
|
||||
Accessor::Ident(ident) => ident,
|
||||
other => {
|
||||
self.level -= 1;
|
||||
let err = ParseError::simple_syntax_error(line!() as usize, other.loc());
|
||||
|
@ -1922,15 +1893,15 @@ impl Parser {
|
|||
) -> ParseResult<ParamSignature> {
|
||||
debug_call_info!(self);
|
||||
match expr {
|
||||
Expr::Accessor(Accessor::Local(local)) => {
|
||||
if &local.inspect()[..] == "self" && !allow_self {
|
||||
Expr::Accessor(Accessor::Ident(ident)) => {
|
||||
if &ident.inspect()[..] == "self" && !allow_self {
|
||||
self.level -= 1;
|
||||
let err = ParseError::simple_syntax_error(line!() as usize, local.loc());
|
||||
let err = ParseError::simple_syntax_error(line!() as usize, ident.loc());
|
||||
self.errs.push(err);
|
||||
return Err(());
|
||||
}
|
||||
let name = VarName::new(local.symbol);
|
||||
let pat = ParamPattern::VarName(name);
|
||||
// FIXME deny: public
|
||||
let pat = ParamPattern::VarName(ident.name);
|
||||
let param = ParamSignature::new(pat, None, None);
|
||||
self.level -= 1;
|
||||
Ok(param)
|
||||
|
@ -1978,18 +1949,18 @@ impl Parser {
|
|||
Expr::UnaryOp(unary) => match unary.op.kind {
|
||||
TokenKind::RefOp => {
|
||||
let var = unary.args.into_iter().next().unwrap();
|
||||
let var = option_enum_unwrap!(*var, Expr::Accessor:(Accessor::Local:(_)))
|
||||
let var = option_enum_unwrap!(*var, Expr::Accessor:(Accessor::Ident:(_)))
|
||||
.unwrap_or_else(|| todo!());
|
||||
let pat = ParamPattern::Ref(VarName::new(var.symbol));
|
||||
let pat = ParamPattern::Ref(var.name);
|
||||
let param = ParamSignature::new(pat, None, None);
|
||||
self.level -= 1;
|
||||
Ok(param)
|
||||
}
|
||||
TokenKind::RefMutOp => {
|
||||
let var = unary.args.into_iter().next().unwrap();
|
||||
let var = option_enum_unwrap!(*var, Expr::Accessor:(Accessor::Local:(_)))
|
||||
let var = option_enum_unwrap!(*var, Expr::Accessor:(Accessor::Ident:(_)))
|
||||
.unwrap_or_else(|| todo!());
|
||||
let pat = ParamPattern::RefMut(VarName::new(var.symbol));
|
||||
let pat = ParamPattern::RefMut(var.name);
|
||||
let param = ParamSignature::new(pat, None, None);
|
||||
self.level -= 1;
|
||||
Ok(param)
|
||||
|
@ -2201,10 +2172,9 @@ impl Parser {
|
|||
) -> ParseResult<PreDeclTypeSpec> {
|
||||
debug_call_info!(self);
|
||||
let t_spec = match accessor {
|
||||
Accessor::Local(local) => PreDeclTypeSpec::Simple(SimpleTypeSpec::new(
|
||||
VarName::new(local.symbol),
|
||||
ConstArgs::empty(),
|
||||
)),
|
||||
Accessor::Ident(ident) => {
|
||||
PreDeclTypeSpec::Simple(SimpleTypeSpec::new(ident.name, ConstArgs::empty()))
|
||||
}
|
||||
other => todo!("{other}"),
|
||||
};
|
||||
self.level -= 1;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue