mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-30 04:44:44 +00:00
Add builder & linker
This commit is contained in:
parent
671fbee518
commit
201b313cd2
19 changed files with 241 additions and 109 deletions
|
@ -2839,6 +2839,7 @@ pub enum DefKind {
|
|||
Trait,
|
||||
Subsume,
|
||||
StructuralTrait,
|
||||
Module,
|
||||
Other,
|
||||
}
|
||||
|
||||
|
@ -2846,6 +2847,10 @@ impl DefKind {
|
|||
pub const fn is_trait(&self) -> bool {
|
||||
matches!(self, Self::Trait | Self::Subsume | Self::StructuralTrait)
|
||||
}
|
||||
|
||||
pub fn is_module(&self) -> bool {
|
||||
matches!(self, Self::Module)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
|
|
|
@ -6,9 +6,8 @@ use crate::ast::AST;
|
|||
use crate::desugar::Desugarer;
|
||||
use crate::error::ParserRunnerErrors;
|
||||
use crate::parse::ParserRunner;
|
||||
use crate::reorder::Reorderer;
|
||||
|
||||
/// Summarize parsing, desugaring, and reordering
|
||||
/// Summarize parsing and desugaring
|
||||
pub struct ASTBuilder {
|
||||
runner: ParserRunner,
|
||||
}
|
||||
|
@ -27,24 +26,16 @@ impl ASTBuilder {
|
|||
let mut desugarer = Desugarer::new();
|
||||
let module = desugarer.desugar(module);
|
||||
let ast = AST::new(Str::ever(self.runner.cfg().module), module);
|
||||
let reorderer = Reorderer::new();
|
||||
let ast = reorderer
|
||||
.reorder(ast)
|
||||
.map_err(|errs| ParserRunnerErrors::convert(self.runner.input(), errs))?;
|
||||
Ok(ast)
|
||||
}
|
||||
|
||||
pub fn build_with_input(&mut self, src: String) -> Result<AST, ParserRunnerErrors> {
|
||||
let module = self.runner.parse_with_input(src)?;
|
||||
pub fn build_with_str(&mut self, src: String) -> Result<AST, ParserRunnerErrors> {
|
||||
let module = self.runner.parse_with_str(src)?;
|
||||
let mut desugarer = Desugarer::new();
|
||||
let module = desugarer.desugar(module);
|
||||
let mut desugarer = Desugarer::new();
|
||||
let module = desugarer.desugar(module);
|
||||
let ast = AST::new(Str::ever(self.runner.cfg().module), module);
|
||||
let reorderer = Reorderer::new();
|
||||
let ast = reorderer
|
||||
.reorder(ast)
|
||||
.map_err(|errs| ParserRunnerErrors::convert(self.runner.input(), errs))?;
|
||||
Ok(ast)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ pub mod desugar;
|
|||
pub mod error;
|
||||
pub mod lex;
|
||||
pub mod parse;
|
||||
pub mod reorder;
|
||||
pub mod token;
|
||||
|
||||
pub use parse::{Parser, ParserRunner};
|
||||
|
|
|
@ -193,7 +193,7 @@ impl Runnable for ParserRunner {
|
|||
}
|
||||
|
||||
fn eval(&mut self, src: String) -> Result<String, ParserRunnerErrors> {
|
||||
let ast = self.parse_with_input(src)?;
|
||||
let ast = self.parse_with_str(src)?;
|
||||
Ok(format!("{ast}"))
|
||||
}
|
||||
}
|
||||
|
@ -212,7 +212,6 @@ impl ParserRunner {
|
|||
self.parse_token_stream(ts)
|
||||
}
|
||||
|
||||
/// Parses with default configuration
|
||||
pub fn parse_with_default_config(input: Input) -> Result<Module, ParserRunnerErrors> {
|
||||
let cfg = ErgConfig {
|
||||
input,
|
||||
|
@ -222,7 +221,7 @@ impl ParserRunner {
|
|||
self_.parse()
|
||||
}
|
||||
|
||||
pub fn parse_with_input(&mut self, src: String) -> Result<Module, ParserRunnerErrors> {
|
||||
pub fn parse_with_str(&mut self, src: String) -> Result<Module, ParserRunnerErrors> {
|
||||
let ts = Lexer::new(Input::Str(src))
|
||||
.lex()
|
||||
.map_err(|errs| ParserRunnerErrors::convert(self.input(), errs))?;
|
||||
|
|
|
@ -1,113 +0,0 @@
|
|||
use erg_common::dict::Dict;
|
||||
use erg_common::log;
|
||||
use erg_common::traits::{Locational, Stream};
|
||||
use erg_common::Str;
|
||||
|
||||
use crate::ast::{ClassDef, Expr, Methods, Module, PreDeclTypeSpec, TypeSpec, AST};
|
||||
use crate::error::{ParseError, ParseErrors};
|
||||
|
||||
/// Combine method definitions across multiple modules, specialized class contexts, etc.
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Reorderer {
|
||||
// TODO: inner scope types
|
||||
pub def_root_pos_map: Dict<Str, usize>,
|
||||
pub deps: Dict<Str, Vec<Str>>,
|
||||
pub errs: ParseErrors,
|
||||
}
|
||||
|
||||
impl Reorderer {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
def_root_pos_map: Dict::new(),
|
||||
deps: Dict::new(),
|
||||
errs: ParseErrors::empty(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reorder(mut self, mut ast: AST) -> Result<AST, ParseErrors> {
|
||||
log!(info "the reordering process has started.");
|
||||
let mut new = vec![];
|
||||
while let Some(chunk) = ast.module.lpop() {
|
||||
match chunk {
|
||||
Expr::Def(def) => {
|
||||
match def.body.block.first().unwrap() {
|
||||
Expr::Call(call) => {
|
||||
match call.obj.get_name().map(|s| &s[..]) {
|
||||
// TODO: decorator
|
||||
Some("Class" | "Inherit" | "Inheritable") => {
|
||||
self.def_root_pos_map.insert(
|
||||
def.sig.ident().unwrap().inspect().clone(),
|
||||
new.len(),
|
||||
);
|
||||
let type_def = ClassDef::new(def, vec![]);
|
||||
new.push(Expr::ClassDef(type_def));
|
||||
}
|
||||
_ => {
|
||||
new.push(Expr::Def(def));
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
new.push(Expr::Def(def));
|
||||
}
|
||||
}
|
||||
}
|
||||
Expr::Methods(methods) => match &methods.class {
|
||||
TypeSpec::PreDeclTy(PreDeclTypeSpec::Simple(simple)) => {
|
||||
self.link_methods(simple.name.inspect().clone(), &mut new, methods)
|
||||
}
|
||||
TypeSpec::TypeApp { spec, .. } => {
|
||||
if let TypeSpec::PreDeclTy(PreDeclTypeSpec::Simple(simple)) = spec.as_ref()
|
||||
{
|
||||
self.link_methods(simple.name.inspect().clone(), &mut new, methods)
|
||||
} else {
|
||||
let similar_name = self
|
||||
.def_root_pos_map
|
||||
.keys()
|
||||
.fold("".to_string(), |acc, key| acc + &key[..] + ",");
|
||||
self.errs.push(ParseError::no_var_error(
|
||||
line!() as usize,
|
||||
methods.class.loc(),
|
||||
&methods.class.to_string(),
|
||||
Some(similar_name),
|
||||
));
|
||||
}
|
||||
}
|
||||
other => todo!("{other}"),
|
||||
},
|
||||
other => {
|
||||
new.push(other);
|
||||
}
|
||||
}
|
||||
}
|
||||
let ast = AST::new(ast.name, Module::new(new));
|
||||
log!(info "the reordering process has completed:\n{}", ast);
|
||||
if self.errs.is_empty() {
|
||||
Ok(ast)
|
||||
} else {
|
||||
Err(self.errs)
|
||||
}
|
||||
}
|
||||
|
||||
fn link_methods(&mut self, name: Str, new: &mut Vec<Expr>, methods: Methods) {
|
||||
if let Some(pos) = self.def_root_pos_map.get(&name) {
|
||||
let mut class_def = match new.remove(*pos) {
|
||||
Expr::ClassDef(class_def) => class_def,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
class_def.methods_list.push(methods);
|
||||
new.insert(*pos, Expr::ClassDef(class_def));
|
||||
} else {
|
||||
let similar_name = self
|
||||
.def_root_pos_map
|
||||
.keys()
|
||||
.fold("".to_string(), |acc, key| acc + &key[..] + ",");
|
||||
self.errs.push(ParseError::no_var_error(
|
||||
line!() as usize,
|
||||
methods.class.loc(),
|
||||
&name,
|
||||
Some(similar_name),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue