Add DefKind

This commit is contained in:
Shunsuke Shibayama 2022-09-18 17:56:58 +09:00
parent 1a3f204879
commit bd17bf3299
5 changed files with 145 additions and 96 deletions

View file

@ -17,6 +17,7 @@ use erg_common::{
switch_unreachable, switch_unreachable,
}; };
use erg_parser::ast::DefId; use erg_parser::ast::DefId;
use erg_parser::ast::DefKind;
use erg_type::codeobj::{CodeObj, CodeObjFlags}; use erg_type::codeobj::{CodeObj, CodeObjFlags};
use Opcode::*; use Opcode::*;
@ -32,7 +33,7 @@ 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::{ use crate::hir::{
Accessor, Args, Array, AttrDef, Attribute, BinOp, Block, Call, ClassDef, DefBody, Expr, Accessor, Args, Array, AttrDef, Attribute, BinOp, Block, Call, ClassDef, Def, DefBody, Expr,
Identifier, Lambda, Literal, PosArg, Record, Signature, SubrSignature, Tuple, UnaryOp, Identifier, Lambda, Literal, PosArg, Record, Signature, SubrSignature, Tuple, UnaryOp,
VarSignature, HIR, VarSignature, HIR,
}; };
@ -771,8 +772,73 @@ impl CodeGenerator {
.collect() .collect()
} }
fn emit_acc(&mut self, acc: Accessor) {
log!(info "entered {} ({acc})", fn_name!());
match acc {
Accessor::Ident(ident) => {
self.emit_load_name_instr(ident).unwrap_or_else(|err| {
self.errs.push(err);
});
}
Accessor::Attr(a) => {
let class = a.obj.ref_t().name();
let uniq_obj_name = a.obj.__name__().map(Str::rc);
// C = Class ...
// C.
// a = C.x
// ↓
// class C:
// a = x
if Some(&self.cur_block_codeobj().name[..]) != a.obj.__name__() {
self.codegen_expr(*a.obj);
self.emit_load_attr_instr(
&class,
uniq_obj_name.as_ref().map(|s| &s[..]),
a.ident,
)
.unwrap_or_else(|err| {
self.errs.push(err);
});
} else {
self.emit_load_name_instr(a.ident).unwrap_or_else(|err| {
self.errs.push(err);
});
}
}
Accessor::TupleAttr(t_attr) => {
self.codegen_expr(*t_attr.obj);
self.emit_load_const(t_attr.index.value);
self.write_instr(BINARY_SUBSCR);
self.write_arg(0);
self.stack_dec();
}
Accessor::Subscr(subscr) => {
self.codegen_expr(*subscr.obj);
self.codegen_expr(*subscr.index);
self.write_instr(BINARY_SUBSCR);
self.write_arg(0);
self.stack_dec();
}
}
}
fn emit_def(&mut self, def: Def) {
log!(info "entered {} ({})", fn_name!(), def.sig);
if def.def_kind().is_trait() {
return self.emit_trait_def(def);
}
match def.sig {
Signature::Subr(sig) => self.emit_subr_def(None, sig, def.body),
Signature::Var(sig) => self.emit_var_def(sig, def.body),
}
}
fn emit_trait_def(&mut self, def: Def) {
todo!()
}
fn emit_class_def(&mut self, class_def: ClassDef) { fn emit_class_def(&mut self, class_def: ClassDef) {
log!(info "entered {} ({class_def})", fn_name!()); log!(info "entered {} ({})", fn_name!(), class_def.sig);
let ident = class_def.sig.ident().clone(); let ident = class_def.sig.ident().clone();
let kind = class_def.kind; let kind = class_def.kind;
let require_or_sup = class_def.require_or_sup.clone(); let require_or_sup = class_def.require_or_sup.clone();
@ -794,10 +860,6 @@ impl CodeGenerator {
self.stack_dec(); self.stack_dec();
} }
fn _emit_trait_def() {
todo!()
}
// 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) {}
@ -1243,7 +1305,7 @@ impl CodeGenerator {
let acc = enum_unwrap!(obj, Expr::Accessor); let acc = enum_unwrap!(obj, Expr::Accessor);
let func = args.remove_left_or_key("f").unwrap(); let func = args.remove_left_or_key("f").unwrap();
self.codegen_expr(func); self.codegen_expr(func);
self.codegen_acc(acc.clone()); self.emit_acc(acc.clone());
self.write_instr(CALL_FUNCTION); self.write_instr(CALL_FUNCTION);
self.write_arg(1); self.write_arg(1);
// (1 (subroutine) + argc) input objects -> 1 return object // (1 (subroutine) + argc) input objects -> 1 return object
@ -1352,14 +1414,9 @@ impl CodeGenerator {
} }
} }
match expr { match expr {
Expr::Lit(lit) => { Expr::Lit(lit) => self.emit_load_const(lit.value),
self.emit_load_const(lit.value); Expr::Accessor(acc) => self.emit_acc(acc),
} Expr::Def(def) => self.emit_def(def),
Expr::Accessor(acc) => self.codegen_acc(acc),
Expr::Def(def) => match def.sig {
Signature::Subr(sig) => self.emit_subr_def(None, sig, def.body),
Signature::Var(sig) => self.emit_var_def(sig, def.body),
},
Expr::ClassDef(class) => self.emit_class_def(class), Expr::ClassDef(class) => self.emit_class_def(class),
Expr::AttrDef(attr) => self.emit_attr_def(attr), Expr::AttrDef(attr) => self.emit_attr_def(attr),
Expr::Lambda(lambda) => self.emit_lambda(lambda), Expr::Lambda(lambda) => self.emit_lambda(lambda),
@ -1413,56 +1470,6 @@ impl CodeGenerator {
} }
} }
fn codegen_acc(&mut self, acc: Accessor) {
log!(info "entered {} ({acc})", fn_name!());
match acc {
Accessor::Ident(ident) => {
self.emit_load_name_instr(ident).unwrap_or_else(|err| {
self.errs.push(err);
});
}
Accessor::Attr(a) => {
let class = a.obj.ref_t().name();
let uniq_obj_name = a.obj.__name__().map(Str::rc);
// C = Class ...
// C.
// a = C.x
// ↓
// class C:
// a = x
if Some(&self.cur_block_codeobj().name[..]) != a.obj.__name__() {
self.codegen_expr(*a.obj);
self.emit_load_attr_instr(
&class,
uniq_obj_name.as_ref().map(|s| &s[..]),
a.ident,
)
.unwrap_or_else(|err| {
self.errs.push(err);
});
} else {
self.emit_load_name_instr(a.ident).unwrap_or_else(|err| {
self.errs.push(err);
});
}
}
Accessor::TupleAttr(t_attr) => {
self.codegen_expr(*t_attr.obj);
self.emit_load_const(t_attr.index.value);
self.write_instr(BINARY_SUBSCR);
self.write_arg(0);
self.stack_dec();
}
Accessor::Subscr(subscr) => {
self.codegen_expr(*subscr.obj);
self.codegen_expr(*subscr.index);
self.write_instr(BINARY_SUBSCR);
self.write_arg(0);
self.stack_dec();
}
}
}
/// forブロックなどで使う /// forブロックなどで使う
fn codegen_frameless_block(&mut self, block: Block, params: Vec<Str>) { fn codegen_frameless_block(&mut self, block: Block, params: Vec<Str>) {
log!(info "entered {}", fn_name!()); log!(info "entered {}", fn_name!());

View file

@ -26,6 +26,7 @@ use erg_common::vis::Visibility;
use erg_common::Str; use erg_common::Str;
use erg_common::{fn_name, get_hash, log}; use erg_common::{fn_name, get_hash, log};
use erg_parser::ast::DefKind;
use erg_type::typaram::TyParam; use erg_type::typaram::TyParam;
use erg_type::value::ValueObj; use erg_type::value::ValueObj;
use erg_type::{Predicate, TyBound, Type}; use erg_type::{Predicate, TyBound, Type};
@ -230,6 +231,17 @@ pub enum ContextKind {
Dummy, Dummy,
} }
impl From<DefKind> for ContextKind {
fn from(kind: DefKind) -> Self {
match kind {
DefKind::Class | DefKind::Inherit => Self::Class,
DefKind::Trait | DefKind::Subsume => Self::Trait,
DefKind::StructuralTrait => Self::StructuralTrait,
DefKind::Other => Self::Instant,
}
}
}
impl ContextKind { impl ContextKind {
pub const fn is_method_def(&self) -> bool { pub const fn is_method_def(&self) -> bool {
matches!(self, Self::MethodDefs) matches!(self, Self::MethodDefs)

View file

@ -11,7 +11,7 @@ use erg_common::{
impl_stream_for_wrapper, impl_stream_for_wrapper,
}; };
use erg_parser::ast::{fmt_lines, DefId, Params, TypeSpec, VarName}; use erg_parser::ast::{fmt_lines, DefId, DefKind, Params, TypeSpec, VarName};
use erg_parser::token::{Token, TokenKind}; use erg_parser::token::{Token, TokenKind};
use erg_type::constructors::{array, tuple}; use erg_type::constructors::{array, tuple};
@ -1306,6 +1306,30 @@ impl Def {
pub const fn new(sig: Signature, body: DefBody) -> Self { pub const fn new(sig: Signature, body: DefBody) -> Self {
Self { sig, body } Self { sig, body }
} }
pub fn def_kind(&self) -> DefKind {
match self.body.block.first().unwrap() {
Expr::Call(call) => match call.obj.show_acc().as_ref().map(|n| &n[..]) {
Some("Class") => DefKind::Class,
Some("Inherit") => DefKind::Inherit,
Some("Trait") => DefKind::Trait,
Some("Subsume") => DefKind::Subsume,
Some("Inheritable") => {
if let Some(Expr::Call(inner)) = call.args.get_left_or_key("Class") {
match inner.obj.show_acc().as_ref().map(|n| &n[..]) {
Some("Class") => DefKind::Class,
Some("Inherit") => DefKind::Inherit,
_ => DefKind::Other,
}
} else {
DefKind::Other
}
}
_ => DefKind::Other,
},
_ => DefKind::Other,
}
}
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]

View file

@ -564,13 +564,7 @@ impl ASTLowerer {
name, name,
)); ));
} }
let kind = if def.is_class_def() { let kind = ContextKind::from(def.def_kind());
ContextKind::Class
} else if def.is_trait_def() {
ContextKind::Trait
} else {
ContextKind::Instant
};
self.ctx.grow(name, kind, def.sig.vis())?; self.ctx.grow(name, kind, def.sig.vis())?;
let res = match def.sig { let res = match def.sig {
ast::Signature::Subr(sig) => self.lower_subr_def(sig, def.body), ast::Signature::Subr(sig) => self.lower_subr_def(sig, def.body),

View file

@ -2832,6 +2832,22 @@ impl TypeAscription {
} }
} }
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum DefKind {
Class,
Inherit,
Trait,
Subsume,
StructuralTrait,
Other,
}
impl DefKind {
pub const fn is_trait(&self) -> bool {
matches!(self, Self::Trait | Self::Subsume | Self::StructuralTrait)
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct DefBody { pub struct DefBody {
pub op: Token, pub op: Token,
@ -2877,33 +2893,29 @@ impl Def {
matches!(&self.sig, Signature::Subr(_)) matches!(&self.sig, Signature::Subr(_))
} }
pub fn is_class_def(&self) -> bool { pub fn def_kind(&self) -> DefKind {
match self.body.block.first().unwrap() { match self.body.block.first().unwrap() {
Expr::Call(call) Expr::Call(call) => match call.obj.get_name().map(|n| &n[..]) {
if call.obj.get_name().map(|n| &n[..]) == Some("Class") Some("Class") => DefKind::Class,
|| call.obj.get_name().map(|n| &n[..]) == Some("Inherit") => Some("Inherit") => DefKind::Inherit,
{ Some("Trait") => DefKind::Trait,
true Some("Subsume") => DefKind::Subsume,
} Some("Inheritable") => {
Expr::Call(call) if call.obj.get_name().map(|n| &n[..]) == Some("Inheritable") => {
if let Some(Expr::Call(inner)) = call.args.get_left_or_key("Class") { if let Some(Expr::Call(inner)) = call.args.get_left_or_key("Class") {
inner.obj.get_name().map(|n| &n[..]) == Some("Class") match inner.obj.get_name().map(|n| &n[..]) {
|| inner.obj.get_name().map(|n| &n[..]) == Some("Inherit") Some("Class") => DefKind::Class,
Some("Inherit") => DefKind::Inherit,
_ => DefKind::Other,
}
} else { } else {
false DefKind::Other
} }
} }
_ => false, _ => DefKind::Other,
},
_ => DefKind::Other,
} }
} }
pub fn is_trait_def(&self) -> bool {
matches!(
self.body.block.first().unwrap(),
Expr::Call(call) if call.obj.get_name().map(|n| &n[..]) == Some("Trait")
|| call.obj.get_name().map(|n| &n[..]) == Some("Subsume")
)
}
} }
/// e.g. /// e.g.