From ce4dc6210bdb488af99ced591b5c6b6d70e3e452 Mon Sep 17 00:00:00 2001 From: Mark Date: Sun, 17 Jun 2018 11:56:57 +0200 Subject: [PATCH] Circular reference problem with generator and container #52 --- src/lib.rs | 2 +- src/mango/lexing/gen_code_lexer.rs | 63 ++++++++++++++++-------------- 2 files changed, 34 insertions(+), 31 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index eb74ae95..c9a815a3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,4 @@ -#![feature(nll)] +//#![feature(nll)] #![feature(generators, generator_trait)] extern crate core; diff --git a/src/mango/lexing/gen_code_lexer.rs b/src/mango/lexing/gen_code_lexer.rs index e8a86956..a004e04a 100644 --- a/src/mango/lexing/gen_code_lexer.rs +++ b/src/mango/lexing/gen_code_lexer.rs @@ -36,61 +36,59 @@ use mango::util::strslice::slice::glyphat; // } //} -struct Container> { +// TODO: this is problematic because the generator wants references to the container, +// TODO: and the container obviously stores the generator + +struct CodeLexer> { indent: i32, delegate: Option>, reader: Rc>, + // TODO: https://stackoverflow.com/questions/50895121/rust-expects-two-levels-of-boxing-for-generator-while-i-only-specified-one generator: G, } -impl Container>> { +impl CodeLexer>> { fn lex_indents(&mut self) -> Vec { let mut line_indent = 0; let mut res = Vec::with_capacity(12); - while let Match(_) = self.reader.borrow_mut().matches("\\t") { + // TODO: I don't need * in MWE but I do here (and other places), can I get rid of it? + while let Match(_) = (*self.reader).borrow_mut().matches("\\t") { line_indent += 1; } for _ in line_indent..self.indent { // This line is dedented, make end tokens. // TODO: turn this "new" into a constant - if let Match(_) = self.reader.borrow_mut().matches("end") { + if let Match(_) = (*self.reader).borrow_mut().matches("end") { // If this is followed by an 'end' keyword, then that 'end' is redundant. - yield Tokens::EndBlock(EndBlockToken::new(true, true)); + res.push(Tokens::EndBlock(EndBlockToken::new(true, true))); } else { - yield Tokens::EndBlock(EndBlockToken::new(true, false)); + res.push(Tokens::EndBlock(EndBlockToken::new(true, false))); } } for _ in self.indent..line_indent { // This line is indented, make start tokens. - self.buffer.push(Tokens::StartBlock(StartBlockToken::new())); + res.push(Tokens::StartBlock(StartBlockToken::new())); } self.indent = line_indent; - self.lex() + res } - pub fn new(&mut self, reader: Rc>) -> Box { - let q = 42; - Box::new(Container { - indent: 0, - reader: reader, - delegate: Option::None, - generator: Box::new(move || { - - loop { - - // Delegate to another lexer if one is set. - if let Option::Some(delegate) = self.delegate { - match delegate.lex() { - MaybeToken::Token(token) => { - yield token; - continue; - } - MaybeToken::End => { - self.delegate = Option::None; - } + pub fn new(reader: Rc>) -> Box { + let generator: Box + 'static> = Box::new(|| { + loop { + // Delegate to another lexer if one is set. + if let Option::Some(ref mut delegate) = self.delegate { + match delegate.lex() { + MaybeToken::Token(token) => { + yield token; + continue; + } + MaybeToken::End => { + self.delegate = Option::None; } } + } // // TODO: see if all these match_res can be removed (they couldn't before due to borrowchecker, even with non-lexical lifetimes) // let continue_match_res = self.reader.borrow_mut().matches("\\.\\.\\."); @@ -203,9 +201,14 @@ impl Container>> { // return // } // } - } + } - }), + }); + Box::new(CodeLexer { + indent: 0, + reader: reader, + delegate: Option::None, + generator: generator, }) }