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::{fmt_iter, impl_display_from_debug, switch_lang};
|
||||||
use crate::{RcArray, Str};
|
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)]
|
#[derive(Clone, PartialEq, Default)]
|
||||||
|
@ -29,7 +68,7 @@ pub enum ValueObj {
|
||||||
Bool(bool),
|
Bool(bool),
|
||||||
Array(Rc<[ValueObj]>),
|
Array(Rc<[ValueObj]>),
|
||||||
Dict(Rc<[(ValueObj, ValueObj)]>),
|
Dict(Rc<[(ValueObj, ValueObj)]>),
|
||||||
Record(Dict<Str, ValueObj>),
|
Record(Dict<Field, ValueObj>),
|
||||||
Code(Box<CodeObj>),
|
Code(Box<CodeObj>),
|
||||||
Subr(ConstSubr),
|
Subr(ConstSubr),
|
||||||
Type(Box<Type>),
|
Type(Box<Type>),
|
||||||
|
|
|
@ -19,7 +19,7 @@ use erg_common::{
|
||||||
};
|
};
|
||||||
use Opcode::*;
|
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 erg_parser::token::{Token, TokenCategory, TokenKind};
|
||||||
|
|
||||||
use crate::compile::{AccessKind, Name, StoreLoadKind};
|
use crate::compile::{AccessKind, Name, StoreLoadKind};
|
||||||
|
@ -29,12 +29,162 @@ use crate::hir::{
|
||||||
};
|
};
|
||||||
use AccessKind::*;
|
use AccessKind::*;
|
||||||
|
|
||||||
fn obj_name(obj: &Expr) -> Option<String> {
|
fn is_python_global(name: &str) -> bool {
|
||||||
match obj {
|
match name {
|
||||||
Expr::Accessor(Accessor::Local(n)) => Some(n.inspect().to_string()),
|
"ArithmeticError"
|
||||||
Expr::Accessor(Accessor::Attr(a)) => Some(obj_name(&a.obj)? + "." + a.name.inspect()),
|
| "AssertionError"
|
||||||
Expr::Accessor(Accessor::SelfDot(n)) => Some(format!(".{}", n.inspect())),
|
| "AttributeError"
|
||||||
_ => None,
|
| "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 {
|
fn escape_name(ident: Identifier) -> Str {
|
||||||
let mut name = convert_to_python_name(name).to_string();
|
let vis = ident.vis();
|
||||||
name = name.replace('!', "__erg_proc__");
|
let mut name = convert_to_python_name(ident.name.into_token().content).to_string();
|
||||||
name = name.replace('$', "__erg_shared__");
|
name = name.replace('!', "__erg_proc");
|
||||||
Str::rc(&name)
|
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)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -324,9 +479,9 @@ impl CodeGenerator {
|
||||||
Some(StoreLoadKind::Global)
|
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 current_is_toplevel = self.cur_block() == self.toplevel_block();
|
||||||
let name = escape_name(name);
|
let name = escape_name(ident);
|
||||||
match self.rec_search(&name) {
|
match self.rec_search(&name) {
|
||||||
Some(st @ (StoreLoadKind::Local | StoreLoadKind::Global)) => {
|
Some(st @ (StoreLoadKind::Local | StoreLoadKind::Global)) => {
|
||||||
let st = if current_is_toplevel {
|
let st = if current_is_toplevel {
|
||||||
|
@ -371,10 +526,10 @@ impl CodeGenerator {
|
||||||
Name::local(self.cur_block_codeobj().names.len() - 1)
|
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
|
let name = self
|
||||||
.local_search(&name, Name)
|
.local_search(ident.inspect(), Name)
|
||||||
.unwrap_or_else(|| self.register_name(name));
|
.unwrap_or_else(|| self.register_name(ident));
|
||||||
let instr = match name.kind {
|
let instr = match name.kind {
|
||||||
StoreLoadKind::Fast | StoreLoadKind::FastConst => Opcode::LOAD_FAST,
|
StoreLoadKind::Fast | StoreLoadKind::FastConst => Opcode::LOAD_FAST,
|
||||||
StoreLoadKind::Global | StoreLoadKind::GlobalConst => Opcode::LOAD_GLOBAL,
|
StoreLoadKind::Global | StoreLoadKind::GlobalConst => Opcode::LOAD_GLOBAL,
|
||||||
|
@ -427,10 +582,10 @@ impl CodeGenerator {
|
||||||
Ok(())
|
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
|
let name = self
|
||||||
.local_search(&name, acc_kind)
|
.local_search(ident.inspect(), acc_kind)
|
||||||
.unwrap_or_else(|| self.register_name(name));
|
.unwrap_or_else(|| self.register_name(ident));
|
||||||
let instr = match name.kind {
|
let instr = match name.kind {
|
||||||
StoreLoadKind::Fast => Opcode::STORE_FAST,
|
StoreLoadKind::Fast => Opcode::STORE_FAST,
|
||||||
StoreLoadKind::FastConst => Opcode::ERG_STORE_FAST_IMMUT,
|
StoreLoadKind::FastConst => Opcode::ERG_STORE_FAST_IMMUT,
|
||||||
|
@ -492,11 +647,11 @@ impl CodeGenerator {
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_var_pat(&mut self, pat: &VarPattern, op: &Token) {
|
fn emit_var_pat(&mut self, pat: VarPattern, op: &Token) {
|
||||||
match pat {
|
match pat {
|
||||||
VarPattern::Local(var) => {
|
VarPattern::Ident(ident) => {
|
||||||
if op.category_is(TokenCategory::DefOp) {
|
if op.category_is(TokenCategory::DefOp) {
|
||||||
self.emit_store_instr(var.inspect().clone(), Name);
|
self.emit_store_instr(ident, Name);
|
||||||
} else {
|
} else {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
@ -507,8 +662,8 @@ impl CodeGenerator {
|
||||||
self.write_instr(UNPACK_SEQUENCE);
|
self.write_instr(UNPACK_SEQUENCE);
|
||||||
self.write_arg(a.len() as u8);
|
self.write_arg(a.len() as u8);
|
||||||
self.stack_inc_n(a.len() - 1);
|
self.stack_inc_n(a.len() - 1);
|
||||||
for sig in a.iter() {
|
for sig in a.into_iter() {
|
||||||
self.emit_var_pat(&sig.pat, op);
|
self.emit_var_pat(sig.pat, op);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch_unreachable!()
|
switch_unreachable!()
|
||||||
|
@ -522,17 +677,20 @@ impl CodeGenerator {
|
||||||
self.write_instr(Opcode::LOAD_BUILD_CLASS);
|
self.write_instr(Opcode::LOAD_BUILD_CLASS);
|
||||||
self.write_arg(0);
|
self.write_arg(0);
|
||||||
self.stack_inc();
|
self.stack_inc();
|
||||||
let name = sig.inspect().unwrap();
|
let ident = match sig.pat {
|
||||||
let code = self.codegen_typedef_block(name.clone(), body.block);
|
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(code);
|
||||||
self.emit_load_const(name.clone());
|
self.emit_load_const(ident.inspect().clone());
|
||||||
self.write_instr(Opcode::MAKE_FUNCTION);
|
self.write_instr(Opcode::MAKE_FUNCTION);
|
||||||
self.write_arg(0);
|
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_instr(Opcode::CALL_FUNCTION);
|
||||||
self.write_arg(2);
|
self.write_arg(2);
|
||||||
self.stack_dec_n((1 + 2) - 1);
|
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) {
|
fn emit_var_def(&mut self, sig: VarSignature, mut body: DefBody) {
|
||||||
|
@ -544,11 +702,11 @@ impl CodeGenerator {
|
||||||
} else {
|
} else {
|
||||||
self.codegen_frameless_block(body.block, vec![]);
|
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) {
|
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 mut opcode_flag = 0u8;
|
||||||
let params = self.gen_param_names(&sig.params);
|
let params = self.gen_param_names(&sig.params);
|
||||||
let code = self.codegen_block(body.block, Some(name.clone()), params);
|
let code = self.codegen_block(body.block, Some(name.clone()), params);
|
||||||
|
@ -568,7 +726,7 @@ impl CodeGenerator {
|
||||||
self.write_arg(opcode_flag);
|
self.write_arg(opcode_flag);
|
||||||
// stack_dec: <code obj> + <name> -> <function>
|
// stack_dec: <code obj> + <name> -> <function>
|
||||||
self.stack_dec();
|
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<()> {
|
fn emit_discard_instr(&mut self, mut args: Args) -> CompileResult<()> {
|
||||||
|
@ -687,7 +845,8 @@ impl CodeGenerator {
|
||||||
let mut pop_jump_points = vec![];
|
let mut pop_jump_points = vec![];
|
||||||
match pat {
|
match pat {
|
||||||
ParamPattern::VarName(name) => {
|
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) => {
|
ParamPattern::Lit(lit) => {
|
||||||
self.emit_load_const(ValueObj::from(&lit));
|
self.emit_load_const(ValueObj::from(&lit));
|
||||||
|
@ -735,15 +894,16 @@ impl CodeGenerator {
|
||||||
Ok(pop_jump_points)
|
Ok(pop_jump_points)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_call_name(&mut self, name: Str, mut args: Args) -> CompileResult<()> {
|
fn emit_call_special(&mut self, name: VarName, mut args: Args) -> CompileResult<()> {
|
||||||
match &name[..] {
|
match &name.inspect()[..] {
|
||||||
"assert" => self.emit_assert_instr(args),
|
"assert" => self.emit_assert_instr(args),
|
||||||
"discard" => self.emit_discard_instr(args),
|
"discard" => self.emit_discard_instr(args),
|
||||||
"for" | "for!" => self.emit_for_instr(args),
|
"for" | "for!" => self.emit_for_instr(args),
|
||||||
"if" | "if!" => self.emit_if_instr(args),
|
"if" | "if!" => self.emit_if_instr(args),
|
||||||
"match" | "match!" => self.emit_match_instr(args, true),
|
"match" | "match!" => self.emit_match_instr(args, true),
|
||||||
_ => {
|
_ => {
|
||||||
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);
|
self.errs.push(e);
|
||||||
});
|
});
|
||||||
let argc = args.len();
|
let argc = args.len();
|
||||||
|
@ -772,66 +932,20 @@ impl CodeGenerator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_call_method(&mut self, obj: Expr, name: Str, mut args: Args, is_static: bool) {
|
fn emit_call(&mut self, obj: Expr, method_name: Option<Token>, mut args: Args) {
|
||||||
if is_static {
|
let class = Str::rc(obj.ref_t().name()); // これは必ずmethodのあるクラスになっている
|
||||||
self.emit_load_name_instr(name).unwrap_or_else(|err| {
|
let uniq_obj_name = obj.__name__().map(Str::rc);
|
||||||
|
self.codegen_expr(obj);
|
||||||
|
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);
|
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());
|
|
||||||
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)
|
|
||||||
.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_METHOD);
|
|
||||||
0
|
|
||||||
};
|
|
||||||
self.write_arg(argc as u8);
|
|
||||||
// (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 argc = args.len();
|
||||||
let mut kws = Vec::with_capacity(args.kw_len());
|
let mut kws = Vec::with_capacity(args.kw_len());
|
||||||
while let Some(arg) = args.try_remove_pos(0) {
|
while let Some(arg) = args.try_remove_pos(0) {
|
||||||
|
@ -847,11 +961,11 @@ impl CodeGenerator {
|
||||||
self.write_instr(CALL_FUNCTION_KW);
|
self.write_instr(CALL_FUNCTION_KW);
|
||||||
1
|
1
|
||||||
} else {
|
} else {
|
||||||
self.write_instr(CALL_FUNCTION);
|
self.write_instr(CALL_METHOD);
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
self.write_arg(argc as u8);
|
self.write_arg(argc as u8);
|
||||||
// (1 (name) + argc + kwsc) objects -> 1 return object
|
// (1 (method) + argc + kwsc) input objects -> 1 return object
|
||||||
self.stack_dec_n((1 + argc + kwsc) - 1);
|
self.stack_dec_n((1 + argc + kwsc) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -912,7 +1026,7 @@ impl CodeGenerator {
|
||||||
self.emit_load_const(lit.data);
|
self.emit_load_const(lit.data);
|
||||||
}
|
}
|
||||||
Expr::Accessor(Accessor::Local(l)) => {
|
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| {
|
.unwrap_or_else(|err| {
|
||||||
self.errs.push(err);
|
self.errs.push(err);
|
||||||
});
|
});
|
||||||
|
@ -971,7 +1085,8 @@ impl CodeGenerator {
|
||||||
match &bin.op.kind {
|
match &bin.op.kind {
|
||||||
// l..<r == range(l, r)
|
// l..<r == range(l, r)
|
||||||
TokenKind::RightOpen => {
|
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!(),
|
TokenKind::LeftOpen | TokenKind::Closed | TokenKind::Open => todo!(),
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -1034,22 +1149,15 @@ impl CodeGenerator {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expr::Call(call) => {
|
Expr::Call(call) => match *call.obj {
|
||||||
// TODO: unwrap
|
Expr::Accessor(Accessor::Local(local)) => {
|
||||||
let name = Str::from(obj_name(&call.obj).unwrap());
|
let name = VarName::new(local.name);
|
||||||
match *call.obj {
|
self.emit_call_special(name, call.args).unwrap();
|
||||||
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);
|
|
||||||
}
|
|
||||||
obj => {
|
|
||||||
self.emit_call_callable_obj(obj, call.args);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
obj => {
|
||||||
|
self.emit_call(obj, call.method_name, call.args);
|
||||||
|
}
|
||||||
|
},
|
||||||
// TODO: list comprehension
|
// TODO: list comprehension
|
||||||
Expr::Array(arr) => match arr {
|
Expr::Array(arr) => match arr {
|
||||||
Array::Normal(mut arr) => {
|
Array::Normal(mut arr) => {
|
||||||
|
@ -1082,7 +1190,7 @@ impl CodeGenerator {
|
||||||
/// forブロックなどで使う
|
/// forブロックなどで使う
|
||||||
fn codegen_frameless_block(&mut self, block: Block, params: Vec<Str>) {
|
fn codegen_frameless_block(&mut self, block: Block, params: Vec<Str>) {
|
||||||
for param in params {
|
for param in params {
|
||||||
self.emit_store_instr(param, Name);
|
self.emit_store_instr(Identifier::private(param), Name);
|
||||||
}
|
}
|
||||||
for expr in block.into_iter() {
|
for expr in block.into_iter() {
|
||||||
self.codegen_expr(expr);
|
self.codegen_expr(expr);
|
||||||
|
@ -1106,9 +1214,9 @@ impl CodeGenerator {
|
||||||
));
|
));
|
||||||
let mod_name = self.toplevel_block_codeobj().name.clone();
|
let mod_name = self.toplevel_block_codeobj().name.clone();
|
||||||
self.emit_load_const(mod_name);
|
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_load_const(name);
|
||||||
self.emit_store_instr(Str::from("__qualname__"), Attr);
|
self.emit_store_instr(Identifier::public("__qualname__"), Attr);
|
||||||
// TODO: サブルーチンはT.subという書式でSTORE
|
// TODO: サブルーチンはT.subという書式でSTORE
|
||||||
for expr in block.into_iter() {
|
for expr in block.into_iter() {
|
||||||
self.codegen_expr(expr);
|
self.codegen_expr(expr);
|
||||||
|
@ -1222,7 +1330,8 @@ impl CodeGenerator {
|
||||||
let mut print_point = 0;
|
let mut print_point = 0;
|
||||||
if self.input().is_repl() {
|
if self.input().is_repl() {
|
||||||
print_point = self.cur_block().lasti;
|
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() {
|
for expr in hir.module.into_iter() {
|
||||||
self.codegen_expr(expr);
|
self.codegen_expr(expr);
|
||||||
|
|
|
@ -15,10 +15,10 @@ use erg_common::ty::{
|
||||||
Constraint, FreeKind, HasLevel, IntervalOp, ParamTy, Predicate, RefinementType, SubrKind,
|
Constraint, FreeKind, HasLevel, IntervalOp, ParamTy, Predicate, RefinementType, SubrKind,
|
||||||
SubrType, TyBound, TyParam, TyParamOrdering, Type,
|
SubrType, TyBound, TyParam, TyParamOrdering, Type,
|
||||||
};
|
};
|
||||||
use erg_common::value::ValueObj;
|
use erg_common::value::{ValueObj, Visibility};
|
||||||
use erg_common::Str;
|
use erg_common::Str;
|
||||||
use erg_common::{
|
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 Predicate as Pred;
|
||||||
use TyParamOrdering::*;
|
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::error::{binop_to_dname, unaryop_to_dname, TyCheckError, TyCheckErrors, TyCheckResult};
|
||||||
use crate::eval::Evaluator;
|
use crate::eval::Evaluator;
|
||||||
use crate::hir;
|
use crate::hir;
|
||||||
use crate::varinfo::{Mutability, ParamIdx, VarInfo, VarKind, Visibility};
|
use crate::varinfo::{Mutability, ParamIdx, VarInfo, VarKind};
|
||||||
use Mutability::*;
|
use Mutability::*;
|
||||||
use Visibility::*;
|
use Visibility::*;
|
||||||
|
|
||||||
|
@ -777,30 +777,30 @@ impl Context {
|
||||||
opt_t: Option<Type>,
|
opt_t: Option<Type>,
|
||||||
id: Option<DefId>,
|
id: Option<DefId>,
|
||||||
) -> TyCheckResult<()> {
|
) -> TyCheckResult<()> {
|
||||||
let vis = Private; // TODO:
|
|
||||||
let muty = Mutability::from(&sig.inspect().unwrap()[..]);
|
let muty = Mutability::from(&sig.inspect().unwrap()[..]);
|
||||||
match &sig.pat {
|
match &sig.pat {
|
||||||
ast::VarPattern::Local(v) => {
|
ast::VarPattern::Ident(ident) => {
|
||||||
if sig.t_spec.is_none() && opt_t.is_none() {
|
if sig.t_spec.is_none() && opt_t.is_none() {
|
||||||
Err(TyCheckError::no_type_spec_error(
|
Err(TyCheckError::no_type_spec_error(
|
||||||
line!() as usize,
|
line!() as usize,
|
||||||
sig.loc(),
|
sig.loc(),
|
||||||
self.caused_by(),
|
self.caused_by(),
|
||||||
v.inspect(),
|
ident.inspect(),
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
if self.registered(v.inspect(), v.inspect().is_uppercase()) {
|
if self.registered(ident.inspect(), ident.is_const()) {
|
||||||
return Err(TyCheckError::duplicate_decl_error(
|
return Err(TyCheckError::duplicate_decl_error(
|
||||||
line!() as usize,
|
line!() as usize,
|
||||||
sig.loc(),
|
sig.loc(),
|
||||||
self.caused_by(),
|
self.caused_by(),
|
||||||
v.inspect(),
|
ident.inspect(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
let vis = ident.vis();
|
||||||
let kind = id.map_or(VarKind::Declared, VarKind::Defined);
|
let kind = id.map_or(VarKind::Declared, VarKind::Defined);
|
||||||
let sig_t = self.instantiate_var_sig_t(sig, opt_t, PreRegister)?;
|
let sig_t = self.instantiate_var_sig_t(sig, opt_t, PreRegister)?;
|
||||||
self.decls
|
self.decls
|
||||||
.insert(v.clone(), VarInfo::new(sig_t, muty, vis, kind));
|
.insert(ident.name.clone(), VarInfo::new(sig_t, muty, vis, kind));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -826,7 +826,8 @@ impl Context {
|
||||||
opt_ret_t: Option<Type>,
|
opt_ret_t: Option<Type>,
|
||||||
id: Option<DefId>,
|
id: Option<DefId>,
|
||||||
) -> TyCheckResult<()> {
|
) -> TyCheckResult<()> {
|
||||||
let name = sig.name.inspect();
|
let name = sig.ident.inspect();
|
||||||
|
let vis = sig.ident.vis();
|
||||||
let muty = Mutability::from(&name[..]);
|
let muty = Mutability::from(&name[..]);
|
||||||
let kind = id.map_or(VarKind::Declared, VarKind::Defined);
|
let kind = id.map_or(VarKind::Declared, VarKind::Defined);
|
||||||
if self.registered(name, name.is_uppercase()) {
|
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 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) {
|
if let Some(_decl) = self.decls.remove(name) {
|
||||||
return Err(TyCheckError::duplicate_decl_error(
|
return Err(TyCheckError::duplicate_decl_error(
|
||||||
line!() as usize,
|
line!() as usize,
|
||||||
|
@ -847,7 +848,7 @@ impl Context {
|
||||||
name,
|
name,
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
self.decls.insert(sig.name.clone(), vi);
|
self.decls.insert(sig.ident.name.clone(), vi);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -868,7 +869,6 @@ impl Context {
|
||||||
id: DefId,
|
id: DefId,
|
||||||
) -> TyCheckResult<()> {
|
) -> TyCheckResult<()> {
|
||||||
self.validate_var_sig_t(sig, body_t, Normal)?;
|
self.validate_var_sig_t(sig, body_t, Normal)?;
|
||||||
let vis = Private; // TODO:
|
|
||||||
let muty = Mutability::from(&sig.inspect().unwrap()[..]);
|
let muty = Mutability::from(&sig.inspect().unwrap()[..]);
|
||||||
let (generalized, bounds) = self.generalize_t(body_t.clone());
|
let (generalized, bounds) = self.generalize_t(body_t.clone());
|
||||||
let generalized = if !bounds.is_empty() {
|
let generalized = if !bounds.is_empty() {
|
||||||
|
@ -882,24 +882,24 @@ impl Context {
|
||||||
};
|
};
|
||||||
match &sig.pat {
|
match &sig.pat {
|
||||||
ast::VarPattern::Discard(_token) => Ok(()),
|
ast::VarPattern::Discard(_token) => Ok(()),
|
||||||
ast::VarPattern::Local(v) => {
|
ast::VarPattern::Ident(ident) => {
|
||||||
if self.registered(v.inspect(), v.inspect().is_uppercase()) {
|
if self.registered(ident.inspect(), ident.is_const()) {
|
||||||
Err(TyCheckError::reassign_error(
|
Err(TyCheckError::reassign_error(
|
||||||
line!() as usize,
|
line!() as usize,
|
||||||
v.loc(),
|
ident.loc(),
|
||||||
self.caused_by(),
|
self.caused_by(),
|
||||||
v.inspect(),
|
ident.inspect(),
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
if self.decls.remove(v.inspect()).is_some() {
|
if self.decls.remove(ident.inspect()).is_some() {
|
||||||
// something to do?
|
// something to do?
|
||||||
}
|
}
|
||||||
|
let vis = ident.vis();
|
||||||
let vi = VarInfo::new(generalized, muty, vis, VarKind::Defined(id));
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::VarPattern::Public(_) => todo!(),
|
|
||||||
ast::VarPattern::Array(arr) => {
|
ast::VarPattern::Array(arr) => {
|
||||||
for (elem, inf) in arr.iter().zip(generalized.inner_ts().iter()) {
|
for (elem, inf) in arr.iter().zip(generalized.inner_ts().iter()) {
|
||||||
let id = DefId(get_hash(&(&self.name, elem)));
|
let id = DefId(get_hash(&(&self.name, elem)));
|
||||||
|
@ -1036,12 +1036,12 @@ impl Context {
|
||||||
id: DefId,
|
id: DefId,
|
||||||
body_t: &Type,
|
body_t: &Type,
|
||||||
) -> TyCheckResult<()> {
|
) -> TyCheckResult<()> {
|
||||||
let muty = if sig.name.is_const() {
|
let muty = if sig.ident.is_const() {
|
||||||
Mutability::Const
|
Mutability::Const
|
||||||
} else {
|
} else {
|
||||||
Mutability::Immutable
|
Mutability::Immutable
|
||||||
};
|
};
|
||||||
let name = &sig.name;
|
let name = &sig.ident.name;
|
||||||
// FIXME: constでない関数
|
// FIXME: constでない関数
|
||||||
let t = self
|
let t = self
|
||||||
.get_current_scope_var(name.inspect())
|
.get_current_scope_var(name.inspect())
|
||||||
|
@ -1070,7 +1070,7 @@ impl Context {
|
||||||
name.inspect(),
|
name.inspect(),
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
let sub_t = if sig.name.is_procedural() {
|
let sub_t = if sig.ident.is_procedural() {
|
||||||
Type::proc(
|
Type::proc(
|
||||||
non_default_params.clone(),
|
non_default_params.clone(),
|
||||||
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() {
|
if self.unify(&spec_t, body_t, None, Some(sig.loc())).is_err() {
|
||||||
return Err(TyCheckError::type_mismatch_error(
|
return Err(TyCheckError::type_mismatch_error(
|
||||||
line!() as usize,
|
line!() as usize,
|
||||||
n.loc(),
|
ident.loc(),
|
||||||
self.caused_by(),
|
self.caused_by(),
|
||||||
n.inspect(),
|
ident.inspect(),
|
||||||
&spec_t,
|
&spec_t,
|
||||||
body_t,
|
body_t,
|
||||||
));
|
));
|
||||||
|
@ -2703,7 +2703,7 @@ impl Context {
|
||||||
None,
|
None,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
Ok(if sig.name.is_procedural() {
|
Ok(if sig.ident.is_procedural() {
|
||||||
Type::proc(non_defaults, defaults, return_t)
|
Type::proc(non_defaults, defaults, return_t)
|
||||||
} else {
|
} else {
|
||||||
Type::func(non_defaults, defaults, return_t)
|
Type::func(non_defaults, defaults, return_t)
|
||||||
|
@ -3104,17 +3104,35 @@ impl Context {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 戻り値ではなく、call全体の型を返す
|
/// 戻り値ではなく、call全体の型を返す
|
||||||
/// objは現時点ではAccessorのみ対応
|
fn search_callee_t(
|
||||||
/// 受け入れるobj(Accessor)はcheckしてないハリボテ
|
&self,
|
||||||
fn search_call_t(&self, callee: &hir::Expr, namespace: &Str) -> TyCheckResult<Type> {
|
obj: &hir::Expr,
|
||||||
match callee {
|
method_name: &Option<Token>,
|
||||||
hir::Expr::Accessor(hir::Accessor::Local(local)) => {
|
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)
|
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,17 +3145,18 @@ impl Context {
|
||||||
erg_common::debug_power_assert!(args.len() == 2);
|
erg_common::debug_power_assert!(args.len() == 2);
|
||||||
let symbol = Token::symbol(binop_to_dname(op.inspect()));
|
let symbol = Token::symbol(binop_to_dname(op.inspect()));
|
||||||
let op = hir::Expr::Accessor(hir::Accessor::local(symbol, Type::ASTOmitted));
|
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)
|
||||||
// HACK: dname.loc()はダミーLocationしか返さないので、エラーならop.loc()で上書きする
|
.map_err(|e| {
|
||||||
let core = ErrorCore::new(
|
// HACK: dname.loc()はダミーLocationしか返さないので、エラーならop.loc()で上書きする
|
||||||
e.core.errno,
|
let core = ErrorCore::new(
|
||||||
e.core.kind,
|
e.core.errno,
|
||||||
op.loc(),
|
e.core.kind,
|
||||||
e.core.desc,
|
op.loc(),
|
||||||
e.core.hint,
|
e.core.desc,
|
||||||
);
|
e.core.hint,
|
||||||
TyCheckError::new(core, e.caused_by)
|
);
|
||||||
})
|
TyCheckError::new(core, e.caused_by)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_unaryop_t(
|
pub(crate) fn get_unaryop_t(
|
||||||
|
@ -3149,40 +3168,45 @@ impl Context {
|
||||||
erg_common::debug_power_assert!(args.len() == 1);
|
erg_common::debug_power_assert!(args.len() == 1);
|
||||||
let symbol = Token::symbol(unaryop_to_dname(op.inspect()));
|
let symbol = Token::symbol(unaryop_to_dname(op.inspect()));
|
||||||
let op = hir::Expr::Accessor(hir::Accessor::local(symbol, Type::ASTOmitted));
|
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)
|
||||||
let core = ErrorCore::new(
|
.map_err(|e| {
|
||||||
e.core.errno,
|
let core = ErrorCore::new(
|
||||||
e.core.kind,
|
e.core.errno,
|
||||||
op.loc(),
|
e.core.kind,
|
||||||
e.core.desc,
|
op.loc(),
|
||||||
e.core.hint,
|
e.core.desc,
|
||||||
);
|
e.core.hint,
|
||||||
TyCheckError::new(core, e.caused_by)
|
);
|
||||||
})
|
TyCheckError::new(core, e.caused_by)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_call_t(
|
pub(crate) fn get_call_t(
|
||||||
&self,
|
&self,
|
||||||
callee: &hir::Expr,
|
obj: &hir::Expr,
|
||||||
|
method_name: &Option<Token>,
|
||||||
pos_args: &[hir::PosArg],
|
pos_args: &[hir::PosArg],
|
||||||
kw_args: &[hir::KwArg],
|
kw_args: &[hir::KwArg],
|
||||||
namespace: &Str,
|
namespace: &Str,
|
||||||
) -> TyCheckResult<Type> {
|
) -> TyCheckResult<Type> {
|
||||||
match callee {
|
match obj {
|
||||||
hir::Expr::Accessor(hir::Accessor::Local(local)) if &local.inspect()[..] == "match" => {
|
hir::Expr::Accessor(hir::Accessor::Local(local)) if &local.inspect()[..] == "match" => {
|
||||||
return self.get_match_call_t(pos_args, kw_args)
|
return self.get_match_call_t(pos_args, kw_args)
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
let found = self.search_call_t(callee, namespace)?;
|
let found = self.search_callee_t(obj, method_name, namespace)?;
|
||||||
log!("Found:\ncallee: {callee}\nfound: {found}");
|
log!(
|
||||||
let instance = self.instantiate(found, callee)?;
|
"Found:\ncallee: {obj}{}\nfound: {found}",
|
||||||
|
fmt_option!(pre ".", method_name.as_ref().map(|t| &t.content))
|
||||||
|
);
|
||||||
|
let instance = self.instantiate(found, obj)?;
|
||||||
log!(
|
log!(
|
||||||
"Instantiated:\ninstance: {instance}\npos_args: ({})\nkw_args: ({})",
|
"Instantiated:\ninstance: {instance}\npos_args: ({})\nkw_args: ({})",
|
||||||
fmt_slice(pos_args),
|
fmt_slice(pos_args),
|
||||||
fmt_slice(kw_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}");
|
log!("Substituted:\ninstance: {instance}");
|
||||||
let res = self.deref_tyvar(instance)?;
|
let res = self.deref_tyvar(instance)?;
|
||||||
log!("Derefed:\nres: {res}\n");
|
log!("Derefed:\nres: {res}\n");
|
||||||
|
@ -3195,7 +3219,7 @@ impl Context {
|
||||||
log!("Params Evaluated:\nres: {res}\n");
|
log!("Params Evaluated:\nres: {res}\n");
|
||||||
let res = self.deref_tyvar(res)?;
|
let res = self.deref_tyvar(res)?;
|
||||||
log!("Derefed (2):\nres: {res}\n");
|
log!("Derefed (2):\nres: {res}\n");
|
||||||
self.propagate(&res, callee)?;
|
self.propagate(&res, obj)?;
|
||||||
log!("Propagated:\nres: {res}\n");
|
log!("Propagated:\nres: {res}\n");
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
@ -4150,6 +4174,7 @@ impl Context {
|
||||||
if name.len() <= 1 {
|
if name.len() <= 1 {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
// TODO: add `.decls`
|
||||||
let most_similar_name = self
|
let most_similar_name = self
|
||||||
.params
|
.params
|
||||||
.iter()
|
.iter()
|
||||||
|
|
|
@ -5,11 +5,12 @@
|
||||||
use erg_common::color::{GREEN, RESET};
|
use erg_common::color::{GREEN, RESET};
|
||||||
use erg_common::log;
|
use erg_common::log;
|
||||||
use erg_common::traits::Stream;
|
use erg_common::traits::Stream;
|
||||||
|
use erg_common::value::Visibility;
|
||||||
use erg_common::Str;
|
use erg_common::Str;
|
||||||
|
|
||||||
use crate::error::{EffectError, EffectErrors, EffectResult};
|
use crate::error::{EffectError, EffectErrors, EffectResult};
|
||||||
use crate::hir::{Accessor, Def, Expr, Signature, HIR};
|
use crate::hir::{Accessor, Def, Expr, Signature, HIR};
|
||||||
use crate::varinfo::Visibility;
|
|
||||||
use Visibility::*;
|
use Visibility::*;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -85,7 +86,7 @@ impl SideEffectChecker {
|
||||||
(Str::ever("::<instant>"), Private)
|
(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);
|
self.path_stack.push(name_and_vis);
|
||||||
// TODO: support raw identifier (``)
|
// TODO: support raw identifier (``)
|
||||||
|
|
|
@ -5,9 +5,9 @@ use erg_common::rccell::RcCell;
|
||||||
use erg_common::set::Set;
|
use erg_common::set::Set;
|
||||||
use erg_common::traits::Stream;
|
use erg_common::traits::Stream;
|
||||||
use erg_common::ty::{OpKind, Predicate, SubrKind, TyBound, TyParam, Type};
|
use erg_common::ty::{OpKind, Predicate, SubrKind, TyBound, TyParam, Type};
|
||||||
use erg_common::value::ValueObj;
|
use erg_common::value::{Field, ValueObj};
|
||||||
use erg_common::Str;
|
|
||||||
use erg_common::{fn_name, set};
|
use erg_common::{fn_name, set};
|
||||||
|
use erg_common::{RcArray, Str};
|
||||||
use OpKind::*;
|
use OpKind::*;
|
||||||
|
|
||||||
use erg_parser::ast::*;
|
use erg_parser::ast::*;
|
||||||
|
@ -181,6 +181,46 @@ impl Evaluator {
|
||||||
None
|
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)を評価する
|
// ConstExprを評価するのではなく、コンパイル時関数の式(AST上ではただのExpr)を評価する
|
||||||
// コンパイル時評価できないならNoneを返す
|
// コンパイル時評価できないならNoneを返す
|
||||||
pub(crate) fn eval_const_expr(&self, expr: &Expr, ctx: &Context) -> Option<ValueObj> {
|
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::UnaryOp(unary) => self.eval_const_unary(unary),
|
||||||
Expr::Call(call) => self.eval_const_call(call, ctx),
|
Expr::Call(call) => self.eval_const_call(call, ctx),
|
||||||
Expr::Def(def) => self.eval_const_def(def),
|
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}"),
|
other => todo!("{other}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ use std::fmt;
|
||||||
use erg_common::error::Location;
|
use erg_common::error::Location;
|
||||||
use erg_common::traits::{HasType, Locational, NestedDisplay, Stream};
|
use erg_common::traits::{HasType, Locational, NestedDisplay, Stream};
|
||||||
use erg_common::ty::{Constraint, TyParam, Type};
|
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::Str;
|
||||||
use erg_common::{
|
use erg_common::{
|
||||||
impl_display_for_enum, impl_display_from_nested, impl_locational, impl_locational_for_enum,
|
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,
|
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 erg_parser::token::{Token, TokenKind};
|
||||||
|
|
||||||
use crate::error::readable_name;
|
use crate::error::readable_name;
|
||||||
|
@ -676,9 +676,9 @@ impl UnaryOp {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Call {
|
pub struct Call {
|
||||||
pub obj: Box<Expr>,
|
pub obj: Box<Expr>,
|
||||||
|
pub method_name: Option<Token>,
|
||||||
pub args: Args,
|
pub args: Args,
|
||||||
/// 全体の型、e.g. `abs(-1)` -> `Neg -> Nat`
|
/// 全体の型(引数自体の型は関係ない)、e.g. `abs(-1)` -> `Neg -> Nat`
|
||||||
/// necessary for mangling
|
|
||||||
pub sig_t: Type,
|
pub sig_t: Type,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -725,9 +725,10 @@ impl Locational for Call {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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 {
|
Self {
|
||||||
obj: Box::new(obj),
|
obj: Box::new(obj),
|
||||||
|
method_name,
|
||||||
args,
|
args,
|
||||||
sig_t,
|
sig_t,
|
||||||
}
|
}
|
||||||
|
@ -808,34 +809,38 @@ impl VarSignature {
|
||||||
pub fn inspect(&self) -> Option<&Str> {
|
pub fn inspect(&self) -> Option<&Str> {
|
||||||
self.pat.inspect()
|
self.pat.inspect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn vis(&self) -> Visibility {
|
||||||
|
self.pat.vis()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct SubrSignature {
|
pub struct SubrSignature {
|
||||||
pub name: VarName,
|
pub ident: Identifier,
|
||||||
pub params: Params,
|
pub params: Params,
|
||||||
pub t: Type,
|
pub t: Type,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for SubrSignature {
|
impl fmt::Display for SubrSignature {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
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 {
|
impl Locational for SubrSignature {
|
||||||
fn loc(&self) -> Location {
|
fn loc(&self) -> Location {
|
||||||
Location::concat(&self.name, &self.params)
|
Location::concat(&self.ident, &self.params)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SubrSignature {
|
impl SubrSignature {
|
||||||
pub const fn new(name: VarName, params: Params, t: Type) -> Self {
|
pub const fn new(ident: Identifier, params: Params, t: Type) -> Self {
|
||||||
Self { name, params, t }
|
Self { ident, params, t }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_procedural(&self) -> bool {
|
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 {
|
pub fn is_const(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Self::Var(v) => v.pat.is_const(),
|
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 {
|
pub fn is_procedural(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Self::Var(v) => v.pat.is_procedural(),
|
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に)定義
|
//! 組み込みオブジェクトの型情報を(Contextに)定義
|
||||||
use erg_common::ty::type_constrs::*;
|
use erg_common::ty::type_constrs::*;
|
||||||
use erg_common::ty::{TyParam, Type};
|
use erg_common::ty::{TyParam, Type};
|
||||||
use erg_common::value::ValueObj;
|
use erg_common::value::{ValueObj, Visibility};
|
||||||
use erg_common::Str;
|
use erg_common::Str;
|
||||||
use erg_common::{debug_power_assert, set};
|
use erg_common::{debug_power_assert, set};
|
||||||
use ParamSpec as PS;
|
use ParamSpec as PS;
|
||||||
|
@ -12,7 +12,7 @@ use Type::*;
|
||||||
use erg_parser::ast::VarName;
|
use erg_parser::ast::VarName;
|
||||||
|
|
||||||
use crate::context::{ConstTemplate, Context, ContextKind, DefaultInfo, ParamSpec};
|
use crate::context::{ConstTemplate, Context, ContextKind, DefaultInfo, ParamSpec};
|
||||||
use crate::varinfo::{Mutability, VarInfo, VarKind, Visibility};
|
use crate::varinfo::{Mutability, VarInfo, VarKind};
|
||||||
use DefaultInfo::*;
|
use DefaultInfo::*;
|
||||||
use Mutability::*;
|
use Mutability::*;
|
||||||
use VarKind::*;
|
use VarKind::*;
|
||||||
|
|
|
@ -6,7 +6,7 @@ use erg_common::error::Location;
|
||||||
use erg_common::get_hash;
|
use erg_common::get_hash;
|
||||||
use erg_common::traits::{HasType, Locational, Stream};
|
use erg_common::traits::{HasType, Locational, Stream};
|
||||||
use erg_common::ty::{ParamTy, TyParam, Type};
|
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_common::{fn_name, log, switch_lang};
|
||||||
|
|
||||||
use erg_parser::ast;
|
use erg_parser::ast;
|
||||||
|
@ -16,7 +16,6 @@ use crate::context::{Context, ContextKind, RegistrationMode};
|
||||||
use crate::error::{LowerError, LowerErrors, LowerResult, LowerWarnings};
|
use crate::error::{LowerError, LowerErrors, LowerResult, LowerWarnings};
|
||||||
use crate::hir;
|
use crate::hir;
|
||||||
use crate::hir::HIR;
|
use crate::hir::HIR;
|
||||||
use crate::varinfo::Visibility;
|
|
||||||
use Visibility::*;
|
use Visibility::*;
|
||||||
|
|
||||||
/// Singleton that checks types of an AST, and convert (lower) it into a HIR
|
/// 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 obj = self.lower_expr(*call.obj, false)?;
|
||||||
let t = self
|
let t = self.ctx.get_call_t(
|
||||||
.ctx
|
&obj,
|
||||||
.get_call_t(&obj, &hir_args.pos_args, &hir_args.kw_args, &self.ctx.name)?;
|
&call.method_name,
|
||||||
Ok(hir::Call::new(obj, hir_args, t))
|
&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> {
|
fn lower_lambda(&mut self, lambda: ast::Lambda) -> LowerResult<hir::Lambda> {
|
||||||
|
@ -361,13 +364,13 @@ impl ASTLowerer {
|
||||||
.assign_var(&sig, id, found_body_t)?;
|
.assign_var(&sig, id, found_body_t)?;
|
||||||
match block.first().unwrap() {
|
match block.first().unwrap() {
|
||||||
hir::Expr::Call(call) => {
|
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() {
|
if call.is_import_call() {
|
||||||
self.ctx
|
self.ctx
|
||||||
.outer
|
.outer
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.import_mod(name, &call.args.pos_args.first().unwrap().expr)?;
|
.import_mod(&ident.name, &call.args.pos_args.first().unwrap().expr)?;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
todo!()
|
todo!()
|
||||||
|
@ -392,9 +395,9 @@ impl ASTLowerer {
|
||||||
.outer
|
.outer
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.get_current_scope_var(sig.name.inspect())
|
.get_current_scope_var(sig.ident.inspect())
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
log!("{}\n", sig.name.inspect());
|
log!("{}\n", sig.ident.inspect());
|
||||||
log!("{}\n", self.ctx.outer.as_ref().unwrap());
|
log!("{}\n", self.ctx.outer.as_ref().unwrap());
|
||||||
panic!()
|
panic!()
|
||||||
}) // FIXME: or instantiate
|
}) // FIXME: or instantiate
|
||||||
|
@ -406,7 +409,7 @@ impl ASTLowerer {
|
||||||
let found_body_t = block.ref_t();
|
let found_body_t = block.ref_t();
|
||||||
let expect_body_t = t.return_t().unwrap();
|
let expect_body_t = t.return_t().unwrap();
|
||||||
if let Err(e) =
|
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);
|
self.errs.push(e);
|
||||||
}
|
}
|
||||||
|
@ -416,7 +419,7 @@ impl ASTLowerer {
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.assign_subr(&sig, id, found_body_t)?;
|
.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);
|
let body = hir::DefBody::new(body.op, block, body.id);
|
||||||
Ok(hir::Def::new(hir::Signature::Subr(sig), body))
|
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::set::Set;
|
||||||
use erg_common::traits::{HasType, Locational, Stream};
|
use erg_common::traits::{HasType, Locational, Stream};
|
||||||
use erg_common::ty::{ArgsOwnership, Ownership};
|
use erg_common::ty::{ArgsOwnership, Ownership};
|
||||||
|
use erg_common::value::Visibility;
|
||||||
use erg_common::Str;
|
use erg_common::Str;
|
||||||
|
|
||||||
use crate::error::{OwnershipError, OwnershipErrors, OwnershipResult};
|
use crate::error::{OwnershipError, OwnershipErrors, OwnershipResult};
|
||||||
use crate::hir::{self, Accessor, Array, Block, Def, Expr, Signature, HIR};
|
use crate::hir::{self, Accessor, Array, Block, Def, Expr, Signature, HIR};
|
||||||
use crate::varinfo::Visibility;
|
|
||||||
use Visibility::*;
|
use Visibility::*;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
@ -84,19 +84,17 @@ impl OwnershipChecker {
|
||||||
match expr {
|
match expr {
|
||||||
Expr::Def(def) => {
|
Expr::Def(def) => {
|
||||||
self.define(def);
|
self.define(def);
|
||||||
let name_and_vis = match &def.sig {
|
let name = match &def.sig {
|
||||||
Signature::Var(var) =>
|
Signature::Var(var) => {
|
||||||
// TODO: visibility
|
|
||||||
{
|
|
||||||
if let Some(name) = var.inspect() {
|
if let Some(name) = var.inspect() {
|
||||||
(name.clone(), Private)
|
name.clone()
|
||||||
} else {
|
} 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
|
self.dict
|
||||||
.insert(Str::from(self.full_path()), LocalVars::default());
|
.insert(Str::from(self.full_path()), LocalVars::default());
|
||||||
self.check_block(&def.body.block);
|
self.check_block(&def.body.block);
|
||||||
|
@ -239,7 +237,7 @@ impl OwnershipChecker {
|
||||||
Signature::Subr(sig) => {
|
Signature::Subr(sig) => {
|
||||||
self.current_scope()
|
self.current_scope()
|
||||||
.alive_vars
|
.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::traits::HasType;
|
||||||
use erg_common::ty::Type;
|
use erg_common::ty::Type;
|
||||||
|
use erg_common::value::Visibility;
|
||||||
|
use Visibility::*;
|
||||||
|
|
||||||
use erg_parser::ast::DefId;
|
use erg_parser::ast::DefId;
|
||||||
|
|
||||||
|
@ -32,24 +34,6 @@ impl Mutability {
|
||||||
|
|
||||||
use 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.
|
/// e.g.
|
||||||
/// ```erg
|
/// ```erg
|
||||||
/// K(T, [U, V]) = ...
|
/// K(T, [U, V]) = ...
|
||||||
|
|
|
@ -6,7 +6,7 @@ use erg_common::error::Location;
|
||||||
use erg_common::set::Set as HashSet;
|
use erg_common::set::Set as HashSet;
|
||||||
use erg_common::traits::{Locational, NestedDisplay, Stream};
|
use erg_common::traits::{Locational, NestedDisplay, Stream};
|
||||||
use erg_common::ty::SubrKind;
|
use erg_common::ty::SubrKind;
|
||||||
use erg_common::value::ValueObj;
|
use erg_common::value::{ValueObj, Visibility};
|
||||||
use erg_common::Str;
|
use erg_common::Str;
|
||||||
use erg_common::{
|
use erg_common::{
|
||||||
fmt_option, fmt_vec, impl_display_for_enum, impl_display_for_single_struct,
|
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)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct Record {
|
pub struct Record {
|
||||||
l_brace: Token,
|
l_brace: Token,
|
||||||
|
@ -732,12 +738,15 @@ impl UnaryOp {
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct Call {
|
pub struct Call {
|
||||||
pub obj: Box<Expr>,
|
pub obj: Box<Expr>,
|
||||||
|
pub method_name: Option<Token>,
|
||||||
pub args: Args,
|
pub args: Args,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NestedDisplay for Call {
|
impl NestedDisplay for Call {
|
||||||
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, level: usize) -> std::fmt::Result {
|
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)
|
self.args.fmt_nest(f, level + 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -755,9 +764,10 @@ impl Locational for Call {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Call {
|
impl Call {
|
||||||
pub fn new(obj: Expr, args: Args) -> Self {
|
pub fn new(obj: Expr, method_name: Option<Token>, args: Args) -> Self {
|
||||||
Self {
|
Self {
|
||||||
obj: Box::new(obj),
|
obj: Box::new(obj),
|
||||||
|
method_name,
|
||||||
args,
|
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)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct VarArrayPattern {
|
pub struct VarArrayPattern {
|
||||||
l_sqbr: Token,
|
l_sqbr: Token,
|
||||||
|
@ -1708,8 +1779,7 @@ impl VarRecordPattern {
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub enum VarPattern {
|
pub enum VarPattern {
|
||||||
Discard(Token),
|
Discard(Token),
|
||||||
Local(VarName), // x
|
Ident(Identifier),
|
||||||
Public(VarName), // .x
|
|
||||||
/// e.g. `[x, y, z]` of `[x, y, z] = [1, 2, 3]`
|
/// e.g. `[x, y, z]` of `[x, y, z] = [1, 2, 3]`
|
||||||
Array(VarArrayPattern),
|
Array(VarArrayPattern),
|
||||||
/// e.g. `(x, y, z)` of `(x, y, z) = (1, 2, 3)`
|
/// 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 {
|
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Self::Discard(_) => write!(f, "_"),
|
Self::Discard(_) => write!(f, "_"),
|
||||||
Self::Local(n) => write!(f, "{}", n),
|
Self::Ident(ident) => write!(f, "{}", ident),
|
||||||
Self::Public(n) => write!(f, ".{}", n),
|
|
||||||
Self::Array(a) => write!(f, "{}", a),
|
Self::Array(a) => write!(f, "{}", a),
|
||||||
Self::Tuple(t) => write!(f, "{}", t),
|
Self::Tuple(t) => write!(f, "{}", t),
|
||||||
Self::Record(r) => write!(f, "{}", r),
|
Self::Record(r) => write!(f, "{}", r),
|
||||||
|
@ -1732,19 +1801,19 @@ impl NestedDisplay for VarPattern {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_display_from_nested!(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 {
|
impl VarPattern {
|
||||||
pub const fn inspect(&self) -> Option<&Str> {
|
pub const fn inspect(&self) -> Option<&Str> {
|
||||||
match self {
|
match self {
|
||||||
Self::Local(n) | Self::Public(n) => Some(n.inspect()),
|
Self::Ident(ident) => Some(ident.inspect()),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn inspects(&self) -> Vec<&Str> {
|
pub fn inspects(&self) -> Vec<&Str> {
|
||||||
match self {
|
match self {
|
||||||
Self::Local(n) | Self::Public(n) => vec![n.inspect()],
|
Self::Ident(ident) => vec![ident.inspect()],
|
||||||
Self::Array(VarArrayPattern { elems, .. })
|
Self::Array(VarArrayPattern { elems, .. })
|
||||||
| Self::Tuple(VarTuplePattern { elems, .. })
|
| Self::Tuple(VarTuplePattern { elems, .. })
|
||||||
| Self::Record(VarRecordPattern { elems, .. }) => {
|
| Self::Record(VarRecordPattern { elems, .. }) => {
|
||||||
|
@ -1757,7 +1826,7 @@ impl VarPattern {
|
||||||
// _!(...) = ... is invalid
|
// _!(...) = ... is invalid
|
||||||
pub fn is_procedural(&self) -> bool {
|
pub fn is_procedural(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Self::Local(n) | Self::Public(n) => n.is_procedural(),
|
Self::Ident(ident) => ident.is_procedural(),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1765,10 +1834,18 @@ impl VarPattern {
|
||||||
// _ = (type block) is invalid
|
// _ = (type block) is invalid
|
||||||
pub fn is_const(&self) -> bool {
|
pub fn is_const(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Self::Local(n) | Self::Public(n) => n.is_const(),
|
Self::Ident(ident) => ident.is_const(),
|
||||||
_ => false,
|
_ => 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)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
|
@ -1807,6 +1884,10 @@ impl VarSignature {
|
||||||
pub fn is_const(&self) -> bool {
|
pub fn is_const(&self) -> bool {
|
||||||
self.pat.is_const()
|
self.pat.is_const()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const fn vis(&self) -> Visibility {
|
||||||
|
self.pat.vis()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
|
@ -2066,7 +2147,7 @@ impl Params {
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct SubrSignature {
|
pub struct SubrSignature {
|
||||||
pub decorators: HashSet<Decorator>,
|
pub decorators: HashSet<Decorator>,
|
||||||
pub name: VarName,
|
pub ident: Identifier,
|
||||||
pub params: Params,
|
pub params: Params,
|
||||||
pub return_t_spec: Option<TypeSpec>,
|
pub return_t_spec: Option<TypeSpec>,
|
||||||
pub bounds: TypeBoundSpecs,
|
pub bounds: TypeBoundSpecs,
|
||||||
|
@ -2078,7 +2159,7 @@ impl NestedDisplay for SubrSignature {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"{}{}{}",
|
"{}{}{}",
|
||||||
self.name,
|
self.ident,
|
||||||
self.params,
|
self.params,
|
||||||
fmt_option!(pre ": ", self.return_t_spec)
|
fmt_option!(pre ": ", self.return_t_spec)
|
||||||
)
|
)
|
||||||
|
@ -2086,7 +2167,7 @@ impl NestedDisplay for SubrSignature {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"{}|{}|{}{}",
|
"{}|{}|{}{}",
|
||||||
self.name,
|
self.ident,
|
||||||
self.bounds,
|
self.bounds,
|
||||||
self.params,
|
self.params,
|
||||||
fmt_option!(pre ": ", self.return_t_spec)
|
fmt_option!(pre ": ", self.return_t_spec)
|
||||||
|
@ -2100,11 +2181,11 @@ impl_display_from_nested!(SubrSignature);
|
||||||
impl Locational for SubrSignature {
|
impl Locational for SubrSignature {
|
||||||
fn loc(&self) -> Location {
|
fn loc(&self) -> Location {
|
||||||
if !self.bounds.is_empty() {
|
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 {
|
} else if let Some(return_t) = &self.return_t_spec {
|
||||||
Location::concat(&self.name, return_t)
|
Location::concat(&self.ident, return_t)
|
||||||
} else {
|
} else {
|
||||||
Location::concat(&self.name, &self.params)
|
Location::concat(&self.ident, &self.params)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2112,14 +2193,14 @@ impl Locational for SubrSignature {
|
||||||
impl SubrSignature {
|
impl SubrSignature {
|
||||||
pub const fn new(
|
pub const fn new(
|
||||||
decorators: HashSet<Decorator>,
|
decorators: HashSet<Decorator>,
|
||||||
name: VarName,
|
ident: Identifier,
|
||||||
params: Params,
|
params: Params,
|
||||||
return_t: Option<TypeSpec>,
|
return_t: Option<TypeSpec>,
|
||||||
bounds: TypeBoundSpecs,
|
bounds: TypeBoundSpecs,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
decorators,
|
decorators,
|
||||||
name,
|
ident,
|
||||||
params,
|
params,
|
||||||
return_t_spec: return_t,
|
return_t_spec: return_t,
|
||||||
bounds,
|
bounds,
|
||||||
|
@ -2127,7 +2208,11 @@ impl SubrSignature {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_const(&self) -> bool {
|
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 {
|
impl Signature {
|
||||||
pub fn name_as_str(&self) -> &Str {
|
pub fn name_as_str(&self) -> &Str {
|
||||||
match self {
|
match self {
|
||||||
Self::Var(v) => v.pat.inspect().unwrap(),
|
Self::Var(var) => var.pat.inspect().unwrap(),
|
||||||
Self::Subr(s) => s.name.inspect(),
|
Self::Subr(subr) => subr.ident.inspect(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn name(&self) -> Option<&VarName> {
|
pub fn ident(&self) -> Option<&Identifier> {
|
||||||
match self {
|
match self {
|
||||||
Self::Var(v) => {
|
Self::Var(var) => {
|
||||||
if let VarPattern::Local(v) = &v.pat {
|
if let VarPattern::Ident(ident) = &var.pat {
|
||||||
Some(v)
|
Some(ident)
|
||||||
} else {
|
} else {
|
||||||
None
|
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 {
|
pub fn is_const(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Self::Var(v) => v.is_const(),
|
Self::Var(var) => var.is_const(),
|
||||||
Self::Subr(s) => s.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()
|
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 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 op = Token::from_str(TokenKind::FuncArrow, "->");
|
||||||
let (call, return_t_spec) = if previous.body.block.len() == 1
|
let (call, return_t_spec) = if previous.body.block.len() == 1
|
||||||
&& previous.body.block.first().unwrap().is_match_call()
|
&& previous.body.block.first().unwrap().is_match_call()
|
||||||
|
@ -104,7 +104,7 @@ impl Desugarer {
|
||||||
vec![],
|
vec![],
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
let call = Call::new(match_symbol, args);
|
let call = Call::new(match_symbol, None, args);
|
||||||
(call, return_t_spec)
|
(call, return_t_spec)
|
||||||
};
|
};
|
||||||
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::Local:(_))).inspect();
|
||||||
|
|
|
@ -515,7 +515,7 @@ impl Parser {
|
||||||
return Ok(Signature::Var(var));
|
return Ok(Signature::Var(var));
|
||||||
}
|
}
|
||||||
let decorators = self.opt_reduce_decorators().map_err(|_| self.stack_dec())?;
|
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 |...|
|
// TODO: parse bounds |...|
|
||||||
let bounds = TypeBoundSpecs::empty();
|
let bounds = TypeBoundSpecs::empty();
|
||||||
if self.cur_is(VBar) {
|
if self.cur_is(VBar) {
|
||||||
|
@ -534,7 +534,7 @@ impl Parser {
|
||||||
};
|
};
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
Ok(Signature::Subr(SubrSignature::new(
|
Ok(Signature::Subr(SubrSignature::new(
|
||||||
decorators, name, params, t_spec, bounds,
|
decorators, ident, params, t_spec, bounds,
|
||||||
)))
|
)))
|
||||||
} else {
|
} else {
|
||||||
if !bounds.is_empty() {
|
if !bounds.is_empty() {
|
||||||
|
@ -554,7 +554,7 @@ impl Parser {
|
||||||
self.errs.push(err);
|
self.errs.push(err);
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
let t_spec = if name.is_const() {
|
let t_spec = if ident.is_const() {
|
||||||
if self.cur_is(SubtypeOf) {
|
if self.cur_is(SubtypeOf) {
|
||||||
self.skip();
|
self.skip();
|
||||||
Some(self.try_reduce_type_spec().map_err(|_| self.stack_dec())?)
|
Some(self.try_reduce_type_spec().map_err(|_| self.stack_dec())?)
|
||||||
|
@ -568,12 +568,10 @@ impl Parser {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
let var_pat = if opt_dot.is_some() {
|
Ok(Signature::Var(VarSignature::new(
|
||||||
VarPattern::Public(name)
|
VarPattern::Ident(ident),
|
||||||
} else {
|
t_spec,
|
||||||
VarPattern::Local(name)
|
)))
|
||||||
};
|
|
||||||
Ok(Signature::Var(VarSignature::new(var_pat, t_spec)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -906,14 +904,9 @@ impl Parser {
|
||||||
debug_call_info!(self);
|
debug_call_info!(self);
|
||||||
match self.peek() {
|
match self.peek() {
|
||||||
Some(t) if t.is(Symbol) => {
|
Some(t) if t.is(Symbol) => {
|
||||||
let (opt_dot, varname) = self.try_reduce_name().map_err(|_| self.stack_dec())?;
|
let ident = self.try_reduce_ident().map_err(|_| self.stack_dec())?;
|
||||||
let var_pat = if let Some(_dot) = opt_dot {
|
|
||||||
VarPattern::Public(varname)
|
|
||||||
} else {
|
|
||||||
VarPattern::Local(varname)
|
|
||||||
};
|
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
Ok(var_pat)
|
Ok(VarPattern::Ident(ident))
|
||||||
}
|
}
|
||||||
Some(t) if t.is(UBar) => {
|
Some(t) if t.is(UBar) => {
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
|
@ -968,8 +961,8 @@ impl Parser {
|
||||||
debug_call_info!(self);
|
debug_call_info!(self);
|
||||||
match self.peek() {
|
match self.peek() {
|
||||||
Some(t) if t.is(Symbol) => {
|
Some(t) if t.is(Symbol) => {
|
||||||
let (opt_dot, varname) = self.try_reduce_name().map_err(|_| self.stack_dec())?;
|
let ident = self.try_reduce_ident().map_err(|_| self.stack_dec())?;
|
||||||
if let Some(dot) = opt_dot {
|
if let Some(dot) = &ident.dot {
|
||||||
let loc = dot.loc();
|
let loc = dot.loc();
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
self.errs.push(ParseError::syntax_error(
|
self.errs.push(ParseError::syntax_error(
|
||||||
|
@ -986,7 +979,7 @@ impl Parser {
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
Ok(ParamPattern::VarName(varname))
|
Ok(ParamPattern::VarName(ident.name))
|
||||||
}
|
}
|
||||||
Some(t) if t.is(UBar) => {
|
Some(t) if t.is(UBar) => {
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
|
@ -1000,8 +993,8 @@ impl Parser {
|
||||||
}
|
}
|
||||||
Some(t) if t.is(Spread) => {
|
Some(t) if t.is(Spread) => {
|
||||||
self.skip();
|
self.skip();
|
||||||
let (opt_dot, varname) = self.try_reduce_name().map_err(|_| self.stack_dec())?;
|
let ident = self.try_reduce_ident().map_err(|_| self.stack_dec())?;
|
||||||
if let Some(dot) = opt_dot {
|
if let Some(dot) = &ident.dot {
|
||||||
let loc = dot.loc();
|
let loc = dot.loc();
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
self.errs.push(ParseError::syntax_error(
|
self.errs.push(ParseError::syntax_error(
|
||||||
|
@ -1018,7 +1011,7 @@ impl Parser {
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
Ok(ParamPattern::VarArgsName(varname))
|
Ok(ParamPattern::VarArgsName(ident.name))
|
||||||
}
|
}
|
||||||
Some(t) if t.is(LSqBr) => {
|
Some(t) if t.is(LSqBr) => {
|
||||||
let l_sqbr = self.lpop();
|
let l_sqbr = self.lpop();
|
||||||
|
@ -1162,11 +1155,11 @@ impl Parser {
|
||||||
debug_call_info!(self);
|
debug_call_info!(self);
|
||||||
if self.cur_is(Symbol) && self.nth_is(1, Colon) {
|
if self.cur_is(Symbol) && self.nth_is(1, Colon) {
|
||||||
// TODO: handle `.`
|
// 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();
|
self.skip();
|
||||||
let typ = self.try_reduce_type_spec().map_err(|_| self.stack_dec())?;
|
let typ = self.try_reduce_type_spec().map_err(|_| self.stack_dec())?;
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
Ok(ParamTySpec::new(Some(name.into_token()), typ))
|
Ok(ParamTySpec::new(Some(ident.name.into_token()), typ))
|
||||||
} else {
|
} else {
|
||||||
let ty_spec = self.try_reduce_type_spec().map_err(|_| self.stack_dec())?;
|
let ty_spec = self.try_reduce_type_spec().map_err(|_| self.stack_dec())?;
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
|
@ -1228,15 +1221,15 @@ impl Parser {
|
||||||
debug_call_info!(self);
|
debug_call_info!(self);
|
||||||
match self.peek() {
|
match self.peek() {
|
||||||
Some(t) if t.is(Symbol) => {
|
Some(t) if t.is(Symbol) => {
|
||||||
// TODO: handle dot
|
// TODO: handle dot (`.`)
|
||||||
let (_opt_dot, name) = self.try_reduce_name().map_err(|_| self.stack_dec())?;
|
let ident = self.try_reduce_ident().map_err(|_| self.stack_dec())?;
|
||||||
if let Some(res) = self.opt_reduce_args() {
|
if let Some(res) = self.opt_reduce_args() {
|
||||||
let args = self.validate_const_args(res?)?;
|
let args = self.validate_const_args(res?)?;
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
Ok(SimpleTypeSpec::new(name, args))
|
Ok(SimpleTypeSpec::new(ident.name, args))
|
||||||
} else {
|
} else {
|
||||||
self.level -= 1;
|
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);
|
self.errs.push(err);
|
||||||
return Err(());
|
return Err(());
|
||||||
};
|
};
|
||||||
let acc = Accessor::attr(obj, Local::new(symbol));
|
if let Some(args) = self
|
||||||
if let Ok(args) = self.try_reduce_args() {
|
.opt_reduce_args()
|
||||||
let call = Call::new(Expr::Accessor(acc), args);
|
.transpose()
|
||||||
|
.map_err(|_| self.stack_dec())?
|
||||||
|
{
|
||||||
|
let call = Call::new(obj, Some(symbol), args);
|
||||||
stack.push(ExprOrOp::Expr(Expr::Call(call)));
|
stack.push(ExprOrOp::Expr(Expr::Call(call)));
|
||||||
} else {
|
} else {
|
||||||
|
let acc = Accessor::attr(obj, Local::new(symbol));
|
||||||
stack.push(ExprOrOp::Expr(Expr::Accessor(acc)));
|
stack.push(ExprOrOp::Expr(Expr::Accessor(acc)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1864,7 +1861,12 @@ impl Parser {
|
||||||
let acc = self.try_reduce_acc().map_err(|_| self.stack_dec())?;
|
let acc = self.try_reduce_acc().map_err(|_| self.stack_dec())?;
|
||||||
if let Some(res) = self.opt_reduce_args() {
|
if let Some(res) = self.opt_reduce_args() {
|
||||||
let args = res.map_err(|_| self.stack_dec())?;
|
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;
|
self.level -= 1;
|
||||||
Ok(Expr::Call(call))
|
Ok(Expr::Call(call))
|
||||||
} else {
|
} else {
|
||||||
|
@ -1978,9 +1980,8 @@ impl Parser {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// option: Dot(`.`)
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn try_reduce_name(&mut self) -> ParseResult<(Option<Token>, VarName)> {
|
fn try_reduce_ident(&mut self) -> ParseResult<Identifier> {
|
||||||
debug_call_info!(self);
|
debug_call_info!(self);
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
match self.peek() {
|
match self.peek() {
|
||||||
|
@ -1988,9 +1989,13 @@ impl Parser {
|
||||||
let dot = self.lpop();
|
let dot = self.lpop();
|
||||||
// TODO:
|
// TODO:
|
||||||
assert!(self.cur_category_is(TC::Symbol));
|
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!());
|
let err = self.skip_and_throw_syntax_err(caused_by!());
|
||||||
self.errs.push(err);
|
self.errs.push(err);
|
||||||
|
|
|
@ -4,3 +4,4 @@ fib 1 = 1
|
||||||
fib(n: Nat): Nat = fib(n-1) + fib(n-2)
|
fib(n: Nat): Nat = fib(n-1) + fib(n-2)
|
||||||
|
|
||||||
assert fib(10) == 55
|
assert fib(10) == 55
|
||||||
|
print! fib 10
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue