mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-29 12:24:45 +00:00
Impl: variable visibility
This commit is contained in:
parent
a6f9e89ffc
commit
20aaf6a53e
14 changed files with 620 additions and 309 deletions
|
@ -18,6 +18,45 @@ use crate::ty::{fresh_varname, ConstSubr, Predicate, TyParam, Type};
|
|||
use crate::{fmt_iter, impl_display_from_debug, switch_lang};
|
||||
use crate::{RcArray, Str};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
#[repr(u8)]
|
||||
pub enum Visibility {
|
||||
Private,
|
||||
Public,
|
||||
}
|
||||
|
||||
impl Visibility {
|
||||
pub const fn is_public(&self) -> bool {
|
||||
matches!(self, Self::Public)
|
||||
}
|
||||
pub const fn is_private(&self) -> bool {
|
||||
matches!(self, Self::Private)
|
||||
}
|
||||
}
|
||||
|
||||
/// same structure as `Identifier`, but only for Record fields.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct Field {
|
||||
vis: Visibility,
|
||||
symbol: Str,
|
||||
}
|
||||
|
||||
impl fmt::Display for Field {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
if self.vis == Visibility::Public {
|
||||
write!(f, ".{}", self.symbol)
|
||||
} else {
|
||||
write!(f, "{}", self.symbol)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Field {
|
||||
pub const fn new(vis: Visibility, symbol: Str) -> Self {
|
||||
Field { vis, symbol }
|
||||
}
|
||||
}
|
||||
|
||||
/// 値オブジェクト
|
||||
/// コンパイル時評価ができ、シリアライズも可能
|
||||
#[derive(Clone, PartialEq, Default)]
|
||||
|
@ -29,7 +68,7 @@ pub enum ValueObj {
|
|||
Bool(bool),
|
||||
Array(Rc<[ValueObj]>),
|
||||
Dict(Rc<[(ValueObj, ValueObj)]>),
|
||||
Record(Dict<Str, ValueObj>),
|
||||
Record(Dict<Field, ValueObj>),
|
||||
Code(Box<CodeObj>),
|
||||
Subr(ConstSubr),
|
||||
Type(Box<Type>),
|
||||
|
|
|
@ -19,7 +19,7 @@ use erg_common::{
|
|||
};
|
||||
use Opcode::*;
|
||||
|
||||
use erg_parser::ast::{ParamPattern, Params, VarPattern};
|
||||
use erg_parser::ast::{Identifier, ParamPattern, Params, VarName, VarPattern};
|
||||
use erg_parser::token::{Token, TokenCategory, TokenKind};
|
||||
|
||||
use crate::compile::{AccessKind, Name, StoreLoadKind};
|
||||
|
@ -29,12 +29,162 @@ use crate::hir::{
|
|||
};
|
||||
use AccessKind::*;
|
||||
|
||||
fn obj_name(obj: &Expr) -> Option<String> {
|
||||
match obj {
|
||||
Expr::Accessor(Accessor::Local(n)) => Some(n.inspect().to_string()),
|
||||
Expr::Accessor(Accessor::Attr(a)) => Some(obj_name(&a.obj)? + "." + a.name.inspect()),
|
||||
Expr::Accessor(Accessor::SelfDot(n)) => Some(format!(".{}", n.inspect())),
|
||||
_ => None,
|
||||
fn is_python_global(name: &str) -> bool {
|
||||
match name {
|
||||
"ArithmeticError"
|
||||
| "AssertionError"
|
||||
| "AttributeError"
|
||||
| "BaseException"
|
||||
| "BlockingIOError"
|
||||
| "BrokenPipeError"
|
||||
| "BufferError"
|
||||
| "BytesWarning"
|
||||
| "ChildProcessError"
|
||||
| "ConnectionAbortedError"
|
||||
| "ConnectionError"
|
||||
| "ConnectionRefusedError"
|
||||
| "ConnectionResetError"
|
||||
| "DeprecationWarning"
|
||||
| "EOFError"
|
||||
| "Ellipsis"
|
||||
| "EncodingWarning"
|
||||
| "EnvironmentError"
|
||||
| "Exception"
|
||||
| "False"
|
||||
| "FileExistsError"
|
||||
| "FileNotFoundError"
|
||||
| "FloatingPointError"
|
||||
| "FutureWarning"
|
||||
| "GeneratorExit"
|
||||
| "IOError"
|
||||
| "ImportError"
|
||||
| "ImportWarning"
|
||||
| "IndentationError"
|
||||
| "IndexError"
|
||||
| "InterruptedError"
|
||||
| "IsADirectoryError"
|
||||
| "KeyError"
|
||||
| "KeyboardInterrupt"
|
||||
| "LookupError"
|
||||
| "MemoryError"
|
||||
| "ModuleNotFoundError"
|
||||
| "NameError"
|
||||
| "None"
|
||||
| "NotADirectoryError"
|
||||
| "NotImplemented"
|
||||
| "NotImplementedError"
|
||||
| "OSError"
|
||||
| "OverflowError"
|
||||
| "PendingDeprecationWarning"
|
||||
| "PermissionError"
|
||||
| "ProcessLookupError"
|
||||
| "RecursionError"
|
||||
| "ReferenceError"
|
||||
| "ResourceWarning"
|
||||
| "RuntimeError"
|
||||
| "RuntimeWarning"
|
||||
| "StopAsyncIteration"
|
||||
| "StopIteration"
|
||||
| "SyntaxError"
|
||||
| "SyntaxWarning"
|
||||
| "SystemError"
|
||||
| "SystemExit"
|
||||
| "TabError"
|
||||
| "TimeoutError"
|
||||
| "True"
|
||||
| "TypeError"
|
||||
| "UnboundLocalError"
|
||||
| "UnicodeDecodeError"
|
||||
| "UnicodeEncodeError"
|
||||
| "UnicodeError"
|
||||
| "UnicodeTranslateError"
|
||||
| "UnicodeWarning"
|
||||
| "UserWarning"
|
||||
| "ValueError"
|
||||
| "Warning"
|
||||
| "WindowsError"
|
||||
| "ZeroDivisionError"
|
||||
| "__build__class__"
|
||||
| "__debug__"
|
||||
| "__doc__"
|
||||
| "__import__"
|
||||
| "__loader__"
|
||||
| "__name__"
|
||||
| "__package__"
|
||||
| "__spec__"
|
||||
| "__annotations__"
|
||||
| "__builtins__"
|
||||
| "abs"
|
||||
| "aiter"
|
||||
| "all"
|
||||
| "any"
|
||||
| "anext"
|
||||
| "ascii"
|
||||
| "bin"
|
||||
| "bool"
|
||||
| "breakpoint"
|
||||
| "bytearray"
|
||||
| "bytes"
|
||||
| "callable"
|
||||
| "chr"
|
||||
| "classmethod"
|
||||
| "compile"
|
||||
| "complex"
|
||||
| "delattr"
|
||||
| "dict"
|
||||
| "dir"
|
||||
| "divmod"
|
||||
| "enumerate"
|
||||
| "eval"
|
||||
| "exec"
|
||||
| "filter"
|
||||
| "float"
|
||||
| "format"
|
||||
| "frozenset"
|
||||
| "getattr"
|
||||
| "globals"
|
||||
| "hasattr"
|
||||
| "hash"
|
||||
| "help"
|
||||
| "hex"
|
||||
| "id"
|
||||
| "input"
|
||||
| "int"
|
||||
| "isinstance"
|
||||
| "issubclass"
|
||||
| "iter"
|
||||
| "len"
|
||||
| "list"
|
||||
| "locals"
|
||||
| "map"
|
||||
| "max"
|
||||
| "memoryview"
|
||||
| "min"
|
||||
| "next"
|
||||
| "object"
|
||||
| "oct"
|
||||
| "open"
|
||||
| "ord"
|
||||
| "pow"
|
||||
| "print"
|
||||
| "property"
|
||||
| "range"
|
||||
| "repr"
|
||||
| "reversed"
|
||||
| "round"
|
||||
| "set"
|
||||
| "setattr"
|
||||
| "slice"
|
||||
| "sorted"
|
||||
| "staticmethod"
|
||||
| "str"
|
||||
| "sum"
|
||||
| "super"
|
||||
| "tuple"
|
||||
| "type"
|
||||
| "vars"
|
||||
| "zip" => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,11 +226,16 @@ fn convert_to_python_name(name: Str) -> Str {
|
|||
}
|
||||
}
|
||||
|
||||
fn escape_name(name: Str) -> Str {
|
||||
let mut name = convert_to_python_name(name).to_string();
|
||||
name = name.replace('!', "__erg_proc__");
|
||||
name = name.replace('$', "__erg_shared__");
|
||||
fn escape_name(ident: Identifier) -> Str {
|
||||
let vis = ident.vis();
|
||||
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) {
|
||||
Str::rc(&name)
|
||||
} else {
|
||||
Str::from("__".to_string() + &name)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -324,9 +479,9 @@ impl CodeGenerator {
|
|||
Some(StoreLoadKind::Global)
|
||||
}
|
||||
|
||||
fn register_name(&mut self, name: Str) -> Name {
|
||||
fn register_name(&mut self, ident: Identifier) -> Name {
|
||||
let current_is_toplevel = self.cur_block() == self.toplevel_block();
|
||||
let name = escape_name(name);
|
||||
let name = escape_name(ident);
|
||||
match self.rec_search(&name) {
|
||||
Some(st @ (StoreLoadKind::Local | StoreLoadKind::Global)) => {
|
||||
let st = if current_is_toplevel {
|
||||
|
@ -371,10 +526,10 @@ impl CodeGenerator {
|
|||
Name::local(self.cur_block_codeobj().names.len() - 1)
|
||||
}
|
||||
|
||||
fn emit_load_name_instr(&mut self, name: Str) -> CompileResult<()> {
|
||||
fn emit_load_name_instr(&mut self, ident: Identifier) -> CompileResult<()> {
|
||||
let name = self
|
||||
.local_search(&name, Name)
|
||||
.unwrap_or_else(|| self.register_name(name));
|
||||
.local_search(ident.inspect(), Name)
|
||||
.unwrap_or_else(|| self.register_name(ident));
|
||||
let instr = match name.kind {
|
||||
StoreLoadKind::Fast | StoreLoadKind::FastConst => Opcode::LOAD_FAST,
|
||||
StoreLoadKind::Global | StoreLoadKind::GlobalConst => Opcode::LOAD_GLOBAL,
|
||||
|
@ -427,10 +582,10 @@ impl CodeGenerator {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn emit_store_instr(&mut self, name: Str, acc_kind: AccessKind) {
|
||||
fn emit_store_instr(&mut self, ident: Identifier, acc_kind: AccessKind) {
|
||||
let name = self
|
||||
.local_search(&name, acc_kind)
|
||||
.unwrap_or_else(|| self.register_name(name));
|
||||
.local_search(ident.inspect(), acc_kind)
|
||||
.unwrap_or_else(|| self.register_name(ident));
|
||||
let instr = match name.kind {
|
||||
StoreLoadKind::Fast => Opcode::STORE_FAST,
|
||||
StoreLoadKind::FastConst => Opcode::ERG_STORE_FAST_IMMUT,
|
||||
|
@ -492,11 +647,11 @@ impl CodeGenerator {
|
|||
.collect()
|
||||
}
|
||||
|
||||
fn emit_var_pat(&mut self, pat: &VarPattern, op: &Token) {
|
||||
fn emit_var_pat(&mut self, pat: VarPattern, op: &Token) {
|
||||
match pat {
|
||||
VarPattern::Local(var) => {
|
||||
VarPattern::Ident(ident) => {
|
||||
if op.category_is(TokenCategory::DefOp) {
|
||||
self.emit_store_instr(var.inspect().clone(), Name);
|
||||
self.emit_store_instr(ident, Name);
|
||||
} else {
|
||||
todo!()
|
||||
}
|
||||
|
@ -507,8 +662,8 @@ impl CodeGenerator {
|
|||
self.write_instr(UNPACK_SEQUENCE);
|
||||
self.write_arg(a.len() as u8);
|
||||
self.stack_inc_n(a.len() - 1);
|
||||
for sig in a.iter() {
|
||||
self.emit_var_pat(&sig.pat, op);
|
||||
for sig in a.into_iter() {
|
||||
self.emit_var_pat(sig.pat, op);
|
||||
}
|
||||
} else {
|
||||
switch_unreachable!()
|
||||
|
@ -522,17 +677,20 @@ impl CodeGenerator {
|
|||
self.write_instr(Opcode::LOAD_BUILD_CLASS);
|
||||
self.write_arg(0);
|
||||
self.stack_inc();
|
||||
let name = sig.inspect().unwrap();
|
||||
let code = self.codegen_typedef_block(name.clone(), body.block);
|
||||
let ident = match sig.pat {
|
||||
VarPattern::Ident(ident) => ident,
|
||||
_ => todo!(),
|
||||
};
|
||||
let code = self.codegen_typedef_block(ident.inspect().clone(), body.block);
|
||||
self.emit_load_const(code);
|
||||
self.emit_load_const(name.clone());
|
||||
self.emit_load_const(ident.inspect().clone());
|
||||
self.write_instr(Opcode::MAKE_FUNCTION);
|
||||
self.write_arg(0);
|
||||
self.emit_load_const(name.clone());
|
||||
self.emit_load_const(ident.inspect().clone());
|
||||
self.write_instr(Opcode::CALL_FUNCTION);
|
||||
self.write_arg(2);
|
||||
self.stack_dec_n((1 + 2) - 1);
|
||||
self.emit_store_instr(name.clone(), Name);
|
||||
self.emit_store_instr(ident, Name);
|
||||
}
|
||||
|
||||
fn emit_var_def(&mut self, sig: VarSignature, mut body: DefBody) {
|
||||
|
@ -544,11 +702,11 @@ impl CodeGenerator {
|
|||
} else {
|
||||
self.codegen_frameless_block(body.block, vec![]);
|
||||
}
|
||||
self.emit_var_pat(&sig.pat, &body.op);
|
||||
self.emit_var_pat(sig.pat, &body.op);
|
||||
}
|
||||
|
||||
fn emit_subr_def(&mut self, sig: SubrSignature, body: DefBody) {
|
||||
let name = sig.name.inspect().clone();
|
||||
let name = sig.ident.inspect().clone();
|
||||
let mut opcode_flag = 0u8;
|
||||
let params = self.gen_param_names(&sig.params);
|
||||
let code = self.codegen_block(body.block, Some(name.clone()), params);
|
||||
|
@ -568,7 +726,7 @@ impl CodeGenerator {
|
|||
self.write_arg(opcode_flag);
|
||||
// stack_dec: <code obj> + <name> -> <function>
|
||||
self.stack_dec();
|
||||
self.emit_store_instr(name, Name);
|
||||
self.emit_store_instr(sig.ident, Name);
|
||||
}
|
||||
|
||||
fn emit_discard_instr(&mut self, mut args: Args) -> CompileResult<()> {
|
||||
|
@ -687,7 +845,8 @@ impl CodeGenerator {
|
|||
let mut pop_jump_points = vec![];
|
||||
match pat {
|
||||
ParamPattern::VarName(name) => {
|
||||
self.emit_store_instr(name.inspect().clone(), AccessKind::Name);
|
||||
let ident = Identifier::new(None, name);
|
||||
self.emit_store_instr(ident, AccessKind::Name);
|
||||
}
|
||||
ParamPattern::Lit(lit) => {
|
||||
self.emit_load_const(ValueObj::from(&lit));
|
||||
|
@ -735,15 +894,16 @@ impl CodeGenerator {
|
|||
Ok(pop_jump_points)
|
||||
}
|
||||
|
||||
fn emit_call_name(&mut self, name: Str, mut args: Args) -> CompileResult<()> {
|
||||
match &name[..] {
|
||||
fn emit_call_special(&mut self, name: VarName, mut args: Args) -> CompileResult<()> {
|
||||
match &name.inspect()[..] {
|
||||
"assert" => self.emit_assert_instr(args),
|
||||
"discard" => self.emit_discard_instr(args),
|
||||
"for" | "for!" => self.emit_for_instr(args),
|
||||
"if" | "if!" => self.emit_if_instr(args),
|
||||
"match" | "match!" => self.emit_match_instr(args, true),
|
||||
_ => {
|
||||
self.emit_load_name_instr(name).unwrap_or_else(|e| {
|
||||
let ident = Identifier::new(None, name);
|
||||
self.emit_load_name_instr(ident).unwrap_or_else(|e| {
|
||||
self.errs.push(e);
|
||||
});
|
||||
let argc = args.len();
|
||||
|
@ -772,40 +932,20 @@ impl CodeGenerator {
|
|||
}
|
||||
}
|
||||
|
||||
fn emit_call_method(&mut self, obj: Expr, name: Str, mut args: Args, is_static: bool) {
|
||||
if is_static {
|
||||
self.emit_load_name_instr(name).unwrap_or_else(|err| {
|
||||
self.errs.push(err);
|
||||
});
|
||||
let argc = args.len();
|
||||
let mut kws = Vec::with_capacity(args.kw_len());
|
||||
while let Some(arg) = args.try_remove_pos(0) {
|
||||
self.codegen_expr(arg.expr);
|
||||
}
|
||||
while let Some(arg) = args.try_remove_kw(0) {
|
||||
kws.push(ValueObj::Str(arg.keyword.content.clone()));
|
||||
self.codegen_expr(arg.expr);
|
||||
}
|
||||
let kwsc = if !kws.is_empty() {
|
||||
let kws_tuple = ValueObj::from(kws);
|
||||
self.emit_load_const(kws_tuple);
|
||||
self.write_instr(CALL_FUNCTION_KW);
|
||||
1
|
||||
} else {
|
||||
self.write_instr(CALL_FUNCTION);
|
||||
0
|
||||
};
|
||||
self.write_arg(1 + argc as u8);
|
||||
// (1 (method as subroutine) + 1 (obj) + argc + kwsc) input objects -> 1 return object
|
||||
self.stack_dec_n((1 + 1 + argc + kwsc) - 1);
|
||||
} else {
|
||||
let class = Str::rc(obj.ref_t().name());
|
||||
fn emit_call(&mut self, obj: Expr, method_name: Option<Token>, mut args: Args) {
|
||||
let class = Str::rc(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[..]), name)
|
||||
if let Some(method_name) = method_name {
|
||||
self.emit_load_method_instr(
|
||||
&class,
|
||||
uniq_obj_name.as_ref().map(|s| &s[..]),
|
||||
method_name.content,
|
||||
)
|
||||
.unwrap_or_else(|err| {
|
||||
self.errs.push(err);
|
||||
});
|
||||
}
|
||||
let argc = args.len();
|
||||
let mut kws = Vec::with_capacity(args.kw_len());
|
||||
while let Some(arg) = args.try_remove_pos(0) {
|
||||
|
@ -828,32 +968,6 @@ impl CodeGenerator {
|
|||
// (1 (method) + argc + kwsc) input objects -> 1 return object
|
||||
self.stack_dec_n((1 + argc + kwsc) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
fn emit_call_callable_obj(&mut self, obj: Expr, mut args: Args) {
|
||||
self.codegen_expr(obj);
|
||||
let argc = args.len();
|
||||
let mut kws = Vec::with_capacity(args.kw_len());
|
||||
while let Some(arg) = args.try_remove_pos(0) {
|
||||
self.codegen_expr(arg.expr);
|
||||
}
|
||||
while let Some(arg) = args.try_remove_kw(0) {
|
||||
kws.push(ValueObj::Str(arg.keyword.content.clone()));
|
||||
self.codegen_expr(arg.expr);
|
||||
}
|
||||
let kwsc = if !kws.is_empty() {
|
||||
let kws_tuple = ValueObj::from(kws);
|
||||
self.emit_load_const(kws_tuple);
|
||||
self.write_instr(CALL_FUNCTION_KW);
|
||||
1
|
||||
} else {
|
||||
self.write_instr(CALL_FUNCTION);
|
||||
0
|
||||
};
|
||||
self.write_arg(argc as u8);
|
||||
// (1 (name) + argc + kwsc) objects -> 1 return object
|
||||
self.stack_dec_n((1 + argc + kwsc) - 1);
|
||||
}
|
||||
|
||||
// assert takes 1 or 2 arguments (0: cond, 1: message)
|
||||
fn emit_assert_instr(&mut self, mut args: Args) -> CompileResult<()> {
|
||||
|
@ -912,7 +1026,7 @@ impl CodeGenerator {
|
|||
self.emit_load_const(lit.data);
|
||||
}
|
||||
Expr::Accessor(Accessor::Local(l)) => {
|
||||
self.emit_load_name_instr(l.inspect().clone())
|
||||
self.emit_load_name_instr(Identifier::new(None, VarName::new(l.name)))
|
||||
.unwrap_or_else(|err| {
|
||||
self.errs.push(err);
|
||||
});
|
||||
|
@ -971,7 +1085,8 @@ impl CodeGenerator {
|
|||
match &bin.op.kind {
|
||||
// l..<r == range(l, r)
|
||||
TokenKind::RightOpen => {
|
||||
self.emit_load_name_instr(Str::ever("range")).unwrap();
|
||||
self.emit_load_name_instr(Identifier::public("range"))
|
||||
.unwrap();
|
||||
}
|
||||
TokenKind::LeftOpen | TokenKind::Closed | TokenKind::Open => todo!(),
|
||||
_ => {}
|
||||
|
@ -1034,22 +1149,15 @@ impl CodeGenerator {
|
|||
_ => {}
|
||||
}
|
||||
}
|
||||
Expr::Call(call) => {
|
||||
// TODO: unwrap
|
||||
let name = Str::from(obj_name(&call.obj).unwrap());
|
||||
match *call.obj {
|
||||
Expr::Accessor(Accessor::Local(_)) => {
|
||||
self.emit_call_name(name, call.args).unwrap();
|
||||
}
|
||||
Expr::Accessor(Accessor::Attr(a)) => {
|
||||
// TODO: impl static dispatch mode
|
||||
self.emit_call_method(*a.obj, name, call.args, false);
|
||||
Expr::Call(call) => match *call.obj {
|
||||
Expr::Accessor(Accessor::Local(local)) => {
|
||||
let name = VarName::new(local.name);
|
||||
self.emit_call_special(name, call.args).unwrap();
|
||||
}
|
||||
obj => {
|
||||
self.emit_call_callable_obj(obj, call.args);
|
||||
}
|
||||
}
|
||||
self.emit_call(obj, call.method_name, call.args);
|
||||
}
|
||||
},
|
||||
// TODO: list comprehension
|
||||
Expr::Array(arr) => match arr {
|
||||
Array::Normal(mut arr) => {
|
||||
|
@ -1082,7 +1190,7 @@ impl CodeGenerator {
|
|||
/// forブロックなどで使う
|
||||
fn codegen_frameless_block(&mut self, block: Block, params: Vec<Str>) {
|
||||
for param in params {
|
||||
self.emit_store_instr(param, Name);
|
||||
self.emit_store_instr(Identifier::private(param), Name);
|
||||
}
|
||||
for expr in block.into_iter() {
|
||||
self.codegen_expr(expr);
|
||||
|
@ -1106,9 +1214,9 @@ impl CodeGenerator {
|
|||
));
|
||||
let mod_name = self.toplevel_block_codeobj().name.clone();
|
||||
self.emit_load_const(mod_name);
|
||||
self.emit_store_instr(Str::from("__module__"), Attr);
|
||||
self.emit_store_instr(Identifier::public("__module__"), Attr);
|
||||
self.emit_load_const(name);
|
||||
self.emit_store_instr(Str::from("__qualname__"), Attr);
|
||||
self.emit_store_instr(Identifier::public("__qualname__"), Attr);
|
||||
// TODO: サブルーチンはT.subという書式でSTORE
|
||||
for expr in block.into_iter() {
|
||||
self.codegen_expr(expr);
|
||||
|
@ -1222,7 +1330,8 @@ impl CodeGenerator {
|
|||
let mut print_point = 0;
|
||||
if self.input().is_repl() {
|
||||
print_point = self.cur_block().lasti;
|
||||
self.emit_load_name_instr(Str::ever("print")).unwrap();
|
||||
self.emit_load_name_instr(Identifier::public("print"))
|
||||
.unwrap();
|
||||
}
|
||||
for expr in hir.module.into_iter() {
|
||||
self.codegen_expr(expr);
|
||||
|
|
|
@ -15,10 +15,10 @@ use erg_common::ty::{
|
|||
Constraint, FreeKind, HasLevel, IntervalOp, ParamTy, Predicate, RefinementType, SubrKind,
|
||||
SubrType, TyBound, TyParam, TyParamOrdering, Type,
|
||||
};
|
||||
use erg_common::value::ValueObj;
|
||||
use erg_common::value::{ValueObj, Visibility};
|
||||
use erg_common::Str;
|
||||
use erg_common::{
|
||||
assume_unreachable, enum_unwrap, fmt_slice, fn_name, get_hash, log, set, try_map,
|
||||
assume_unreachable, enum_unwrap, fmt_option, fmt_slice, fn_name, get_hash, log, set, try_map,
|
||||
};
|
||||
use Predicate as Pred;
|
||||
use TyParamOrdering::*;
|
||||
|
@ -36,7 +36,7 @@ use crate::error::readable_name;
|
|||
use crate::error::{binop_to_dname, unaryop_to_dname, TyCheckError, TyCheckErrors, TyCheckResult};
|
||||
use crate::eval::Evaluator;
|
||||
use crate::hir;
|
||||
use crate::varinfo::{Mutability, ParamIdx, VarInfo, VarKind, Visibility};
|
||||
use crate::varinfo::{Mutability, ParamIdx, VarInfo, VarKind};
|
||||
use Mutability::*;
|
||||
use Visibility::*;
|
||||
|
||||
|
@ -777,30 +777,30 @@ impl Context {
|
|||
opt_t: Option<Type>,
|
||||
id: Option<DefId>,
|
||||
) -> TyCheckResult<()> {
|
||||
let vis = Private; // TODO:
|
||||
let muty = Mutability::from(&sig.inspect().unwrap()[..]);
|
||||
match &sig.pat {
|
||||
ast::VarPattern::Local(v) => {
|
||||
ast::VarPattern::Ident(ident) => {
|
||||
if sig.t_spec.is_none() && opt_t.is_none() {
|
||||
Err(TyCheckError::no_type_spec_error(
|
||||
line!() as usize,
|
||||
sig.loc(),
|
||||
self.caused_by(),
|
||||
v.inspect(),
|
||||
ident.inspect(),
|
||||
))
|
||||
} else {
|
||||
if self.registered(v.inspect(), v.inspect().is_uppercase()) {
|
||||
if self.registered(ident.inspect(), ident.is_const()) {
|
||||
return Err(TyCheckError::duplicate_decl_error(
|
||||
line!() as usize,
|
||||
sig.loc(),
|
||||
self.caused_by(),
|
||||
v.inspect(),
|
||||
ident.inspect(),
|
||||
));
|
||||
}
|
||||
let vis = ident.vis();
|
||||
let kind = id.map_or(VarKind::Declared, VarKind::Defined);
|
||||
let sig_t = self.instantiate_var_sig_t(sig, opt_t, PreRegister)?;
|
||||
self.decls
|
||||
.insert(v.clone(), VarInfo::new(sig_t, muty, vis, kind));
|
||||
.insert(ident.name.clone(), VarInfo::new(sig_t, muty, vis, kind));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -826,7 +826,8 @@ impl Context {
|
|||
opt_ret_t: Option<Type>,
|
||||
id: Option<DefId>,
|
||||
) -> TyCheckResult<()> {
|
||||
let name = sig.name.inspect();
|
||||
let name = sig.ident.inspect();
|
||||
let vis = sig.ident.vis();
|
||||
let muty = Mutability::from(&name[..]);
|
||||
let kind = id.map_or(VarKind::Declared, VarKind::Defined);
|
||||
if self.registered(name, name.is_uppercase()) {
|
||||
|
@ -838,7 +839,7 @@ impl Context {
|
|||
));
|
||||
}
|
||||
let t = self.instantiate_sub_sig_t(sig, opt_ret_t, PreRegister)?;
|
||||
let vi = VarInfo::new(t, muty, Private, kind);
|
||||
let vi = VarInfo::new(t, muty, vis, kind);
|
||||
if let Some(_decl) = self.decls.remove(name) {
|
||||
return Err(TyCheckError::duplicate_decl_error(
|
||||
line!() as usize,
|
||||
|
@ -847,7 +848,7 @@ impl Context {
|
|||
name,
|
||||
));
|
||||
} else {
|
||||
self.decls.insert(sig.name.clone(), vi);
|
||||
self.decls.insert(sig.ident.name.clone(), vi);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -868,7 +869,6 @@ impl Context {
|
|||
id: DefId,
|
||||
) -> TyCheckResult<()> {
|
||||
self.validate_var_sig_t(sig, body_t, Normal)?;
|
||||
let vis = Private; // TODO:
|
||||
let muty = Mutability::from(&sig.inspect().unwrap()[..]);
|
||||
let (generalized, bounds) = self.generalize_t(body_t.clone());
|
||||
let generalized = if !bounds.is_empty() {
|
||||
|
@ -882,24 +882,24 @@ impl Context {
|
|||
};
|
||||
match &sig.pat {
|
||||
ast::VarPattern::Discard(_token) => Ok(()),
|
||||
ast::VarPattern::Local(v) => {
|
||||
if self.registered(v.inspect(), v.inspect().is_uppercase()) {
|
||||
ast::VarPattern::Ident(ident) => {
|
||||
if self.registered(ident.inspect(), ident.is_const()) {
|
||||
Err(TyCheckError::reassign_error(
|
||||
line!() as usize,
|
||||
v.loc(),
|
||||
ident.loc(),
|
||||
self.caused_by(),
|
||||
v.inspect(),
|
||||
ident.inspect(),
|
||||
))
|
||||
} else {
|
||||
if self.decls.remove(v.inspect()).is_some() {
|
||||
if self.decls.remove(ident.inspect()).is_some() {
|
||||
// something to do?
|
||||
}
|
||||
let vis = ident.vis();
|
||||
let vi = VarInfo::new(generalized, muty, vis, VarKind::Defined(id));
|
||||
self.params.push((Some(v.clone()), vi));
|
||||
self.params.push((Some(ident.name.clone()), vi));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
ast::VarPattern::Public(_) => todo!(),
|
||||
ast::VarPattern::Array(arr) => {
|
||||
for (elem, inf) in arr.iter().zip(generalized.inner_ts().iter()) {
|
||||
let id = DefId(get_hash(&(&self.name, elem)));
|
||||
|
@ -1036,12 +1036,12 @@ impl Context {
|
|||
id: DefId,
|
||||
body_t: &Type,
|
||||
) -> TyCheckResult<()> {
|
||||
let muty = if sig.name.is_const() {
|
||||
let muty = if sig.ident.is_const() {
|
||||
Mutability::Const
|
||||
} else {
|
||||
Mutability::Immutable
|
||||
};
|
||||
let name = &sig.name;
|
||||
let name = &sig.ident.name;
|
||||
// FIXME: constでない関数
|
||||
let t = self
|
||||
.get_current_scope_var(name.inspect())
|
||||
|
@ -1070,7 +1070,7 @@ impl Context {
|
|||
name.inspect(),
|
||||
))
|
||||
} else {
|
||||
let sub_t = if sig.name.is_procedural() {
|
||||
let sub_t = if sig.ident.is_procedural() {
|
||||
Type::proc(
|
||||
non_default_params.clone(),
|
||||
default_params.clone(),
|
||||
|
@ -2617,13 +2617,13 @@ impl Context {
|
|||
));
|
||||
}
|
||||
}
|
||||
ast::VarPattern::Local(n) => {
|
||||
ast::VarPattern::Ident(ident) => {
|
||||
if self.unify(&spec_t, body_t, None, Some(sig.loc())).is_err() {
|
||||
return Err(TyCheckError::type_mismatch_error(
|
||||
line!() as usize,
|
||||
n.loc(),
|
||||
ident.loc(),
|
||||
self.caused_by(),
|
||||
n.inspect(),
|
||||
ident.inspect(),
|
||||
&spec_t,
|
||||
body_t,
|
||||
));
|
||||
|
@ -2703,7 +2703,7 @@ impl Context {
|
|||
None,
|
||||
)?;
|
||||
}
|
||||
Ok(if sig.name.is_procedural() {
|
||||
Ok(if sig.ident.is_procedural() {
|
||||
Type::proc(non_defaults, defaults, return_t)
|
||||
} else {
|
||||
Type::func(non_defaults, defaults, return_t)
|
||||
|
@ -3104,17 +3104,35 @@ impl Context {
|
|||
}
|
||||
|
||||
/// 戻り値ではなく、call全体の型を返す
|
||||
/// objは現時点ではAccessorのみ対応
|
||||
/// 受け入れるobj(Accessor)はcheckしてないハリボテ
|
||||
fn search_call_t(&self, callee: &hir::Expr, namespace: &Str) -> TyCheckResult<Type> {
|
||||
match callee {
|
||||
hir::Expr::Accessor(hir::Accessor::Local(local)) => {
|
||||
fn search_callee_t(
|
||||
&self,
|
||||
obj: &hir::Expr,
|
||||
method_name: &Option<Token>,
|
||||
namespace: &Str,
|
||||
) -> TyCheckResult<Type> {
|
||||
if let Some(method_name) = method_name.as_ref() {
|
||||
for ctx in self.rec_sorted_sup_type_ctxs(obj.ref_t()) {
|
||||
if let Some(vi) = ctx.locals.get(method_name.inspect()) {
|
||||
return Ok(vi.t());
|
||||
} else if let Some(vi) = ctx.decls.get(method_name.inspect()) {
|
||||
return Ok(vi.t());
|
||||
}
|
||||
}
|
||||
Err(TyCheckError::no_attr_error(
|
||||
line!() as usize,
|
||||
method_name.loc(),
|
||||
namespace.clone(),
|
||||
obj.ref_t(),
|
||||
method_name.inspect(),
|
||||
self.get_similar_attr(obj.ref_t(), method_name.inspect()),
|
||||
))
|
||||
} else {
|
||||
if obj.ref_t().rec_eq(&ASTOmitted) {
|
||||
let local = enum_unwrap!(obj, hir::Expr::Accessor:(hir::Accessor::Local:(_)));
|
||||
self.get_var_t(&local.name, namespace)
|
||||
} else {
|
||||
Ok(obj.t())
|
||||
}
|
||||
hir::Expr::Accessor(hir::Accessor::Attr(attr)) => {
|
||||
self.get_attr_t(&attr.obj, &attr.name, namespace)
|
||||
}
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3127,7 +3145,8 @@ impl Context {
|
|||
erg_common::debug_power_assert!(args.len() == 2);
|
||||
let symbol = Token::symbol(binop_to_dname(op.inspect()));
|
||||
let op = hir::Expr::Accessor(hir::Accessor::local(symbol, Type::ASTOmitted));
|
||||
self.get_call_t(&op, args, &[], namespace).map_err(|e| {
|
||||
self.get_call_t(&op, &None, args, &[], namespace)
|
||||
.map_err(|e| {
|
||||
// HACK: dname.loc()はダミーLocationしか返さないので、エラーならop.loc()で上書きする
|
||||
let core = ErrorCore::new(
|
||||
e.core.errno,
|
||||
|
@ -3149,7 +3168,8 @@ impl Context {
|
|||
erg_common::debug_power_assert!(args.len() == 1);
|
||||
let symbol = Token::symbol(unaryop_to_dname(op.inspect()));
|
||||
let op = hir::Expr::Accessor(hir::Accessor::local(symbol, Type::ASTOmitted));
|
||||
self.get_call_t(&op, args, &[], namespace).map_err(|e| {
|
||||
self.get_call_t(&op, &None, args, &[], namespace)
|
||||
.map_err(|e| {
|
||||
let core = ErrorCore::new(
|
||||
e.core.errno,
|
||||
e.core.kind,
|
||||
|
@ -3163,26 +3183,30 @@ impl Context {
|
|||
|
||||
pub(crate) fn get_call_t(
|
||||
&self,
|
||||
callee: &hir::Expr,
|
||||
obj: &hir::Expr,
|
||||
method_name: &Option<Token>,
|
||||
pos_args: &[hir::PosArg],
|
||||
kw_args: &[hir::KwArg],
|
||||
namespace: &Str,
|
||||
) -> TyCheckResult<Type> {
|
||||
match callee {
|
||||
match obj {
|
||||
hir::Expr::Accessor(hir::Accessor::Local(local)) if &local.inspect()[..] == "match" => {
|
||||
return self.get_match_call_t(pos_args, kw_args)
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
let found = self.search_call_t(callee, namespace)?;
|
||||
log!("Found:\ncallee: {callee}\nfound: {found}");
|
||||
let instance = self.instantiate(found, callee)?;
|
||||
let found = self.search_callee_t(obj, method_name, namespace)?;
|
||||
log!(
|
||||
"Found:\ncallee: {obj}{}\nfound: {found}",
|
||||
fmt_option!(pre ".", method_name.as_ref().map(|t| &t.content))
|
||||
);
|
||||
let instance = self.instantiate(found, obj)?;
|
||||
log!(
|
||||
"Instantiated:\ninstance: {instance}\npos_args: ({})\nkw_args: ({})",
|
||||
fmt_slice(pos_args),
|
||||
fmt_slice(kw_args)
|
||||
);
|
||||
self.substitute_call(callee, &instance, pos_args, kw_args)?;
|
||||
self.substitute_call(obj, &instance, pos_args, kw_args)?;
|
||||
log!("Substituted:\ninstance: {instance}");
|
||||
let res = self.deref_tyvar(instance)?;
|
||||
log!("Derefed:\nres: {res}\n");
|
||||
|
@ -3195,7 +3219,7 @@ impl Context {
|
|||
log!("Params Evaluated:\nres: {res}\n");
|
||||
let res = self.deref_tyvar(res)?;
|
||||
log!("Derefed (2):\nres: {res}\n");
|
||||
self.propagate(&res, callee)?;
|
||||
self.propagate(&res, obj)?;
|
||||
log!("Propagated:\nres: {res}\n");
|
||||
Ok(res)
|
||||
}
|
||||
|
@ -4150,6 +4174,7 @@ impl Context {
|
|||
if name.len() <= 1 {
|
||||
return None;
|
||||
}
|
||||
// TODO: add `.decls`
|
||||
let most_similar_name = self
|
||||
.params
|
||||
.iter()
|
||||
|
|
|
@ -5,11 +5,12 @@
|
|||
use erg_common::color::{GREEN, RESET};
|
||||
use erg_common::log;
|
||||
use erg_common::traits::Stream;
|
||||
use erg_common::value::Visibility;
|
||||
use erg_common::Str;
|
||||
|
||||
use crate::error::{EffectError, EffectErrors, EffectResult};
|
||||
use crate::hir::{Accessor, Def, Expr, Signature, HIR};
|
||||
use crate::varinfo::Visibility;
|
||||
|
||||
use Visibility::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -85,7 +86,7 @@ impl SideEffectChecker {
|
|||
(Str::ever("::<instant>"), Private)
|
||||
}
|
||||
}
|
||||
Signature::Subr(subr) => (subr.name.inspect().clone(), Private),
|
||||
Signature::Subr(subr) => (subr.ident.inspect().clone(), Private),
|
||||
};
|
||||
self.path_stack.push(name_and_vis);
|
||||
// TODO: support raw identifier (``)
|
||||
|
|
|
@ -5,9 +5,9 @@ use erg_common::rccell::RcCell;
|
|||
use erg_common::set::Set;
|
||||
use erg_common::traits::Stream;
|
||||
use erg_common::ty::{OpKind, Predicate, SubrKind, TyBound, TyParam, Type};
|
||||
use erg_common::value::ValueObj;
|
||||
use erg_common::Str;
|
||||
use erg_common::value::{Field, ValueObj};
|
||||
use erg_common::{fn_name, set};
|
||||
use erg_common::{RcArray, Str};
|
||||
use OpKind::*;
|
||||
|
||||
use erg_parser::ast::*;
|
||||
|
@ -181,6 +181,46 @@ impl Evaluator {
|
|||
None
|
||||
}
|
||||
|
||||
fn eval_const_array(&self, arr: &Array, ctx: &Context) -> Option<ValueObj> {
|
||||
let mut elems = vec![];
|
||||
match arr {
|
||||
Array::Normal(arr) => {
|
||||
for elem in arr.elems.pos_args().iter() {
|
||||
if let Some(elem) = self.eval_const_expr(&elem.expr, ctx) {
|
||||
elems.push(elem);
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
Some(ValueObj::Array(RcArray::from(elems)))
|
||||
}
|
||||
|
||||
fn eval_const_record(&self, _record: &Record, ctx: &Context) -> Option<ValueObj> {
|
||||
let mut attrs = vec![];
|
||||
for attr in _record.attrs.iter() {
|
||||
if let Some(elem) = self.eval_const_block(&attr.body.block, ctx) {
|
||||
let ident = match &attr.sig {
|
||||
Signature::Var(var) => match &var.pat {
|
||||
VarPattern::Ident(ident) => {
|
||||
Field::new(ident.vis(), ident.inspect().clone())
|
||||
}
|
||||
_ => todo!(),
|
||||
},
|
||||
_ => todo!(),
|
||||
};
|
||||
attrs.push((ident, elem));
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
Some(ValueObj::Record(attrs.into_iter().collect()))
|
||||
}
|
||||
|
||||
// ConstExprを評価するのではなく、コンパイル時関数の式(AST上ではただのExpr)を評価する
|
||||
// コンパイル時評価できないならNoneを返す
|
||||
pub(crate) fn eval_const_expr(&self, expr: &Expr, ctx: &Context) -> Option<ValueObj> {
|
||||
|
@ -191,6 +231,8 @@ impl Evaluator {
|
|||
Expr::UnaryOp(unary) => self.eval_const_unary(unary),
|
||||
Expr::Call(call) => self.eval_const_call(call, ctx),
|
||||
Expr::Def(def) => self.eval_const_def(def),
|
||||
Expr::Array(arr) => self.eval_const_array(arr, ctx),
|
||||
Expr::Record(rec) => self.eval_const_record(rec, ctx),
|
||||
other => todo!("{other}"),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ use std::fmt;
|
|||
use erg_common::error::Location;
|
||||
use erg_common::traits::{HasType, Locational, NestedDisplay, Stream};
|
||||
use erg_common::ty::{Constraint, TyParam, Type};
|
||||
use erg_common::value::ValueObj;
|
||||
use erg_common::value::{ValueObj, Visibility};
|
||||
use erg_common::Str;
|
||||
use erg_common::{
|
||||
impl_display_for_enum, impl_display_from_nested, impl_locational, impl_locational_for_enum,
|
||||
|
@ -12,7 +12,7 @@ use erg_common::{
|
|||
impl_t, impl_t_for_enum,
|
||||
};
|
||||
|
||||
use erg_parser::ast::{fmt_lines, DefId, Params, VarName, VarPattern};
|
||||
use erg_parser::ast::{fmt_lines, DefId, Identifier, Params, VarPattern};
|
||||
use erg_parser::token::{Token, TokenKind};
|
||||
|
||||
use crate::error::readable_name;
|
||||
|
@ -676,9 +676,9 @@ impl UnaryOp {
|
|||
#[derive(Debug, Clone)]
|
||||
pub struct Call {
|
||||
pub obj: Box<Expr>,
|
||||
pub method_name: Option<Token>,
|
||||
pub args: Args,
|
||||
/// 全体の型、e.g. `abs(-1)` -> `Neg -> Nat`
|
||||
/// necessary for mangling
|
||||
/// 全体の型(引数自体の型は関係ない)、e.g. `abs(-1)` -> `Neg -> Nat`
|
||||
pub sig_t: Type,
|
||||
}
|
||||
|
||||
|
@ -725,9 +725,10 @@ impl Locational for Call {
|
|||
}
|
||||
|
||||
impl Call {
|
||||
pub fn new(obj: Expr, args: Args, sig_t: Type) -> Self {
|
||||
pub fn new(obj: Expr, method_name: Option<Token>, args: Args, sig_t: Type) -> Self {
|
||||
Self {
|
||||
obj: Box::new(obj),
|
||||
method_name,
|
||||
args,
|
||||
sig_t,
|
||||
}
|
||||
|
@ -808,34 +809,38 @@ impl VarSignature {
|
|||
pub fn inspect(&self) -> Option<&Str> {
|
||||
self.pat.inspect()
|
||||
}
|
||||
|
||||
pub fn vis(&self) -> Visibility {
|
||||
self.pat.vis()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SubrSignature {
|
||||
pub name: VarName,
|
||||
pub ident: Identifier,
|
||||
pub params: Params,
|
||||
pub t: Type,
|
||||
}
|
||||
|
||||
impl fmt::Display for SubrSignature {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}{} (: {})", self.name, self.params, self.t)
|
||||
write!(f, "{}{} (: {})", self.ident, self.params, self.t)
|
||||
}
|
||||
}
|
||||
|
||||
impl Locational for SubrSignature {
|
||||
fn loc(&self) -> Location {
|
||||
Location::concat(&self.name, &self.params)
|
||||
Location::concat(&self.ident, &self.params)
|
||||
}
|
||||
}
|
||||
|
||||
impl SubrSignature {
|
||||
pub const fn new(name: VarName, params: Params, t: Type) -> Self {
|
||||
Self { name, params, t }
|
||||
pub const fn new(ident: Identifier, params: Params, t: Type) -> Self {
|
||||
Self { ident, params, t }
|
||||
}
|
||||
|
||||
pub fn is_procedural(&self) -> bool {
|
||||
self.name.is_procedural()
|
||||
self.ident.is_procedural()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -892,14 +897,21 @@ impl Signature {
|
|||
pub fn is_const(&self) -> bool {
|
||||
match self {
|
||||
Self::Var(v) => v.pat.is_const(),
|
||||
Self::Subr(s) => s.name.is_const(),
|
||||
Self::Subr(s) => s.ident.is_const(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_procedural(&self) -> bool {
|
||||
match self {
|
||||
Self::Var(v) => v.pat.is_procedural(),
|
||||
Self::Subr(s) => s.name.is_procedural(),
|
||||
Self::Subr(s) => s.ident.is_procedural(),
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn vis(&self) -> Visibility {
|
||||
match self {
|
||||
Self::Var(v) => v.pat.vis(),
|
||||
Self::Subr(s) => s.ident.vis(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
//! 組み込みオブジェクトの型情報を(Contextに)定義
|
||||
use erg_common::ty::type_constrs::*;
|
||||
use erg_common::ty::{TyParam, Type};
|
||||
use erg_common::value::ValueObj;
|
||||
use erg_common::value::{ValueObj, Visibility};
|
||||
use erg_common::Str;
|
||||
use erg_common::{debug_power_assert, set};
|
||||
use ParamSpec as PS;
|
||||
|
@ -12,7 +12,7 @@ use Type::*;
|
|||
use erg_parser::ast::VarName;
|
||||
|
||||
use crate::context::{ConstTemplate, Context, ContextKind, DefaultInfo, ParamSpec};
|
||||
use crate::varinfo::{Mutability, VarInfo, VarKind, Visibility};
|
||||
use crate::varinfo::{Mutability, VarInfo, VarKind};
|
||||
use DefaultInfo::*;
|
||||
use Mutability::*;
|
||||
use VarKind::*;
|
||||
|
|
|
@ -6,7 +6,7 @@ use erg_common::error::Location;
|
|||
use erg_common::get_hash;
|
||||
use erg_common::traits::{HasType, Locational, Stream};
|
||||
use erg_common::ty::{ParamTy, TyParam, Type};
|
||||
use erg_common::value::ValueObj;
|
||||
use erg_common::value::{ValueObj, Visibility};
|
||||
use erg_common::{fn_name, log, switch_lang};
|
||||
|
||||
use erg_parser::ast;
|
||||
|
@ -16,7 +16,6 @@ use crate::context::{Context, ContextKind, RegistrationMode};
|
|||
use crate::error::{LowerError, LowerErrors, LowerResult, LowerWarnings};
|
||||
use crate::hir;
|
||||
use crate::hir::HIR;
|
||||
use crate::varinfo::Visibility;
|
||||
use Visibility::*;
|
||||
|
||||
/// Singleton that checks types of an AST, and convert (lower) it into a HIR
|
||||
|
@ -245,10 +244,14 @@ impl ASTLowerer {
|
|||
));
|
||||
}
|
||||
let obj = self.lower_expr(*call.obj, false)?;
|
||||
let t = self
|
||||
.ctx
|
||||
.get_call_t(&obj, &hir_args.pos_args, &hir_args.kw_args, &self.ctx.name)?;
|
||||
Ok(hir::Call::new(obj, hir_args, t))
|
||||
let t = self.ctx.get_call_t(
|
||||
&obj,
|
||||
&call.method_name,
|
||||
&hir_args.pos_args,
|
||||
&hir_args.kw_args,
|
||||
&self.ctx.name,
|
||||
)?;
|
||||
Ok(hir::Call::new(obj, call.method_name, hir_args, t))
|
||||
}
|
||||
|
||||
fn lower_lambda(&mut self, lambda: ast::Lambda) -> LowerResult<hir::Lambda> {
|
||||
|
@ -361,13 +364,13 @@ impl ASTLowerer {
|
|||
.assign_var(&sig, id, found_body_t)?;
|
||||
match block.first().unwrap() {
|
||||
hir::Expr::Call(call) => {
|
||||
if let ast::VarPattern::Local(name) = &sig.pat {
|
||||
if let ast::VarPattern::Ident(ident) = &sig.pat {
|
||||
if call.is_import_call() {
|
||||
self.ctx
|
||||
.outer
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.import_mod(name, &call.args.pos_args.first().unwrap().expr)?;
|
||||
.import_mod(&ident.name, &call.args.pos_args.first().unwrap().expr)?;
|
||||
}
|
||||
} else {
|
||||
todo!()
|
||||
|
@ -392,9 +395,9 @@ impl ASTLowerer {
|
|||
.outer
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.get_current_scope_var(sig.name.inspect())
|
||||
.get_current_scope_var(sig.ident.inspect())
|
||||
.unwrap_or_else(|| {
|
||||
log!("{}\n", sig.name.inspect());
|
||||
log!("{}\n", sig.ident.inspect());
|
||||
log!("{}\n", self.ctx.outer.as_ref().unwrap());
|
||||
panic!()
|
||||
}) // FIXME: or instantiate
|
||||
|
@ -406,7 +409,7 @@ impl ASTLowerer {
|
|||
let found_body_t = block.ref_t();
|
||||
let expect_body_t = t.return_t().unwrap();
|
||||
if let Err(e) =
|
||||
self.return_t_check(sig.loc(), sig.name.inspect(), expect_body_t, found_body_t)
|
||||
self.return_t_check(sig.loc(), sig.ident.inspect(), expect_body_t, found_body_t)
|
||||
{
|
||||
self.errs.push(e);
|
||||
}
|
||||
|
@ -416,7 +419,7 @@ impl ASTLowerer {
|
|||
.as_mut()
|
||||
.unwrap()
|
||||
.assign_subr(&sig, id, found_body_t)?;
|
||||
let sig = hir::SubrSignature::new(sig.name, sig.params, t);
|
||||
let sig = hir::SubrSignature::new(sig.ident, sig.params, t);
|
||||
let body = hir::DefBody::new(body.op, block, body.id);
|
||||
Ok(hir::Def::new(hir::Signature::Subr(sig), body))
|
||||
}
|
||||
|
|
|
@ -5,11 +5,11 @@ use erg_common::log;
|
|||
use erg_common::set::Set;
|
||||
use erg_common::traits::{HasType, Locational, Stream};
|
||||
use erg_common::ty::{ArgsOwnership, Ownership};
|
||||
use erg_common::value::Visibility;
|
||||
use erg_common::Str;
|
||||
|
||||
use crate::error::{OwnershipError, OwnershipErrors, OwnershipResult};
|
||||
use crate::hir::{self, Accessor, Array, Block, Def, Expr, Signature, HIR};
|
||||
use crate::varinfo::Visibility;
|
||||
use Visibility::*;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
|
@ -84,19 +84,17 @@ impl OwnershipChecker {
|
|||
match expr {
|
||||
Expr::Def(def) => {
|
||||
self.define(def);
|
||||
let name_and_vis = match &def.sig {
|
||||
Signature::Var(var) =>
|
||||
// TODO: visibility
|
||||
{
|
||||
let name = match &def.sig {
|
||||
Signature::Var(var) => {
|
||||
if let Some(name) = var.inspect() {
|
||||
(name.clone(), Private)
|
||||
name.clone()
|
||||
} else {
|
||||
(Str::ever("::<instant>"), Private)
|
||||
Str::ever("::<instant>")
|
||||
}
|
||||
}
|
||||
Signature::Subr(subr) => (subr.name.inspect().clone(), Private),
|
||||
Signature::Subr(subr) => subr.ident.inspect().clone(),
|
||||
};
|
||||
self.path_stack.push(name_and_vis);
|
||||
self.path_stack.push((name, def.sig.vis()));
|
||||
self.dict
|
||||
.insert(Str::from(self.full_path()), LocalVars::default());
|
||||
self.check_block(&def.body.block);
|
||||
|
@ -239,7 +237,7 @@ impl OwnershipChecker {
|
|||
Signature::Subr(sig) => {
|
||||
self.current_scope()
|
||||
.alive_vars
|
||||
.insert(sig.name.inspect().clone());
|
||||
.insert(sig.ident.inspect().clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@ use std::fmt;
|
|||
|
||||
use erg_common::traits::HasType;
|
||||
use erg_common::ty::Type;
|
||||
use erg_common::value::Visibility;
|
||||
use Visibility::*;
|
||||
|
||||
use erg_parser::ast::DefId;
|
||||
|
||||
|
@ -32,24 +34,6 @@ impl Mutability {
|
|||
|
||||
use Mutability::*;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
#[repr(u8)]
|
||||
pub enum Visibility {
|
||||
Private,
|
||||
Public,
|
||||
}
|
||||
|
||||
impl Visibility {
|
||||
pub const fn is_public(&self) -> bool {
|
||||
matches!(self, Self::Public)
|
||||
}
|
||||
pub const fn is_private(&self) -> bool {
|
||||
matches!(self, Self::Private)
|
||||
}
|
||||
}
|
||||
|
||||
use Visibility::*;
|
||||
|
||||
/// e.g.
|
||||
/// ```erg
|
||||
/// K(T, [U, V]) = ...
|
||||
|
|
|
@ -6,7 +6,7 @@ use erg_common::error::Location;
|
|||
use erg_common::set::Set as HashSet;
|
||||
use erg_common::traits::{Locational, NestedDisplay, Stream};
|
||||
use erg_common::ty::SubrKind;
|
||||
use erg_common::value::ValueObj;
|
||||
use erg_common::value::{ValueObj, Visibility};
|
||||
use erg_common::Str;
|
||||
use erg_common::{
|
||||
fmt_option, fmt_vec, impl_display_for_enum, impl_display_for_single_struct,
|
||||
|
@ -603,6 +603,12 @@ impl From<Vec<Def>> for RecordAttrs {
|
|||
}
|
||||
}
|
||||
|
||||
impl RecordAttrs {
|
||||
pub fn iter(&self) -> impl Iterator<Item = &Def> {
|
||||
self.0.iter()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct Record {
|
||||
l_brace: Token,
|
||||
|
@ -732,12 +738,15 @@ impl UnaryOp {
|
|||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct Call {
|
||||
pub obj: Box<Expr>,
|
||||
pub method_name: Option<Token>,
|
||||
pub args: Args,
|
||||
}
|
||||
|
||||
impl NestedDisplay for Call {
|
||||
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, level: usize) -> std::fmt::Result {
|
||||
writeln!(f, "({}):", self.obj)?;
|
||||
write!(f, "({})", self.obj)?;
|
||||
write!(f, "{}", fmt_option!(pre ".", self.method_name))?;
|
||||
writeln!(f, ":")?;
|
||||
self.args.fmt_nest(f, level + 1)
|
||||
}
|
||||
}
|
||||
|
@ -755,9 +764,10 @@ impl Locational for Call {
|
|||
}
|
||||
|
||||
impl Call {
|
||||
pub fn new(obj: Expr, args: Args) -> Self {
|
||||
pub fn new(obj: Expr, method_name: Option<Token>, args: Args) -> Self {
|
||||
Self {
|
||||
obj: Box::new(obj),
|
||||
method_name,
|
||||
args,
|
||||
}
|
||||
}
|
||||
|
@ -1597,6 +1607,67 @@ impl VarName {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct Identifier {
|
||||
pub dot: Option<Token>,
|
||||
pub name: VarName,
|
||||
}
|
||||
|
||||
impl fmt::Display for Identifier {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match &self.dot {
|
||||
Some(_dot) => write!(f, ".{}", self.name),
|
||||
None => write!(f, "{}", self.name),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Locational for Identifier {
|
||||
fn loc(&self) -> Location {
|
||||
if let Some(dot) = &self.dot {
|
||||
Location::concat(dot, &self.name)
|
||||
} else {
|
||||
self.name.loc()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Identifier {
|
||||
pub const fn new(dot: Option<Token>, name: VarName) -> Self {
|
||||
Self { dot, name }
|
||||
}
|
||||
|
||||
pub fn public(name: &'static str) -> Self {
|
||||
Self::new(
|
||||
Some(Token::from_str(TokenKind::Dot, ".")),
|
||||
VarName::from_static(name),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn private(name: Str) -> Self {
|
||||
Self::new(None, VarName::from_str(name))
|
||||
}
|
||||
|
||||
pub fn is_const(&self) -> bool {
|
||||
self.name.is_const()
|
||||
}
|
||||
|
||||
pub const fn vis(&self) -> Visibility {
|
||||
match &self.dot {
|
||||
Some(_dot) => 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(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct VarArrayPattern {
|
||||
l_sqbr: Token,
|
||||
|
@ -1708,8 +1779,7 @@ impl VarRecordPattern {
|
|||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum VarPattern {
|
||||
Discard(Token),
|
||||
Local(VarName), // x
|
||||
Public(VarName), // .x
|
||||
Ident(Identifier),
|
||||
/// e.g. `[x, y, z]` of `[x, y, z] = [1, 2, 3]`
|
||||
Array(VarArrayPattern),
|
||||
/// e.g. `(x, y, z)` of `(x, y, z) = (1, 2, 3)`
|
||||
|
@ -1722,8 +1792,7 @@ impl NestedDisplay for VarPattern {
|
|||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
|
||||
match self {
|
||||
Self::Discard(_) => write!(f, "_"),
|
||||
Self::Local(n) => write!(f, "{}", n),
|
||||
Self::Public(n) => write!(f, ".{}", n),
|
||||
Self::Ident(ident) => write!(f, "{}", ident),
|
||||
Self::Array(a) => write!(f, "{}", a),
|
||||
Self::Tuple(t) => write!(f, "{}", t),
|
||||
Self::Record(r) => write!(f, "{}", r),
|
||||
|
@ -1732,19 +1801,19 @@ impl NestedDisplay for VarPattern {
|
|||
}
|
||||
|
||||
impl_display_from_nested!(VarPattern);
|
||||
impl_locational_for_enum!(VarPattern; Discard, Local, Public, Array, Tuple, Record);
|
||||
impl_locational_for_enum!(VarPattern; Discard, Ident, Array, Tuple, Record);
|
||||
|
||||
impl VarPattern {
|
||||
pub const fn inspect(&self) -> Option<&Str> {
|
||||
match self {
|
||||
Self::Local(n) | Self::Public(n) => Some(n.inspect()),
|
||||
Self::Ident(ident) => Some(ident.inspect()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn inspects(&self) -> Vec<&Str> {
|
||||
match self {
|
||||
Self::Local(n) | Self::Public(n) => vec![n.inspect()],
|
||||
Self::Ident(ident) => vec![ident.inspect()],
|
||||
Self::Array(VarArrayPattern { elems, .. })
|
||||
| Self::Tuple(VarTuplePattern { elems, .. })
|
||||
| Self::Record(VarRecordPattern { elems, .. }) => {
|
||||
|
@ -1757,7 +1826,7 @@ impl VarPattern {
|
|||
// _!(...) = ... is invalid
|
||||
pub fn is_procedural(&self) -> bool {
|
||||
match self {
|
||||
Self::Local(n) | Self::Public(n) => n.is_procedural(),
|
||||
Self::Ident(ident) => ident.is_procedural(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
@ -1765,10 +1834,18 @@ impl VarPattern {
|
|||
// _ = (type block) is invalid
|
||||
pub fn is_const(&self) -> bool {
|
||||
match self {
|
||||
Self::Local(n) | Self::Public(n) => n.is_const(),
|
||||
Self::Ident(ident) => ident.is_const(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn vis(&self) -> Visibility {
|
||||
match self {
|
||||
Self::Ident(ident) => ident.vis(),
|
||||
// TODO: `[.x, .y]`?
|
||||
_ => Visibility::Private,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
|
@ -1807,6 +1884,10 @@ impl VarSignature {
|
|||
pub fn is_const(&self) -> bool {
|
||||
self.pat.is_const()
|
||||
}
|
||||
|
||||
pub const fn vis(&self) -> Visibility {
|
||||
self.pat.vis()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
|
@ -2066,7 +2147,7 @@ impl Params {
|
|||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct SubrSignature {
|
||||
pub decorators: HashSet<Decorator>,
|
||||
pub name: VarName,
|
||||
pub ident: Identifier,
|
||||
pub params: Params,
|
||||
pub return_t_spec: Option<TypeSpec>,
|
||||
pub bounds: TypeBoundSpecs,
|
||||
|
@ -2078,7 +2159,7 @@ impl NestedDisplay for SubrSignature {
|
|||
write!(
|
||||
f,
|
||||
"{}{}{}",
|
||||
self.name,
|
||||
self.ident,
|
||||
self.params,
|
||||
fmt_option!(pre ": ", self.return_t_spec)
|
||||
)
|
||||
|
@ -2086,7 +2167,7 @@ impl NestedDisplay for SubrSignature {
|
|||
write!(
|
||||
f,
|
||||
"{}|{}|{}{}",
|
||||
self.name,
|
||||
self.ident,
|
||||
self.bounds,
|
||||
self.params,
|
||||
fmt_option!(pre ": ", self.return_t_spec)
|
||||
|
@ -2100,11 +2181,11 @@ impl_display_from_nested!(SubrSignature);
|
|||
impl Locational for SubrSignature {
|
||||
fn loc(&self) -> Location {
|
||||
if !self.bounds.is_empty() {
|
||||
Location::concat(&self.name, &self.bounds)
|
||||
Location::concat(&self.ident, &self.bounds)
|
||||
} else if let Some(return_t) = &self.return_t_spec {
|
||||
Location::concat(&self.name, return_t)
|
||||
Location::concat(&self.ident, return_t)
|
||||
} else {
|
||||
Location::concat(&self.name, &self.params)
|
||||
Location::concat(&self.ident, &self.params)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2112,14 +2193,14 @@ impl Locational for SubrSignature {
|
|||
impl SubrSignature {
|
||||
pub const fn new(
|
||||
decorators: HashSet<Decorator>,
|
||||
name: VarName,
|
||||
ident: Identifier,
|
||||
params: Params,
|
||||
return_t: Option<TypeSpec>,
|
||||
bounds: TypeBoundSpecs,
|
||||
) -> Self {
|
||||
Self {
|
||||
decorators,
|
||||
name,
|
||||
ident,
|
||||
params,
|
||||
return_t_spec: return_t,
|
||||
bounds,
|
||||
|
@ -2127,7 +2208,11 @@ impl SubrSignature {
|
|||
}
|
||||
|
||||
pub fn is_const(&self) -> bool {
|
||||
self.name.is_const()
|
||||
self.ident.is_const()
|
||||
}
|
||||
|
||||
pub const fn vis(&self) -> Visibility {
|
||||
self.ident.vis()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2236,21 +2321,21 @@ impl_locational_for_enum!(Signature; Var, Subr);
|
|||
impl Signature {
|
||||
pub fn name_as_str(&self) -> &Str {
|
||||
match self {
|
||||
Self::Var(v) => v.pat.inspect().unwrap(),
|
||||
Self::Subr(s) => s.name.inspect(),
|
||||
Self::Var(var) => var.pat.inspect().unwrap(),
|
||||
Self::Subr(subr) => subr.ident.inspect(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn name(&self) -> Option<&VarName> {
|
||||
pub fn ident(&self) -> Option<&Identifier> {
|
||||
match self {
|
||||
Self::Var(v) => {
|
||||
if let VarPattern::Local(v) = &v.pat {
|
||||
Some(v)
|
||||
Self::Var(var) => {
|
||||
if let VarPattern::Ident(ident) = &var.pat {
|
||||
Some(ident)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
Self::Subr(s) => Some(&s.name),
|
||||
Self::Subr(subr) => Some(&subr.ident),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2263,8 +2348,15 @@ impl Signature {
|
|||
|
||||
pub fn is_const(&self) -> bool {
|
||||
match self {
|
||||
Self::Var(v) => v.is_const(),
|
||||
Self::Subr(s) => s.is_const(),
|
||||
Self::Var(var) => var.is_const(),
|
||||
Self::Subr(subr) => subr.is_const(),
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn vis(&self) -> Visibility {
|
||||
match self {
|
||||
Self::Var(var) => var.vis(),
|
||||
Self::Subr(subr) => subr.vis(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ impl Desugarer {
|
|||
if previous.is_subr() && previous.sig.name_as_str() == def.sig.name_as_str()
|
||||
{
|
||||
let mut previous = enum_unwrap!(new.pop().unwrap(), Expr::Def);
|
||||
let name = def.sig.name().unwrap().clone();
|
||||
let name = def.sig.ident().unwrap().clone();
|
||||
let op = Token::from_str(TokenKind::FuncArrow, "->");
|
||||
let (call, return_t_spec) = if previous.body.block.len() == 1
|
||||
&& previous.body.block.first().unwrap().is_match_call()
|
||||
|
@ -104,7 +104,7 @@ impl Desugarer {
|
|||
vec![],
|
||||
None,
|
||||
);
|
||||
let call = Call::new(match_symbol, args);
|
||||
let call = Call::new(match_symbol, None, args);
|
||||
(call, return_t_spec)
|
||||
};
|
||||
let param_name = enum_unwrap!(&call.args.pos_args().iter().next().unwrap().expr, Expr::Accessor:(Accessor::Local:(_))).inspect();
|
||||
|
|
|
@ -515,7 +515,7 @@ impl Parser {
|
|||
return Ok(Signature::Var(var));
|
||||
}
|
||||
let decorators = self.opt_reduce_decorators().map_err(|_| self.stack_dec())?;
|
||||
let (opt_dot, name) = self.try_reduce_name().map_err(|_| self.stack_dec())?;
|
||||
let ident = self.try_reduce_ident().map_err(|_| self.stack_dec())?;
|
||||
// TODO: parse bounds |...|
|
||||
let bounds = TypeBoundSpecs::empty();
|
||||
if self.cur_is(VBar) {
|
||||
|
@ -534,7 +534,7 @@ impl Parser {
|
|||
};
|
||||
self.level -= 1;
|
||||
Ok(Signature::Subr(SubrSignature::new(
|
||||
decorators, name, params, t_spec, bounds,
|
||||
decorators, ident, params, t_spec, bounds,
|
||||
)))
|
||||
} else {
|
||||
if !bounds.is_empty() {
|
||||
|
@ -554,7 +554,7 @@ impl Parser {
|
|||
self.errs.push(err);
|
||||
return Err(());
|
||||
}
|
||||
let t_spec = if name.is_const() {
|
||||
let t_spec = if ident.is_const() {
|
||||
if self.cur_is(SubtypeOf) {
|
||||
self.skip();
|
||||
Some(self.try_reduce_type_spec().map_err(|_| self.stack_dec())?)
|
||||
|
@ -568,12 +568,10 @@ impl Parser {
|
|||
None
|
||||
};
|
||||
self.level -= 1;
|
||||
let var_pat = if opt_dot.is_some() {
|
||||
VarPattern::Public(name)
|
||||
} else {
|
||||
VarPattern::Local(name)
|
||||
};
|
||||
Ok(Signature::Var(VarSignature::new(var_pat, t_spec)))
|
||||
Ok(Signature::Var(VarSignature::new(
|
||||
VarPattern::Ident(ident),
|
||||
t_spec,
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -906,14 +904,9 @@ impl Parser {
|
|||
debug_call_info!(self);
|
||||
match self.peek() {
|
||||
Some(t) if t.is(Symbol) => {
|
||||
let (opt_dot, varname) = self.try_reduce_name().map_err(|_| self.stack_dec())?;
|
||||
let var_pat = if let Some(_dot) = opt_dot {
|
||||
VarPattern::Public(varname)
|
||||
} else {
|
||||
VarPattern::Local(varname)
|
||||
};
|
||||
let ident = self.try_reduce_ident().map_err(|_| self.stack_dec())?;
|
||||
self.level -= 1;
|
||||
Ok(var_pat)
|
||||
Ok(VarPattern::Ident(ident))
|
||||
}
|
||||
Some(t) if t.is(UBar) => {
|
||||
self.level -= 1;
|
||||
|
@ -968,8 +961,8 @@ impl Parser {
|
|||
debug_call_info!(self);
|
||||
match self.peek() {
|
||||
Some(t) if t.is(Symbol) => {
|
||||
let (opt_dot, varname) = self.try_reduce_name().map_err(|_| self.stack_dec())?;
|
||||
if let Some(dot) = opt_dot {
|
||||
let ident = self.try_reduce_ident().map_err(|_| self.stack_dec())?;
|
||||
if let Some(dot) = &ident.dot {
|
||||
let loc = dot.loc();
|
||||
self.level -= 1;
|
||||
self.errs.push(ParseError::syntax_error(
|
||||
|
@ -986,7 +979,7 @@ impl Parser {
|
|||
return Err(());
|
||||
}
|
||||
self.level -= 1;
|
||||
Ok(ParamPattern::VarName(varname))
|
||||
Ok(ParamPattern::VarName(ident.name))
|
||||
}
|
||||
Some(t) if t.is(UBar) => {
|
||||
self.level -= 1;
|
||||
|
@ -1000,8 +993,8 @@ impl Parser {
|
|||
}
|
||||
Some(t) if t.is(Spread) => {
|
||||
self.skip();
|
||||
let (opt_dot, varname) = self.try_reduce_name().map_err(|_| self.stack_dec())?;
|
||||
if let Some(dot) = opt_dot {
|
||||
let ident = self.try_reduce_ident().map_err(|_| self.stack_dec())?;
|
||||
if let Some(dot) = &ident.dot {
|
||||
let loc = dot.loc();
|
||||
self.level -= 1;
|
||||
self.errs.push(ParseError::syntax_error(
|
||||
|
@ -1018,7 +1011,7 @@ impl Parser {
|
|||
return Err(());
|
||||
}
|
||||
self.level -= 1;
|
||||
Ok(ParamPattern::VarArgsName(varname))
|
||||
Ok(ParamPattern::VarArgsName(ident.name))
|
||||
}
|
||||
Some(t) if t.is(LSqBr) => {
|
||||
let l_sqbr = self.lpop();
|
||||
|
@ -1162,11 +1155,11 @@ impl Parser {
|
|||
debug_call_info!(self);
|
||||
if self.cur_is(Symbol) && self.nth_is(1, Colon) {
|
||||
// TODO: handle `.`
|
||||
let (_opt_dot, name) = self.try_reduce_name().map_err(|_| self.stack_dec())?;
|
||||
let ident = self.try_reduce_ident().map_err(|_| self.stack_dec())?;
|
||||
self.skip();
|
||||
let typ = self.try_reduce_type_spec().map_err(|_| self.stack_dec())?;
|
||||
self.level -= 1;
|
||||
Ok(ParamTySpec::new(Some(name.into_token()), typ))
|
||||
Ok(ParamTySpec::new(Some(ident.name.into_token()), typ))
|
||||
} else {
|
||||
let ty_spec = self.try_reduce_type_spec().map_err(|_| self.stack_dec())?;
|
||||
self.level -= 1;
|
||||
|
@ -1228,15 +1221,15 @@ impl Parser {
|
|||
debug_call_info!(self);
|
||||
match self.peek() {
|
||||
Some(t) if t.is(Symbol) => {
|
||||
// TODO: handle dot
|
||||
let (_opt_dot, name) = self.try_reduce_name().map_err(|_| self.stack_dec())?;
|
||||
// TODO: handle dot (`.`)
|
||||
let ident = self.try_reduce_ident().map_err(|_| self.stack_dec())?;
|
||||
if let Some(res) = self.opt_reduce_args() {
|
||||
let args = self.validate_const_args(res?)?;
|
||||
self.level -= 1;
|
||||
Ok(SimpleTypeSpec::new(name, args))
|
||||
Ok(SimpleTypeSpec::new(ident.name, args))
|
||||
} else {
|
||||
self.level -= 1;
|
||||
Ok(SimpleTypeSpec::new(name, ConstArgs::empty()))
|
||||
Ok(SimpleTypeSpec::new(ident.name, ConstArgs::empty()))
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
|
@ -1714,11 +1707,15 @@ impl Parser {
|
|||
self.errs.push(err);
|
||||
return Err(());
|
||||
};
|
||||
let acc = Accessor::attr(obj, Local::new(symbol));
|
||||
if let Ok(args) = self.try_reduce_args() {
|
||||
let call = Call::new(Expr::Accessor(acc), args);
|
||||
if let Some(args) = self
|
||||
.opt_reduce_args()
|
||||
.transpose()
|
||||
.map_err(|_| self.stack_dec())?
|
||||
{
|
||||
let call = Call::new(obj, Some(symbol), args);
|
||||
stack.push(ExprOrOp::Expr(Expr::Call(call)));
|
||||
} else {
|
||||
let acc = Accessor::attr(obj, Local::new(symbol));
|
||||
stack.push(ExprOrOp::Expr(Expr::Accessor(acc)));
|
||||
}
|
||||
}
|
||||
|
@ -1864,7 +1861,12 @@ impl Parser {
|
|||
let acc = self.try_reduce_acc().map_err(|_| self.stack_dec())?;
|
||||
if let Some(res) = self.opt_reduce_args() {
|
||||
let args = res.map_err(|_| self.stack_dec())?;
|
||||
let call = Call::new(Expr::Accessor(acc), args);
|
||||
let (obj, method_name) = match acc {
|
||||
Accessor::Attr(attr) => (*attr.obj, Some(attr.name.symbol)),
|
||||
Accessor::Local(local) => (Expr::Accessor(Accessor::Local(local)), None),
|
||||
_ => todo!(),
|
||||
};
|
||||
let call = Call::new(obj, method_name, args);
|
||||
self.level -= 1;
|
||||
Ok(Expr::Call(call))
|
||||
} else {
|
||||
|
@ -1978,9 +1980,8 @@ impl Parser {
|
|||
todo!()
|
||||
}
|
||||
|
||||
/// option: Dot(`.`)
|
||||
#[inline]
|
||||
fn try_reduce_name(&mut self) -> ParseResult<(Option<Token>, VarName)> {
|
||||
fn try_reduce_ident(&mut self) -> ParseResult<Identifier> {
|
||||
debug_call_info!(self);
|
||||
self.level -= 1;
|
||||
match self.peek() {
|
||||
|
@ -1988,9 +1989,13 @@ impl Parser {
|
|||
let dot = self.lpop();
|
||||
// TODO:
|
||||
assert!(self.cur_category_is(TC::Symbol));
|
||||
Ok((Some(dot), VarName::new(self.lpop())))
|
||||
let ident = Identifier::new(Some(dot), VarName::new(self.lpop()));
|
||||
Ok(ident)
|
||||
}
|
||||
Some(t) if t.is(Symbol) => {
|
||||
let ident = Identifier::new(None, VarName::new(self.lpop()));
|
||||
Ok(ident)
|
||||
}
|
||||
Some(t) if t.is(Symbol) => Ok((None, VarName::new(self.lpop()))),
|
||||
_ => {
|
||||
let err = self.skip_and_throw_syntax_err(caused_by!());
|
||||
self.errs.push(err);
|
||||
|
|
|
@ -4,3 +4,4 @@ fib 1 = 1
|
|||
fib(n: Nat): Nat = fib(n-1) + fib(n-2)
|
||||
|
||||
assert fib(10) == 55
|
||||
print! fib 10
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue