mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-29 12:24:45 +00:00
Impl: auto generating of new
This commit is contained in:
parent
e021ce71a7
commit
5029d71cbe
13 changed files with 401 additions and 88 deletions
|
@ -488,8 +488,22 @@ pub trait ErrorDisplay {
|
||||||
}
|
}
|
||||||
res + RESET
|
res + RESET
|
||||||
}
|
}
|
||||||
Location::LineRange(_begin, _end) => {
|
Location::LineRange(ln_begin, ln_end) => {
|
||||||
todo!()
|
let codes = if self.input() == &Input::REPL {
|
||||||
|
vec![self.input().reread()]
|
||||||
|
} else {
|
||||||
|
self.input().reread_lines(ln_begin, ln_end)
|
||||||
|
};
|
||||||
|
let mut res = CYAN.to_string();
|
||||||
|
for (i, lineno) in (ln_begin..=ln_end).enumerate() {
|
||||||
|
let mut pointer = " ".repeat(lineno.to_string().len() + 2); // +2 means `| `
|
||||||
|
pointer += &"^".repeat(cmp::max(1, codes[i].len()));
|
||||||
|
res += &format!(
|
||||||
|
"{lineno}{VBAR_UNICODE} {code}\n{pointer}\n",
|
||||||
|
code = codes[i]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
res + RESET
|
||||||
}
|
}
|
||||||
Location::Line(lineno) => {
|
Location::Line(lineno) => {
|
||||||
let code = if self.input() == &Input::REPL {
|
let code = if self.input() == &Input::REPL {
|
||||||
|
|
|
@ -22,8 +22,8 @@ impl Visibility {
|
||||||
/// same structure as `Identifier`, but only for Record fields.
|
/// same structure as `Identifier`, but only for Record fields.
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct Field {
|
pub struct Field {
|
||||||
vis: Visibility,
|
pub vis: Visibility,
|
||||||
symbol: Str,
|
pub symbol: Str,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Field {
|
impl fmt::Display for Field {
|
||||||
|
|
|
@ -13,21 +13,25 @@ use erg_common::Str;
|
||||||
use erg_common::{
|
use erg_common::{
|
||||||
debug_power_assert, enum_unwrap, fn_name_full, impl_stream_for_wrapper, log, switch_unreachable,
|
debug_power_assert, enum_unwrap, fn_name_full, impl_stream_for_wrapper, log, switch_unreachable,
|
||||||
};
|
};
|
||||||
|
use erg_parser::ast::DefId;
|
||||||
use erg_type::codeobj::{CodeObj, CodeObjFlags};
|
use erg_type::codeobj::{CodeObj, CodeObjFlags};
|
||||||
use Opcode::*;
|
use Opcode::*;
|
||||||
|
|
||||||
use erg_parser::ast::{Identifier, ParamPattern, Params, VarName};
|
use erg_parser::ast::{Identifier, ParamPattern, ParamSignature, Params, VarName};
|
||||||
use erg_parser::token::{Token, TokenKind};
|
use erg_parser::token::{Token, TokenKind};
|
||||||
|
|
||||||
|
use erg_type::free::fresh_varname;
|
||||||
use erg_type::value::TypeKind;
|
use erg_type::value::TypeKind;
|
||||||
use erg_type::value::ValueObj;
|
use erg_type::value::ValueObj;
|
||||||
use erg_type::{HasType, TypeCode, TypePair};
|
use erg_type::{HasType, Type, TypeCode, TypePair};
|
||||||
|
|
||||||
use crate::compile::{AccessKind, Name, StoreLoadKind};
|
use crate::compile::{AccessKind, Name, StoreLoadKind};
|
||||||
use crate::context::eval::eval_lit;
|
use crate::context::eval::eval_lit;
|
||||||
use crate::error::{CompileError, CompileErrors, CompileResult};
|
use crate::error::{CompileError, CompileErrors, CompileResult};
|
||||||
|
use crate::hir::AttrDef;
|
||||||
|
use crate::hir::Attribute;
|
||||||
use crate::hir::{
|
use crate::hir::{
|
||||||
Accessor, Args, Array, Block, Call, ClassDef, DefBody, Expr, Local, RecordAttrs, Signature,
|
Accessor, Args, Array, Block, Call, ClassDef, Def, DefBody, Expr, Local, Signature,
|
||||||
SubrSignature, Tuple, VarSignature, HIR,
|
SubrSignature, Tuple, VarSignature, HIR,
|
||||||
};
|
};
|
||||||
use AccessKind::*;
|
use AccessKind::*;
|
||||||
|
@ -197,6 +201,7 @@ fn convert_to_python_attr(class: &str, uniq_obj_name: Option<&str>, name: Str) -
|
||||||
("Array!", _, "push!") => Str::ever("append"),
|
("Array!", _, "push!") => Str::ever("append"),
|
||||||
("Complex" | "Real" | "Int" | "Nat" | "Float", _, "Real") => Str::ever("real"),
|
("Complex" | "Real" | "Int" | "Nat" | "Float", _, "Real") => Str::ever("real"),
|
||||||
("Complex" | "Real" | "Int" | "Nat" | "Float", _, "Imag") => Str::ever("imag"),
|
("Complex" | "Real" | "Int" | "Nat" | "Float", _, "Imag") => Str::ever("imag"),
|
||||||
|
("Type", _, "new" | "__new__") => Str::ever("__call__"),
|
||||||
("StringIO!", _, "getvalue!") => Str::ever("getvalue"),
|
("StringIO!", _, "getvalue!") => Str::ever("getvalue"),
|
||||||
("Module", Some("importlib"), "reload!") => Str::ever("reload"),
|
("Module", Some("importlib"), "reload!") => Str::ever("reload"),
|
||||||
("Module", Some("random"), "randint!") => Str::ever("randint"),
|
("Module", Some("random"), "randint!") => Str::ever("randint"),
|
||||||
|
@ -644,6 +649,25 @@ impl CodeGenerator {
|
||||||
self.stack_dec();
|
self.stack_dec();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn store_acc(&mut self, acc: Accessor) {
|
||||||
|
match acc {
|
||||||
|
Accessor::Local(local) => {
|
||||||
|
self.emit_store_instr(Identifier::new(None, VarName::new(local.name)), Name);
|
||||||
|
}
|
||||||
|
Accessor::Public(public) => {
|
||||||
|
self.emit_store_instr(
|
||||||
|
Identifier::new(Some(public.dot), VarName::new(public.name)),
|
||||||
|
Name,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Accessor::Attr(attr) => {
|
||||||
|
self.codegen_expr(*attr.obj);
|
||||||
|
self.emit_store_instr(Identifier::new(None, VarName::new(attr.name)), Attr);
|
||||||
|
}
|
||||||
|
acc => todo!("store: {acc}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn emit_pop_top(&mut self) {
|
fn emit_pop_top(&mut self) {
|
||||||
self.write_instr(Opcode::POP_TOP);
|
self.write_instr(Opcode::POP_TOP);
|
||||||
self.write_arg(0u8);
|
self.write_arg(0u8);
|
||||||
|
@ -686,38 +710,46 @@ impl CodeGenerator {
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_linked_type_def(&mut self, type_def: ClassDef) {
|
fn emit_class_def(&mut self, class_def: ClassDef) {
|
||||||
match type_def.def.sig {
|
let ident = class_def.sig.ident().clone();
|
||||||
Signature::Var(var) => match type_def.kind {
|
let kind = class_def.kind;
|
||||||
TypeKind::Class => self.emit_mono_class_def(var, type_def.public_methods),
|
let require_or_sup = class_def.require_or_sup.clone();
|
||||||
TypeKind::InheritedClass => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
other => todo!("{other:?} is not supported"),
|
|
||||||
},
|
|
||||||
Signature::Subr(_) => todo!("polymorphic type definition"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn emit_mono_class_def(&mut self, sig: VarSignature, methods: RecordAttrs) {
|
|
||||||
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 code = self.codegen_typedef_block(sig.inspect().clone(), methods);
|
let code = self.codegen_typedef_block(class_def);
|
||||||
self.emit_load_const(code);
|
self.emit_load_const(code);
|
||||||
self.emit_load_const(sig.inspect().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(sig.inspect().clone());
|
self.emit_load_const(ident.inspect().clone());
|
||||||
|
let subclasses_len = self.emit_require_type(kind, *require_or_sup);
|
||||||
|
// LOAD subclasses
|
||||||
self.write_instr(Opcode::CALL_FUNCTION);
|
self.write_instr(Opcode::CALL_FUNCTION);
|
||||||
self.write_arg(2);
|
self.write_arg(2 + subclasses_len as u8);
|
||||||
self.stack_dec_n((1 + 2) - 1);
|
self.stack_dec_n((1 + 2 + subclasses_len) - 1);
|
||||||
self.emit_store_instr(sig.ident, Name);
|
self.emit_store_instr(ident, Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: use `TypeVar`, `Generic` in `typing` module
|
// NOTE: use `TypeVar`, `Generic` in `typing` module
|
||||||
// fn emit_poly_type_def(&mut self, sig: SubrSignature, body: DefBody) {}
|
// fn emit_poly_type_def(&mut self, sig: SubrSignature, body: DefBody) {}
|
||||||
|
|
||||||
|
fn emit_require_type(&mut self, kind: TypeKind, require_or_sup: Expr) -> usize {
|
||||||
|
match kind {
|
||||||
|
TypeKind::Class => 0,
|
||||||
|
TypeKind::Subclass => {
|
||||||
|
self.codegen_expr(require_or_sup);
|
||||||
|
1 // TODO: not always 1
|
||||||
|
}
|
||||||
|
_ => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn emit_attr_def(&mut self, attr_def: AttrDef) {
|
||||||
|
self.codegen_frameless_block(attr_def.block, vec![]);
|
||||||
|
self.store_acc(attr_def.attr);
|
||||||
|
}
|
||||||
|
|
||||||
fn emit_var_def(&mut self, sig: VarSignature, mut body: DefBody) {
|
fn emit_var_def(&mut self, sig: VarSignature, mut body: DefBody) {
|
||||||
if body.block.len() == 1 {
|
if body.block.len() == 1 {
|
||||||
self.codegen_expr(body.block.remove(0));
|
self.codegen_expr(body.block.remove(0));
|
||||||
|
@ -971,6 +1003,9 @@ impl CodeGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_call_method(&mut self, obj: Expr, method_name: Token, mut args: Args) {
|
fn emit_call_method(&mut self, obj: Expr, method_name: Token, mut args: Args) {
|
||||||
|
if &method_name.inspect()[..] == "update!" {
|
||||||
|
return self.emit_call_update(obj, args);
|
||||||
|
}
|
||||||
let class = obj.ref_t().name(); // これは必ずmethodのあるクラスになっている
|
let class = obj.ref_t().name(); // これは必ずmethodのあるクラスになっている
|
||||||
let uniq_obj_name = obj.__name__().map(Str::rc);
|
let uniq_obj_name = obj.__name__().map(Str::rc);
|
||||||
self.codegen_expr(obj);
|
self.codegen_expr(obj);
|
||||||
|
@ -1005,6 +1040,21 @@ impl CodeGenerator {
|
||||||
self.stack_dec_n((1 + argc + kwsc) - 1);
|
self.stack_dec_n((1 + argc + kwsc) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// X.update! x -> x + 1
|
||||||
|
/// X = (x -> x + 1)(X)
|
||||||
|
/// X = X + 1
|
||||||
|
fn emit_call_update(&mut self, obj: Expr, mut args: Args) {
|
||||||
|
let acc = enum_unwrap!(obj, Expr::Accessor);
|
||||||
|
let func = args.remove_left_or_key("f").unwrap();
|
||||||
|
self.codegen_expr(func);
|
||||||
|
self.codegen_acc(acc.clone());
|
||||||
|
self.write_instr(CALL_FUNCTION);
|
||||||
|
self.write_arg(1 as u8);
|
||||||
|
// (1 (subroutine) + argc) input objects -> 1 return object
|
||||||
|
self.stack_dec_n((1 + 1) - 1);
|
||||||
|
self.store_acc(acc);
|
||||||
|
}
|
||||||
|
|
||||||
// assert takes 1 or 2 arguments (0: cond, 1: message)
|
// assert takes 1 or 2 arguments (0: cond, 1: message)
|
||||||
fn emit_assert_instr(&mut self, mut args: Args) -> CompileResult<()> {
|
fn emit_assert_instr(&mut self, mut args: Args) -> CompileResult<()> {
|
||||||
self.codegen_expr(args.remove(0));
|
self.codegen_expr(args.remove(0));
|
||||||
|
@ -1066,7 +1116,8 @@ impl CodeGenerator {
|
||||||
Signature::Subr(sig) => self.emit_subr_def(sig, def.body),
|
Signature::Subr(sig) => self.emit_subr_def(sig, def.body),
|
||||||
Signature::Var(sig) => self.emit_var_def(sig, def.body),
|
Signature::Var(sig) => self.emit_var_def(sig, def.body),
|
||||||
},
|
},
|
||||||
Expr::ClassDef(def) => self.emit_linked_type_def(def),
|
Expr::ClassDef(class) => self.emit_class_def(class),
|
||||||
|
Expr::AttrDef(attr) => self.emit_attr_def(attr),
|
||||||
// TODO:
|
// TODO:
|
||||||
Expr::Lambda(lambda) => {
|
Expr::Lambda(lambda) => {
|
||||||
let params = self.gen_param_names(&lambda.params);
|
let params = self.gen_param_names(&lambda.params);
|
||||||
|
@ -1323,22 +1374,42 @@ impl CodeGenerator {
|
||||||
self.cancel_pop_top();
|
self.cancel_pop_top();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn codegen_typedef_block(&mut self, name: Str, methods: RecordAttrs) -> CodeObj {
|
fn codegen_typedef_block(&mut self, class: ClassDef) -> CodeObj {
|
||||||
|
let name = class.sig.ident().inspect().clone();
|
||||||
self.unit_size += 1;
|
self.unit_size += 1;
|
||||||
|
let firstlineno = match (
|
||||||
|
class.private_methods.get(0).and_then(|def| def.ln_begin()),
|
||||||
|
class.public_methods.get(0).and_then(|def| def.ln_begin()),
|
||||||
|
) {
|
||||||
|
(Some(l), Some(r)) => l.min(r),
|
||||||
|
(Some(line), None) | (None, Some(line)) => line,
|
||||||
|
(None, None) => class.sig.ln_begin().unwrap(),
|
||||||
|
};
|
||||||
self.units.push(CodeGenUnit::new(
|
self.units.push(CodeGenUnit::new(
|
||||||
self.unit_size,
|
self.unit_size,
|
||||||
vec![],
|
vec![],
|
||||||
Str::rc(self.cfg.input.enclosed_name()),
|
Str::rc(self.cfg.input.enclosed_name()),
|
||||||
&name,
|
&name,
|
||||||
methods[0].ln_begin().unwrap(),
|
firstlineno,
|
||||||
));
|
));
|
||||||
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(Identifier::public("__module__"), Attr);
|
self.emit_store_instr(Identifier::public("__module__"), Attr);
|
||||||
self.emit_load_const(name);
|
self.emit_load_const(name);
|
||||||
self.emit_store_instr(Identifier::public("__qualname__"), Attr);
|
self.emit_store_instr(Identifier::public("__qualname__"), Attr);
|
||||||
|
if class.need_to_gen_new {
|
||||||
|
self.emit_auto_new(&class.sig, class.__new__);
|
||||||
|
}
|
||||||
// TODO: サブルーチンはT.subという書式でSTORE
|
// TODO: サブルーチンはT.subという書式でSTORE
|
||||||
for def in methods.into_iter() {
|
for def in class.private_methods.into_iter() {
|
||||||
|
self.codegen_expr(Expr::Def(def));
|
||||||
|
// TODO: discard
|
||||||
|
if self.cur_block().stack_len == 1 {
|
||||||
|
self.emit_pop_top();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for mut def in class.public_methods.into_iter() {
|
||||||
|
def.sig.ident_mut().dot = Some(Token::dummy());
|
||||||
self.codegen_expr(Expr::Def(def));
|
self.codegen_expr(Expr::Def(def));
|
||||||
// TODO: discard
|
// TODO: discard
|
||||||
if self.cur_block().stack_len == 1 {
|
if self.cur_block().stack_len == 1 {
|
||||||
|
@ -1378,6 +1449,62 @@ impl CodeGenerator {
|
||||||
unit.codeobj
|
unit.codeobj
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn emit_auto_new(&mut self, sig: &Signature, __new__: Type) {
|
||||||
|
let line = sig.ln_begin().unwrap();
|
||||||
|
let ident = Identifier::private_with_line(Str::ever("__new__"), line);
|
||||||
|
let param_name = fresh_varname();
|
||||||
|
let param = VarName::from_str_and_line(Str::from(param_name.clone()), line);
|
||||||
|
let params = Params::new(
|
||||||
|
vec![ParamSignature::new(
|
||||||
|
ParamPattern::VarName(param),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
)],
|
||||||
|
None,
|
||||||
|
vec![],
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
let sig = Signature::Subr(SubrSignature::new(ident, params.clone(), __new__.clone()));
|
||||||
|
let mut attrs = vec![];
|
||||||
|
match __new__.non_default_params().unwrap()[0].typ() {
|
||||||
|
// {x = Int; y = Int}
|
||||||
|
// self.x = %x.x; self.y = %x.y
|
||||||
|
Type::Record(rec) => {
|
||||||
|
for field in rec.keys() {
|
||||||
|
let obj = Expr::Accessor(Accessor::local(
|
||||||
|
Token::symbol_with_line(¶m_name[..], line),
|
||||||
|
Type::Failure,
|
||||||
|
));
|
||||||
|
let attr = Accessor::Attr(Attribute::new(
|
||||||
|
obj,
|
||||||
|
Token::symbol(&field.symbol[..]),
|
||||||
|
Type::Failure,
|
||||||
|
));
|
||||||
|
let obj = Expr::Accessor(Accessor::local(
|
||||||
|
Token::symbol_with_line("self", line),
|
||||||
|
Type::Failure,
|
||||||
|
));
|
||||||
|
let expr = Expr::Accessor(Accessor::Attr(Attribute::new(
|
||||||
|
obj,
|
||||||
|
Token::symbol(&field.symbol[..]),
|
||||||
|
Type::Failure,
|
||||||
|
)));
|
||||||
|
let attr_def = AttrDef::new(attr, Block::new(vec![expr]));
|
||||||
|
attrs.push(Expr::AttrDef(attr_def));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
other => todo!("{other}"),
|
||||||
|
}
|
||||||
|
let block = Block::new(attrs);
|
||||||
|
let body = DefBody::new(Token::dummy(), block, DefId(0));
|
||||||
|
let private_new_def = Def::new(sig, body.clone());
|
||||||
|
self.codegen_expr(Expr::Def(private_new_def));
|
||||||
|
let ident = Identifier::public_with_line(Token::dummy(), Str::ever("new"), line);
|
||||||
|
let sig = Signature::Subr(SubrSignature::new(ident, params, __new__));
|
||||||
|
let new_def = Def::new(sig, body);
|
||||||
|
self.codegen_expr(Expr::Def(new_def));
|
||||||
|
}
|
||||||
|
|
||||||
fn codegen_block(&mut self, block: Block, opt_name: Option<Str>, params: Vec<Str>) -> CodeObj {
|
fn codegen_block(&mut self, block: Block, opt_name: Option<Str>, params: Vec<Str>) -> CodeObj {
|
||||||
self.unit_size += 1;
|
self.unit_size += 1;
|
||||||
let name = if let Some(name) = opt_name {
|
let name = if let Some(name) = opt_name {
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
|
use std::mem;
|
||||||
|
|
||||||
use erg_common::Str;
|
use erg_common::Str;
|
||||||
|
|
||||||
use erg_type::constructors::mono;
|
use erg_type::constructors::{and, mono};
|
||||||
use erg_type::value::{TypeKind, TypeObj, ValueObj};
|
use erg_type::value::{TypeKind, TypeObj, ValueObj};
|
||||||
use erg_type::Type;
|
use erg_type::Type;
|
||||||
use erg_type::ValueArgs;
|
use erg_type::ValueArgs;
|
||||||
|
@ -19,9 +21,9 @@ fn value_obj_to_t(value: ValueObj) -> TypeObj {
|
||||||
|
|
||||||
/// Requirement: Type, Impl := Type -> Class
|
/// Requirement: Type, Impl := Type -> Class
|
||||||
pub fn class_func(mut args: ValueArgs, __name__: Option<Str>) -> ValueObj {
|
pub fn class_func(mut args: ValueArgs, __name__: Option<Str>) -> ValueObj {
|
||||||
let require = args.pos_args.remove(0);
|
let require = args.remove_left_or_key("Requirement").unwrap();
|
||||||
let require = value_obj_to_t(require);
|
let require = value_obj_to_t(require);
|
||||||
let impls = args.pos_args.pop().or_else(|| args.kw_args.remove("Impl"));
|
let impls = args.remove_left_or_key("Impl");
|
||||||
let impls = impls.map(|v| value_obj_to_t(v));
|
let impls = impls.map(|v| value_obj_to_t(v));
|
||||||
let t = mono(__name__.unwrap_or(Str::ever("<Lambda>")));
|
let t = mono(__name__.unwrap_or(Str::ever("<Lambda>")));
|
||||||
ValueObj::gen_t(TypeKind::Class, t, require, impls, None)
|
ValueObj::gen_t(TypeKind::Class, t, require, impls, None)
|
||||||
|
@ -29,21 +31,34 @@ pub fn class_func(mut args: ValueArgs, __name__: Option<Str>) -> ValueObj {
|
||||||
|
|
||||||
/// Super: Type, Impl := Type, Additional := Type -> Class
|
/// Super: Type, Impl := Type, Additional := Type -> Class
|
||||||
pub fn inherit_func(mut args: ValueArgs, __name__: Option<Str>) -> ValueObj {
|
pub fn inherit_func(mut args: ValueArgs, __name__: Option<Str>) -> ValueObj {
|
||||||
let sup = args.pos_args.remove(0);
|
let sup = args.remove_left_or_key("Super").unwrap();
|
||||||
let sup = value_obj_to_t(sup);
|
let sup = value_obj_to_t(sup);
|
||||||
let impls = args.pos_args.pop().or_else(|| args.kw_args.remove("Impl"));
|
let impls = args.remove_left_or_key("Impl");
|
||||||
let impls = impls.map(|v| value_obj_to_t(v));
|
let impls = impls.map(|v| value_obj_to_t(v));
|
||||||
let additional = args
|
let additional = args.remove_left_or_key("Additional");
|
||||||
.pos_args
|
|
||||||
.pop()
|
|
||||||
.or_else(|| args.kw_args.remove("Additional"));
|
|
||||||
let additional = additional.map(|v| value_obj_to_t(v));
|
let additional = additional.map(|v| value_obj_to_t(v));
|
||||||
let t = mono(__name__.unwrap_or(Str::ever("<Lambda>")));
|
let t = mono(__name__.unwrap_or(Str::ever("<Lambda>")));
|
||||||
ValueObj::gen_t(TypeKind::InheritedClass, t, sup, impls, additional)
|
ValueObj::gen_t(TypeKind::Subclass, t, sup, impls, additional)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Class -> Class
|
/// Class -> Class (with `Inheritable`)
|
||||||
/// This function is used by the compiler to mark a class as inheritable and does nothing in terms of actual operation.
|
/// This function is used by the compiler to mark a class as inheritable and does nothing in terms of actual operation.
|
||||||
pub fn inheritable_func(args: ValueArgs, __name__: Option<Str>) -> ValueObj {
|
pub fn inheritable_func(args: ValueArgs, __name__: Option<Str>) -> ValueObj {
|
||||||
args.pos_args.into_iter().next().unwrap()
|
let class = args.pos_args.into_iter().next().unwrap();
|
||||||
|
match class {
|
||||||
|
ValueObj::Type(TypeObj::Generated(mut gen)) => {
|
||||||
|
if let Some(typ) = &mut gen.impls {
|
||||||
|
match typ.as_mut() {
|
||||||
|
TypeObj::Generated(gen) => {
|
||||||
|
gen.t = and(mem::take(&mut gen.t), mono("Inheritable"));
|
||||||
|
}
|
||||||
|
TypeObj::Builtin(t) => {
|
||||||
|
*t = and(mem::take(t), mono("Inheritable"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ValueObj::Type(TypeObj::Generated(gen))
|
||||||
|
}
|
||||||
|
_ => todo!(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,7 @@ impl Context {
|
||||||
if self.rec_get_const_obj(name).is_some() {
|
if self.rec_get_const_obj(name).is_some() {
|
||||||
panic!("already registered: {name}");
|
panic!("already registered: {name}");
|
||||||
} else {
|
} else {
|
||||||
|
// TODO: not all value objects are comparable
|
||||||
let vi = VarInfo::new(enum_t(set! {obj.clone()}), Const, Private, Builtin);
|
let vi = VarInfo::new(enum_t(set! {obj.clone()}), Const, Private, Builtin);
|
||||||
self.consts.insert(VarName::from_str(Str::rc(name)), obj);
|
self.consts.insert(VarName::from_str(Str::rc(name)), obj);
|
||||||
self.locals.insert(VarName::from_str(Str::rc(name)), vi);
|
self.locals.insert(VarName::from_str(Str::rc(name)), vi);
|
||||||
|
@ -360,8 +361,6 @@ impl Context {
|
||||||
obj.register_builtin_impl("__dict__", fn0_met(Obj, dict(Str, Obj)), Immutable, Public);
|
obj.register_builtin_impl("__dict__", fn0_met(Obj, dict(Str, Obj)), Immutable, Public);
|
||||||
obj.register_builtin_impl("__bytes__", fn0_met(Obj, mono("Bytes")), Immutable, Public);
|
obj.register_builtin_impl("__bytes__", fn0_met(Obj, mono("Bytes")), Immutable, Public);
|
||||||
obj.register_builtin_const("MutType!", ValueObj::builtin_t(mono("Obj!")));
|
obj.register_builtin_const("MutType!", ValueObj::builtin_t(mono("Obj!")));
|
||||||
// let mut record = Self::mono_trait("Record", vec![Obj], Self::TOP_LEVEL);
|
|
||||||
// let mut class = Self::mono_class("Class", vec![Type, Obj], Self::TOP_LEVEL);
|
|
||||||
let mut int = Self::mono_class(
|
let mut int = Self::mono_class(
|
||||||
"Int",
|
"Int",
|
||||||
vec![Ratio, Obj],
|
vec![Ratio, Obj],
|
||||||
|
@ -1089,7 +1088,7 @@ impl Context {
|
||||||
vec![param_t("Impl", Type)],
|
vec![param_t("Impl", Type)],
|
||||||
Class,
|
Class,
|
||||||
);
|
);
|
||||||
let class = ConstSubr::Builtin(BuiltinConstSubr::new(class_func, class_t));
|
let class = ConstSubr::Builtin(BuiltinConstSubr::new("Class", class_func, class_t));
|
||||||
self.register_builtin_const("Class", ValueObj::Subr(class));
|
self.register_builtin_const("Class", ValueObj::Subr(class));
|
||||||
let inherit_t = func(
|
let inherit_t = func(
|
||||||
vec![param_t("Super", Class)],
|
vec![param_t("Super", Class)],
|
||||||
|
@ -1097,11 +1096,15 @@ impl Context {
|
||||||
vec![param_t("Impl", Type), param_t("Additional", Type)],
|
vec![param_t("Impl", Type), param_t("Additional", Type)],
|
||||||
Class,
|
Class,
|
||||||
);
|
);
|
||||||
let inherit = ConstSubr::Builtin(BuiltinConstSubr::new(inherit_func, inherit_t));
|
let inherit = ConstSubr::Builtin(BuiltinConstSubr::new("Inherit", inherit_func, inherit_t));
|
||||||
self.register_builtin_const("Inherit", ValueObj::Subr(inherit));
|
self.register_builtin_const("Inherit", ValueObj::Subr(inherit));
|
||||||
// decorators
|
// decorators
|
||||||
let inheritable =
|
let inheritable_t = func1(Class, Class);
|
||||||
ConstSubr::Builtin(BuiltinConstSubr::new(inheritable_func, func1(Class, Class)));
|
let inheritable = ConstSubr::Builtin(BuiltinConstSubr::new(
|
||||||
|
"Inheritable",
|
||||||
|
inheritable_func,
|
||||||
|
inheritable_t,
|
||||||
|
));
|
||||||
self.register_builtin_const("Inheritable", ValueObj::Subr(inheritable));
|
self.register_builtin_const("Inheritable", ValueObj::Subr(inheritable));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -525,6 +525,7 @@ impl Context {
|
||||||
let gen = enum_unwrap!(t, TypeObj::Generated);
|
let gen = enum_unwrap!(t, TypeObj::Generated);
|
||||||
self.register_gen_type(gen);
|
self.register_gen_type(gen);
|
||||||
}
|
}
|
||||||
|
// TODO: not all value objects are comparable
|
||||||
other => {
|
other => {
|
||||||
let id = DefId(get_hash(name));
|
let id = DefId(get_hash(name));
|
||||||
let vi = VarInfo::new(
|
let vi = VarInfo::new(
|
||||||
|
@ -556,7 +557,7 @@ impl Context {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TypeKind::InheritedClass => {
|
TypeKind::Subclass => {
|
||||||
if gen.t.is_monomorphic() {
|
if gen.t.is_monomorphic() {
|
||||||
let super_classes = vec![gen.require_or_sup.typ().clone()];
|
let super_classes = vec![gen.require_or_sup.typ().clone()];
|
||||||
let super_traits = gen.impls.iter().map(|to| to.typ().clone()).collect();
|
let super_traits = gen.impls.iter().map(|to| to.typ().clone()).collect();
|
||||||
|
@ -568,6 +569,8 @@ impl Context {
|
||||||
TypeObj::Builtin(t) => t,
|
TypeObj::Builtin(t) => t,
|
||||||
TypeObj::Generated(t) => t.require_or_sup.as_ref().typ(),
|
TypeObj::Generated(t) => t.require_or_sup.as_ref().typ(),
|
||||||
};
|
};
|
||||||
|
// `Super.Requirement := {x = Int}` and `Self.Additional := {y = Int}`
|
||||||
|
// => `Self.Requirement := {x = Int; y = Int}`
|
||||||
let param_t = if let Some(additional) = &gen.additional {
|
let param_t = if let Some(additional) = &gen.additional {
|
||||||
self.rec_intersection(¶m_t, additional.typ())
|
self.rec_intersection(¶m_t, additional.typ())
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -493,6 +493,13 @@ impl Context {
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
hir::Expr::AttrDef(attr_def) => {
|
||||||
|
// REVIEW: attr_def.attr is not dereferenced
|
||||||
|
for chunk in attr_def.block.iter_mut() {
|
||||||
|
self.deref_expr_t(chunk)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -243,6 +243,22 @@ impl Args {
|
||||||
.map(|a| &a.expr)
|
.map(|a| &a.expr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn remove_left_or_key(&mut self, key: &str) -> Option<Expr> {
|
||||||
|
if !self.pos_args.is_empty() {
|
||||||
|
Some(self.pos_args.remove(0).expr)
|
||||||
|
} else {
|
||||||
|
if let Some(pos) = self
|
||||||
|
.kw_args
|
||||||
|
.iter()
|
||||||
|
.position(|arg| &arg.keyword.inspect()[..] == key)
|
||||||
|
{
|
||||||
|
Some(self.kw_args.remove(pos).expr)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// represents local variables
|
/// represents local variables
|
||||||
|
@ -894,9 +910,9 @@ 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!(
|
writeln!(
|
||||||
f,
|
f,
|
||||||
"({}){}(: {}):",
|
"({}){} (: {}):",
|
||||||
self.obj,
|
self.obj,
|
||||||
fmt_option!(pre ".", self.method_name),
|
fmt_option!(pre ".", self.method_name.as_ref().map(|t| t.inspect())),
|
||||||
self.sig_t
|
self.sig_t
|
||||||
)?;
|
)?;
|
||||||
self.args.fmt_nest(f, level + 1)
|
self.args.fmt_nest(f, level + 1)
|
||||||
|
@ -1011,6 +1027,7 @@ impl NestedDisplay for VarSignature {
|
||||||
|
|
||||||
impl_display_from_nested!(VarSignature);
|
impl_display_from_nested!(VarSignature);
|
||||||
impl_locational!(VarSignature, ident);
|
impl_locational!(VarSignature, ident);
|
||||||
|
impl_t!(VarSignature);
|
||||||
|
|
||||||
impl VarSignature {
|
impl VarSignature {
|
||||||
pub const fn new(ident: Identifier, t: Type) -> Self {
|
pub const fn new(ident: Identifier, t: Type) -> Self {
|
||||||
|
@ -1041,6 +1058,7 @@ impl NestedDisplay for SubrSignature {
|
||||||
|
|
||||||
impl_display_from_nested!(SubrSignature);
|
impl_display_from_nested!(SubrSignature);
|
||||||
impl_locational!(SubrSignature, ident, params);
|
impl_locational!(SubrSignature, ident, params);
|
||||||
|
impl_t!(SubrSignature);
|
||||||
|
|
||||||
impl SubrSignature {
|
impl SubrSignature {
|
||||||
pub const fn new(ident: Identifier, params: Params, t: Type) -> Self {
|
pub const fn new(ident: Identifier, params: Params, t: Type) -> Self {
|
||||||
|
@ -1096,6 +1114,7 @@ pub enum Signature {
|
||||||
|
|
||||||
impl_nested_display_for_chunk_enum!(Signature; Var, Subr);
|
impl_nested_display_for_chunk_enum!(Signature; Var, Subr);
|
||||||
impl_display_for_enum!(Signature; Var, Subr,);
|
impl_display_for_enum!(Signature; Var, Subr,);
|
||||||
|
impl_t_for_enum!(Signature; Var, Subr);
|
||||||
impl_locational_for_enum!(Signature; Var, Subr,);
|
impl_locational_for_enum!(Signature; Var, Subr,);
|
||||||
|
|
||||||
impl Signature {
|
impl Signature {
|
||||||
|
@ -1130,6 +1149,13 @@ impl Signature {
|
||||||
Self::Subr(s) => &s.ident,
|
Self::Subr(s) => &s.ident,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn ident_mut(&mut self) -> &mut Identifier {
|
||||||
|
match self {
|
||||||
|
Self::Var(v) => &mut v.ident,
|
||||||
|
Self::Subr(s) => &mut s.ident,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// represents a declaration of a variable
|
/// represents a declaration of a variable
|
||||||
|
@ -1254,23 +1280,23 @@ impl Def {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct MethodDefs {
|
pub struct Methods {
|
||||||
pub class: TypeSpec,
|
pub class: TypeSpec,
|
||||||
pub vis: Token, // `.` or `::`
|
pub vis: Token, // `.` or `::`
|
||||||
pub defs: RecordAttrs, // TODO: allow declaration
|
pub defs: RecordAttrs, // TODO: allow declaration
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NestedDisplay for MethodDefs {
|
impl NestedDisplay for Methods {
|
||||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
|
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
|
||||||
writeln!(f, "{}{}", self.class, self.vis.content)?;
|
writeln!(f, "{}{}", self.class, self.vis.content)?;
|
||||||
self.defs.fmt_nest(f, level + 1)
|
self.defs.fmt_nest(f, level + 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_display_from_nested!(MethodDefs);
|
impl_display_from_nested!(Methods);
|
||||||
impl_locational!(MethodDefs, class, defs);
|
impl_locational!(Methods, class, defs);
|
||||||
|
|
||||||
impl HasType for MethodDefs {
|
impl HasType for Methods {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn ref_t(&self) -> &Type {
|
fn ref_t(&self) -> &Type {
|
||||||
Type::NONE
|
Type::NONE
|
||||||
|
@ -1289,7 +1315,7 @@ impl HasType for MethodDefs {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MethodDefs {
|
impl Methods {
|
||||||
pub const fn new(class: TypeSpec, vis: Token, defs: RecordAttrs) -> Self {
|
pub const fn new(class: TypeSpec, vis: Token, defs: RecordAttrs) -> Self {
|
||||||
Self { class, vis, defs }
|
Self { class, vis, defs }
|
||||||
}
|
}
|
||||||
|
@ -1298,21 +1324,25 @@ impl MethodDefs {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ClassDef {
|
pub struct ClassDef {
|
||||||
pub kind: TypeKind,
|
pub kind: TypeKind,
|
||||||
pub def: Def,
|
pub sig: Signature,
|
||||||
|
pub require_or_sup: Box<Expr>,
|
||||||
|
/// The type of `new` and `__new__` that is automatically defined if not defined
|
||||||
|
pub need_to_gen_new: bool,
|
||||||
|
pub __new__: Type,
|
||||||
pub private_methods: RecordAttrs,
|
pub private_methods: RecordAttrs,
|
||||||
pub public_methods: RecordAttrs,
|
pub public_methods: RecordAttrs,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NestedDisplay for ClassDef {
|
impl NestedDisplay for ClassDef {
|
||||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
|
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
|
||||||
self.def.fmt_nest(f, level)?;
|
self.sig.fmt_nest(f, level)?;
|
||||||
self.private_methods.fmt_nest(f, level)?;
|
self.private_methods.fmt_nest(f, level)?;
|
||||||
self.public_methods.fmt_nest(f, level + 1)
|
self.public_methods.fmt_nest(f, level + 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_display_from_nested!(ClassDef);
|
impl_display_from_nested!(ClassDef);
|
||||||
impl_locational!(ClassDef, def);
|
impl_locational!(ClassDef, sig);
|
||||||
|
|
||||||
impl HasType for ClassDef {
|
impl HasType for ClassDef {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -1334,21 +1364,69 @@ impl HasType for ClassDef {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClassDef {
|
impl ClassDef {
|
||||||
pub const fn new(
|
pub fn new(
|
||||||
kind: TypeKind,
|
kind: TypeKind,
|
||||||
def: Def,
|
sig: Signature,
|
||||||
|
require_or_sup: Expr,
|
||||||
|
need_to_gen_new: bool,
|
||||||
|
__new__: Type,
|
||||||
private_methods: RecordAttrs,
|
private_methods: RecordAttrs,
|
||||||
public_methods: RecordAttrs,
|
public_methods: RecordAttrs,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
kind,
|
kind,
|
||||||
def,
|
sig,
|
||||||
|
require_or_sup: Box::new(require_or_sup),
|
||||||
|
need_to_gen_new,
|
||||||
|
__new__,
|
||||||
private_methods,
|
private_methods,
|
||||||
public_methods,
|
public_methods,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct AttrDef {
|
||||||
|
pub attr: Accessor,
|
||||||
|
pub block: Block,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NestedDisplay for AttrDef {
|
||||||
|
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
|
||||||
|
self.attr.fmt_nest(f, level)?;
|
||||||
|
writeln!(f, " = ")?;
|
||||||
|
self.block.fmt_nest(f, level + 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_display_from_nested!(AttrDef);
|
||||||
|
impl_locational!(AttrDef, attr, block);
|
||||||
|
|
||||||
|
impl HasType for AttrDef {
|
||||||
|
#[inline]
|
||||||
|
fn ref_t(&self) -> &Type {
|
||||||
|
Type::NONE
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn ref_mut_t(&mut self) -> &mut Type {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn signature_t(&self) -> Option<&Type> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn signature_mut_t(&mut self) -> Option<&mut Type> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AttrDef {
|
||||||
|
pub const fn new(attr: Accessor, block: Block) -> Self {
|
||||||
|
Self { attr, block }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Expr {
|
pub enum Expr {
|
||||||
Lit(Literal),
|
Lit(Literal),
|
||||||
|
@ -1365,12 +1443,13 @@ pub enum Expr {
|
||||||
Decl(Decl),
|
Decl(Decl),
|
||||||
Def(Def),
|
Def(Def),
|
||||||
ClassDef(ClassDef),
|
ClassDef(ClassDef),
|
||||||
|
AttrDef(AttrDef),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_nested_display_for_chunk_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def, ClassDef);
|
impl_nested_display_for_chunk_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def, ClassDef, AttrDef);
|
||||||
impl_display_from_nested!(Expr);
|
impl_display_from_nested!(Expr);
|
||||||
impl_locational_for_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def, ClassDef);
|
impl_locational_for_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def, ClassDef, AttrDef);
|
||||||
impl_t_for_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def, ClassDef);
|
impl_t_for_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def, ClassDef, AttrDef);
|
||||||
|
|
||||||
impl Expr {
|
impl Expr {
|
||||||
pub fn receiver_t(&self) -> Option<&Type> {
|
pub fn receiver_t(&self) -> Option<&Type> {
|
||||||
|
|
|
@ -13,13 +13,14 @@ use erg_parser::token::{Token, TokenKind};
|
||||||
use erg_type::constructors::{array, array_mut, free_var, func, mono, poly, proc, quant};
|
use erg_type::constructors::{array, array_mut, free_var, func, mono, poly, proc, quant};
|
||||||
use erg_type::free::Constraint;
|
use erg_type::free::Constraint;
|
||||||
use erg_type::typaram::TyParam;
|
use erg_type::typaram::TyParam;
|
||||||
use erg_type::value::{TypeKind, ValueObj};
|
use erg_type::value::{TypeObj, ValueObj};
|
||||||
use erg_type::{HasType, ParamTy, Type};
|
use erg_type::{HasType, ParamTy, Type};
|
||||||
|
|
||||||
use crate::context::{Context, ContextKind, RegistrationMode};
|
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::VarKind;
|
||||||
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
|
||||||
|
@ -548,7 +549,7 @@ impl ASTLowerer {
|
||||||
|
|
||||||
fn lower_class_def(&mut self, class_def: ast::ClassDef) -> LowerResult<hir::ClassDef> {
|
fn lower_class_def(&mut self, class_def: ast::ClassDef) -> LowerResult<hir::ClassDef> {
|
||||||
log!(info "entered {}({class_def})", fn_name!());
|
log!(info "entered {}({class_def})", fn_name!());
|
||||||
let hir_def = self.lower_def(class_def.def)?;
|
let mut hir_def = self.lower_def(class_def.def)?;
|
||||||
let mut private_methods = hir::RecordAttrs::empty();
|
let mut private_methods = hir::RecordAttrs::empty();
|
||||||
let mut public_methods = hir::RecordAttrs::empty();
|
let mut public_methods = hir::RecordAttrs::empty();
|
||||||
for methods in class_def.methods_list.into_iter() {
|
for methods in class_def.methods_list.into_iter() {
|
||||||
|
@ -581,22 +582,44 @@ impl ASTLowerer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let definition = hir_def.body.block.first().unwrap();
|
let (_, ctx) = self
|
||||||
let call = enum_unwrap!(definition, hir::Expr::Call);
|
.ctx
|
||||||
// FIXME:
|
.rec_get_nominal_type_ctx(&mono(hir_def.sig.ident().inspect()))
|
||||||
let kind = match &call.obj.var_full_name().unwrap()[..] {
|
.unwrap();
|
||||||
"Class" | "Inheritable" => TypeKind::Class,
|
let type_obj = enum_unwrap!(self.ctx.rec_get_const_obj(hir_def.sig.ident().inspect()).unwrap(), ValueObj::Type:(TypeObj::Generated:(_)));
|
||||||
"Inherit" => TypeKind::InheritedClass,
|
// vi.t.non_default_params().unwrap()[0].typ().clone()
|
||||||
_ => unreachable!(),
|
let (__new__, need_to_gen_new) = if let Some(vi) = ctx.get_current_scope_var("new") {
|
||||||
|
(vi.t.clone(), vi.kind == VarKind::Auto)
|
||||||
|
} else {
|
||||||
|
todo!()
|
||||||
};
|
};
|
||||||
|
let require_or_sup = self.get_require_or_sup(hir_def.body.block.remove(0));
|
||||||
Ok(hir::ClassDef::new(
|
Ok(hir::ClassDef::new(
|
||||||
kind,
|
type_obj.kind,
|
||||||
hir_def,
|
hir_def.sig,
|
||||||
|
require_or_sup,
|
||||||
|
need_to_gen_new,
|
||||||
|
__new__,
|
||||||
private_methods,
|
private_methods,
|
||||||
public_methods,
|
public_methods,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_require_or_sup(&self, expr: hir::Expr) -> hir::Expr {
|
||||||
|
match expr {
|
||||||
|
acc @ hir::Expr::Accessor(_) => acc,
|
||||||
|
hir::Expr::Call(mut call) => match call.obj.var_full_name().as_ref().map(|s| &s[..]) {
|
||||||
|
Some("Class") => call.args.remove_left_or_key("Requirement").unwrap(),
|
||||||
|
Some("Inherit") => call.args.remove_left_or_key("Super").unwrap(),
|
||||||
|
Some("Inheritable") => {
|
||||||
|
self.get_require_or_sup(call.args.remove_left_or_key("Class").unwrap())
|
||||||
|
}
|
||||||
|
_ => todo!(),
|
||||||
|
},
|
||||||
|
other => todo!("{other}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Call.obj == Accessor cannot be type inferred by itself (it can only be inferred with arguments)
|
// Call.obj == Accessor cannot be type inferred by itself (it can only be inferred with arguments)
|
||||||
// so turn off type checking (check=false)
|
// so turn off type checking (check=false)
|
||||||
fn lower_expr(&mut self, expr: ast::Expr) -> LowerResult<hir::Expr> {
|
fn lower_expr(&mut self, expr: ast::Expr) -> LowerResult<hir::Expr> {
|
||||||
|
|
|
@ -1872,13 +1872,17 @@ impl Identifier {
|
||||||
Self::new(None, VarName::from_str_and_line(name, line))
|
Self::new(None, VarName::from_str_and_line(name, line))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn public_with_line(dot: Token, name: Str, line: usize) -> Self {
|
||||||
|
Self::new(Some(dot), VarName::from_str_and_line(name, line))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_const(&self) -> bool {
|
pub fn is_const(&self) -> bool {
|
||||||
self.name.is_const()
|
self.name.is_const()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn vis(&self) -> Visibility {
|
pub const fn vis(&self) -> Visibility {
|
||||||
match &self.dot {
|
match &self.dot {
|
||||||
Some(_dot) => Visibility::Public,
|
Some(_) => Visibility::Public,
|
||||||
None => Visibility::Private,
|
None => Visibility::Private,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -376,6 +376,16 @@ impl Token {
|
||||||
Self::from_str(TokenKind::Symbol, cont)
|
Self::from_str(TokenKind::Symbol, cont)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn symbol_with_line(cont: &str, line: usize) -> Self {
|
||||||
|
Token {
|
||||||
|
kind: TokenKind::Symbol,
|
||||||
|
content: Str::rc(cont),
|
||||||
|
lineno: line,
|
||||||
|
col_begin: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub const fn static_symbol(s: &'static str) -> Self {
|
pub const fn static_symbol(s: &'static str) -> Self {
|
||||||
Token {
|
Token {
|
||||||
kind: TokenKind::Symbol,
|
kind: TokenKind::Symbol,
|
||||||
|
|
|
@ -142,17 +142,36 @@ impl ValueArgs {
|
||||||
pub const fn new(pos_args: Vec<ValueObj>, kw_args: Dict<Str, ValueObj>) -> Self {
|
pub const fn new(pos_args: Vec<ValueObj>, kw_args: Dict<Str, ValueObj>) -> Self {
|
||||||
ValueArgs { pos_args, kw_args }
|
ValueArgs { pos_args, kw_args }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn remove_left_or_key(&mut self, key: &str) -> Option<ValueObj> {
|
||||||
|
if !self.pos_args.is_empty() {
|
||||||
|
Some(self.pos_args.remove(0))
|
||||||
|
} else {
|
||||||
|
self.kw_args.remove(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct BuiltinConstSubr {
|
pub struct BuiltinConstSubr {
|
||||||
|
name: &'static str,
|
||||||
subr: fn(ValueArgs, Option<Str>) -> ValueObj,
|
subr: fn(ValueArgs, Option<Str>) -> ValueObj,
|
||||||
t: Type,
|
t: Type,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for BuiltinConstSubr {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "<built-in const subroutine '{}'>", self.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl BuiltinConstSubr {
|
impl BuiltinConstSubr {
|
||||||
pub const fn new(subr: fn(ValueArgs, Option<Str>) -> ValueObj, t: Type) -> Self {
|
pub const fn new(
|
||||||
Self { subr, t }
|
name: &'static str,
|
||||||
|
subr: fn(ValueArgs, Option<Str>) -> ValueObj,
|
||||||
|
t: Type,
|
||||||
|
) -> Self {
|
||||||
|
Self { name, subr, t }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,8 +184,10 @@ pub enum ConstSubr {
|
||||||
impl fmt::Display for ConstSubr {
|
impl fmt::Display for ConstSubr {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
ConstSubr::User(_) => write!(f, "<user-defined const subroutine>"),
|
ConstSubr::User(subr) => {
|
||||||
ConstSubr::Builtin(_) => write!(f, "<builtin const subroutine>"),
|
write!(f, "<user-defined const subroutine '{}'>", subr.code.name)
|
||||||
|
}
|
||||||
|
ConstSubr::Builtin(subr) => write!(f, "{subr}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1840,6 +1861,13 @@ impl Type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn contains_intersec(&self, typ: &Type) -> bool {
|
||||||
|
match self {
|
||||||
|
Type::And(t1, t2) => t1.contains_intersec(typ) || t2.contains_intersec(typ),
|
||||||
|
_ => self == typ,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn tvar_name(&self) -> Option<Str> {
|
pub fn tvar_name(&self) -> Option<Str> {
|
||||||
match self {
|
match self {
|
||||||
Self::FreeVar(fv) => fv.unbound_name(),
|
Self::FreeVar(fv) => fv.unbound_name(),
|
||||||
|
|
|
@ -25,9 +25,9 @@ use crate::{ConstSubr, HasType, Predicate, Type};
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
pub enum TypeKind {
|
pub enum TypeKind {
|
||||||
Class,
|
Class,
|
||||||
InheritedClass,
|
Subclass,
|
||||||
Trait,
|
Trait,
|
||||||
SubsumedTrait,
|
Subtrait,
|
||||||
StructuralTrait,
|
StructuralTrait,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ pub enum TypeKind {
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct GenTypeObj {
|
pub struct GenTypeObj {
|
||||||
pub kind: TypeKind,
|
pub kind: TypeKind,
|
||||||
pub t: Type,
|
pub t: Type, // andやorが入る可能性あり
|
||||||
pub require_or_sup: Box<TypeObj>,
|
pub require_or_sup: Box<TypeObj>,
|
||||||
pub impls: Option<Box<TypeObj>>,
|
pub impls: Option<Box<TypeObj>>,
|
||||||
pub additional: Option<Box<TypeObj>>,
|
pub additional: Option<Box<TypeObj>>,
|
||||||
|
@ -66,8 +66,8 @@ impl GenTypeObj {
|
||||||
|
|
||||||
pub fn meta_type(&self) -> Type {
|
pub fn meta_type(&self) -> Type {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
TypeKind::Class | TypeKind::InheritedClass => Type::Class,
|
TypeKind::Class | TypeKind::Subclass => Type::Class,
|
||||||
TypeKind::Trait | TypeKind::SubsumedTrait | TypeKind::StructuralTrait => Type::Trait,
|
TypeKind::Trait | TypeKind::Subtrait | TypeKind::StructuralTrait => Type::Trait,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue