From 04e11ae67aee94d995c7230da08707f8ce30f29d Mon Sep 17 00:00:00 2001 From: Lennart Van Hirtum Date: Tue, 12 Dec 2023 10:44:11 +0100 Subject: [PATCH] Further work on latency counting --- src/arena_alloc.rs | 19 +++ src/ast.rs | 2 +- src/codegen.rs | 9 +- src/dev_aid/syntax_highlighting.rs | 32 ++-- src/flattening.rs | 12 +- src/instantiation/latency.rs | 150 ++++++++++++++++++ .../mod.rs} | 73 +++++---- src/linker.rs | 8 +- src/main.rs | 37 +++-- src/parser.rs | 33 ++-- 10 files changed, 302 insertions(+), 73 deletions(-) create mode 100644 src/instantiation/latency.rs rename src/{instantiation.rs => instantiation/mod.rs} (82%) diff --git a/src/arena_alloc.rs b/src/arena_alloc.rs index 0e791ba..4e63dbc 100644 --- a/src/arena_alloc.rs +++ b/src/arena_alloc.rs @@ -361,6 +361,9 @@ impl FlatAlloc { self.data.push(value); UUID(uuid, PhantomData) } + pub fn len(&self) -> usize { + self.data.len() + } pub fn iter<'a>(&'a self) -> FlatAllocIter<'a, T, IndexMarker> { self.into_iter() } @@ -397,6 +400,14 @@ impl<'a, T, IndexMarker : UUIDMarker> Iterator for FlatAllocIter<'a, T, IndexMar fn next(&mut self) -> Option { self.iter.next().map(|(id, v)| (UUID(id, PhantomData), v)) } + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} +impl<'a, T, IndexMarker : UUIDMarker> ExactSizeIterator for FlatAllocIter<'a, T, IndexMarker> { + fn len(&self) -> usize { + self.iter.len() + } } impl<'a, T, IndexMarker : UUIDMarker> IntoIterator for &'a FlatAlloc { @@ -421,6 +432,14 @@ impl<'a, T, IndexMarker : UUIDMarker> Iterator for FlatAllocIterMut<'a, T, Index fn next(&mut self) -> Option { self.iter.next().map(|(id, v)| (UUID(id, PhantomData), v)) } + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} +impl<'a, T, IndexMarker : UUIDMarker> ExactSizeIterator for FlatAllocIterMut<'a, T, IndexMarker> { + fn len(&self) -> usize { + self.iter.len() + } } impl<'a, T, IndexMarker : UUIDMarker> IntoIterator for &'a mut FlatAlloc { diff --git a/src/ast.rs b/src/ast.rs index 224377a..c9921b9 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -118,7 +118,7 @@ pub enum AssignableExpression { #[derive(Debug)] pub struct AssignableExpressionWithModifiers { pub expr : SpanAssignableExpression, - pub num_regs : u32 + pub num_regs : i64 } #[derive(Debug)] diff --git a/src/codegen.rs b/src/codegen.rs index 9cae85d..b6a26de 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -1,6 +1,6 @@ use std::{ops::Deref, io}; -use crate::{linker::Linker, flattening::{FlattenedModule, FlatID}, ast::{Module, Span}, arena_alloc::ListAllocator}; +use crate::{linker::Linker, flattening::{FlattenedModule, FlatID}, ast::{Module, Span}, arena_alloc::ListAllocator, instantiation::InstantiatedModule}; use moore_circt::{hw, comb, mlir::{self, Owned, builder, OperationExt, SingleBlockOp}, mlir::{Context, OwnedContext, DialectHandle, Builder, Value, Type}}; @@ -19,7 +19,7 @@ impl GenerationContext { Self{global_ctx} } - pub fn to_circt(&self) { + pub fn to_circt(&self, instance : &InstantiatedModule) { let ctx = *self.global_ctx.deref(); //moore_circt::hw:: let module = moore_circt::ModuleOp::new(ctx); @@ -29,6 +29,11 @@ impl GenerationContext { let mut builder = Builder::new(mod_ctx); builder.set_insertion_point_to_start(module.block()); + //let mut wire_names = instance.wires.iter().map(|a| builder.) + for (id, w) in &instance.wires { + + } + //mlir_builder.set_loc(span_to_loc(mod_ctx, hir.span())); //mlir_builder.set_insertion_point_to_end(self.into_mlir.block()); diff --git a/src/dev_aid/syntax_highlighting.rs b/src/dev_aid/syntax_highlighting.rs index 7c0a74c..36cff87 100644 --- a/src/dev_aid/syntax_highlighting.rs +++ b/src/dev_aid/syntax_highlighting.rs @@ -1,7 +1,7 @@ -use std::{ops::Range, path::PathBuf}; +use std::{ops::Range, path::{PathBuf, Path}}; -use crate::{ast::*, tokenizer::*, parser::*, linker::{PreLinker, FileData, Links, NamedUUID, Named, Linkable}, arena_alloc::ArenaVector}; +use crate::{ast::*, tokenizer::*, parser::*, linker::{PreLinker, FileData, Links, NamedUUID, Named, Linkable, Linker, FileUUIDMarker, FileUUID}, arena_alloc::ArenaVector}; use ariadne::FileCache; use console::Style; @@ -210,7 +210,7 @@ fn generate_character_offsets(file_text : &str, tokens : &[Token]) -> Vec, settings : &SyntaxHighlightSettings) { +pub fn compile_all(file_paths : Vec) -> (Linker, ArenaVector) { let mut prelinker : PreLinker = PreLinker::new(); let mut paths_arena = ArenaVector::new(); for file_path in file_paths { @@ -233,18 +233,15 @@ pub fn syntax_highlight_file(file_paths : Vec, settings : &SyntaxHighli let mut linker = prelinker.link(); - let mut file_cache : FileCache = Default::default(); - linker.recompile_all(); - for (file_uuid, f) in &linker.files { - if settings.show_tokens { - print_tokens(&f.file_text, &f.tokens); - } - - let ide_tokens = create_token_ide_info(f, &linker.links); - pretty_print(&f.file_text, &f.tokens, &ide_tokens); + (linker, paths_arena) +} +pub fn print_all_errors(linker : &Linker, paths_arena : &ArenaVector) { + let mut file_cache : FileCache = Default::default(); + + for (file_uuid, f) in &linker.files { let token_offsets = generate_character_offsets(&f.file_text, &f.tokens); let mut errors = f.parsing_errors.clone(); @@ -255,3 +252,14 @@ pub fn syntax_highlight_file(file_paths : Vec, settings : &SyntaxHighli } } } + +pub fn syntax_highlight_file(linker : &Linker, file_uuid : FileUUID, settings : &SyntaxHighlightSettings) { + let f = &linker.files[file_uuid]; + + if settings.show_tokens { + print_tokens(&f.file_text, &f.tokens); + } + + let ide_tokens = create_token_ide_info(f, &linker.links); + pretty_print(&f.file_text, &f.tokens, &ide_tokens); +} diff --git a/src/flattening.rs b/src/flattening.rs index 4d2aa73..92f0db3 100644 --- a/src/flattening.rs +++ b/src/flattening.rs @@ -35,15 +35,15 @@ impl ConnectionWrite { } } -#[derive(Debug)] -pub struct InterfacePort { +#[derive(Debug,Clone,Copy)] +pub struct InterfacePort { pub is_input : bool, - pub id : UID + pub id : FlatID } #[derive(Debug)] pub enum Instantiation { - SubModule{module_uuid : NamedUUID, typ_span : Span, interface_wires : Vec>}, + SubModule{module_uuid : NamedUUID, typ_span : Span, interface_wires : Vec}, PlainWire{read_only : bool, typ : Type, decl_id : Option}, UnaryOp{typ : Type, op : Operator, right : SpanFlatID}, BinaryOp{typ : Type, op : Operator, left : SpanFlatID, right : SpanFlatID}, @@ -86,7 +86,7 @@ impl Instantiation { #[derive(Debug)] pub struct Connection { - pub num_regs : u32, + pub num_regs : i64, pub from : SpanFlatID, pub to : ConnectionWrite, pub condition : FlatID @@ -148,7 +148,7 @@ impl<'l, 'm, 'fl> FlatteningContext<'l, 'm, 'fl> { Instantiation::SubModule{module_uuid, typ_span, interface_wires} } - fn desugar_func_call(&self, func_and_args : &[SpanExpression], closing_bracket_pos : usize, condition : FlatID) -> Option<(&Module, &[InterfacePort])> { + fn desugar_func_call(&self, func_and_args : &[SpanExpression], closing_bracket_pos : usize, condition : FlatID) -> Option<(&Module, &[InterfacePort])> { let (name_expr, name_expr_span) = &func_and_args[0]; // Function name is always there let func_instantiation_id = match name_expr { Expression::Named(LocalOrGlobal::Local(l)) => { diff --git a/src/instantiation/latency.rs b/src/instantiation/latency.rs new file mode 100644 index 0000000..b957d52 --- /dev/null +++ b/src/instantiation/latency.rs @@ -0,0 +1,150 @@ +use std::{iter::zip, collections::VecDeque}; + +use crate::arena_alloc::FlatAlloc; + +use super::{WireID, WireIDMarker, RealWire, SubModule, SubModuleIDMarker}; + + + + +struct FanInOut { + other : WireID, + delta_latency : i64 +} + +/* + Algorithm: + Initialize all inputs at latency 0 + Perform full forward pass, making latencies the maximum of all incoming latencies + Then backward pass, moving nodes forward in latency as much as possible. + Only moving forward is possible, and only when not confliciting with a later node +*/ +struct LatencyComputer { + fanins : FlatAlloc, WireIDMarker>, + fanouts : FlatAlloc, WireIDMarker> +} + +impl LatencyComputer { + fn setup(wires : &FlatAlloc, submodules : &FlatAlloc) -> Self { + // Wire to wire Fanin + let mut fanins : FlatAlloc, WireIDMarker> = wires.iter().map(|(id, wire)| { + let mut fanin = Vec::new(); + wire.source.iter_sources_with_min_latency(|from, delta_latency| { + fanin.push(FanInOut{other : from, delta_latency}); + }); + fanin + }).collect(); + + // Submodules Fanin + for (_id, sub_mod) in submodules { + for (input_wire, input_port) in zip(&sub_mod.wires, &sub_mod.instance.interface) { + if !input_port.is_input {continue;} + for (output_wire, output_port) in zip(&sub_mod.wires, &sub_mod.instance.interface) { + if output_port.is_input {continue;} + + let delta_latency = output_port.absolute_latency - input_port.absolute_latency; + + fanins[*output_wire].push(FanInOut{other: *input_wire, delta_latency}); + } + } + } + + // Process fanouts + let mut fanouts : FlatAlloc, WireIDMarker> = wires.iter().map(|(id, wire)| { + Vec::new() + }).collect(); + + for (id, fin) in &fanins { + for f in fin { + fanouts[f.other].push(FanInOut { other: id, delta_latency: f.delta_latency }) + } + } + + Self {fanins, fanouts} + } + + fn compute_latencies_forward(&self) -> FlatAlloc { + let mut latencies : FlatAlloc = self.fanins.iter().map(|_| 0).collect(); + + let mut queue : VecDeque = VecDeque::new(); + queue.reserve(self.fanins.len()); + + let mut order : Vec = Vec::new(); + order.reserve(self.fanins.len()); + + for (id, v) in &self.fanouts { + if v.is_empty() { + queue.push_back(id); + latencies[id] = 1; // Initialize with 1 + } + } + + while let Some(s) = queue.pop_front() { + let mut all_explored = false; + for from in &self.fanins[s] { + + } + } + + latencies + } +} + +struct RuntimeData { + part_of_path : bool, + eliminated : bool, + maps_to : WireID +} +struct GraphDecycler<'f> { + runtime_data : FlatAlloc, + fanins : &'f FlatAlloc, WireIDMarker> +} + +impl<'f> GraphDecycler<'f> { + fn new(fanins : &FlatAlloc, WireIDMarker>) -> GraphDecycler { + GraphDecycler { + runtime_data : fanins.iter().map(|(maps_to, _)| RuntimeData{ part_of_path: false, eliminated: false, maps_to }).collect(), + fanins + } + } + + fn is_part_of_cycle(&mut self, id : WireID) -> Option { + if self.runtime_data[id].eliminated {return None;} + + if self.runtime_data[id].part_of_path { + // TODO Handle start removing cycle + return Some(id); // New node was part of path, remove it! + } + + self.runtime_data[id].part_of_path = true; + + for fi in &self.fanins[id] { + if let Some(cycle_root) = self.is_part_of_cycle(fi.other) { + if id == cycle_root { + // We have returned to the root + // Cycle is now removed + // So we just continue + } else { + // Part of the chain towards the root + return Some(cycle_root) + } + } + } + + self.runtime_data[id].eliminated = true; // Once we finish a node, eliminate it + None + } + + fn eliminate_cycles(&mut self) { + for (id, wire_fanin) in self.fanins { + if wire_fanin.is_empty() { + // New root to iterate from + self.is_part_of_cycle(id); + } + + + } + + todo!() + } +} diff --git a/src/instantiation.rs b/src/instantiation/mod.rs similarity index 82% rename from src/instantiation.rs rename to src/instantiation/mod.rs index 0a94f03..4874f8e 100644 --- a/src/instantiation.rs +++ b/src/instantiation/mod.rs @@ -2,7 +2,7 @@ use std::{rc::Rc, ops::Deref, cell::RefCell}; use crate::{arena_alloc::{UUID, UUIDMarker, FlatAlloc}, ast::{Value, Operator, Module}, typing::{ConcreteType, Type}, flattening::{FlatID, Instantiation, FlatIDMarker, ConnectionWrite, ConnectionWritePathElement, InterfacePort}, errors::ErrorCollector, linker::{Linker, get_builtin_uuid, NamedUUID}}; - +pub mod latency; #[derive(Debug,Clone,Copy,PartialEq,Eq,Hash)] pub struct WireIDMarker; @@ -16,7 +16,7 @@ pub type SubModuleID = UUID; #[derive(Debug)] pub struct ConnectFrom { - num_regs : u32, + num_regs : i64, from : WireID, condition : WireID } @@ -43,25 +43,25 @@ pub enum RealWireDataSource { } impl RealWireDataSource { - fn iter_sources ()>(&self, mut f : F) { + fn iter_sources_with_min_latency ()>(&self, mut f : F) { match self { RealWireDataSource::ReadOnly => {} RealWireDataSource::Multiplexer { sources } => { for s in sources { - f(s.from.from); - f(s.from.condition); + f(s.from.from, s.from.num_regs); + f(s.from.condition, 0); } } RealWireDataSource::UnaryOp { op, right } => { - f(*right); + f(*right, 0); } RealWireDataSource::BinaryOp { op, left, right } => { - f(*left); - f(*right); + f(*left, 0); + f(*right, 0); } RealWireDataSource::ArrayAccess { arr, arr_idx } => { - f(*arr); - f(*arr_idx); + f(*arr, 0); + f(*arr_idx, 0); } RealWireDataSource::Constant { value } => {} } @@ -73,24 +73,29 @@ pub struct RealWire { source : RealWireDataSource, original_wire : FlatID, typ : ConcreteType, - absolute_latency : i64 // i64::MIN for invalid. Only temporary + latency : i64 } -const LAETNCY_NOT_SET_YET : i64 = i64::MIN; +#[derive(Debug,Clone,Copy)] +pub struct InstantiatedInterfacePort { + pub id : WireID, + pub is_input : bool, + pub absolute_latency : i64 +} #[derive(Debug)] -pub struct SubModuleInstance { - module_uuid : NamedUUID, +pub struct SubModule { + original_flat : FlatID, instance : Rc, - interface_wires : Vec> + wires : Vec } #[derive(Debug)] pub struct InstantiatedModule { - pub interface : Vec, + pub interface : Vec, pub wires : FlatAlloc, - pub submodules : FlatAlloc, - pub errors : ErrorCollector + pub submodules : FlatAlloc, + pub errors : ErrorCollector, } #[derive(Clone,Copy)] @@ -114,8 +119,8 @@ impl SubModuleOrWire { struct InstantiationContext<'fl, 'l> { instance_map : FlatAlloc, wires : FlatAlloc, - submodules : FlatAlloc, - interface : Vec, + submodules : FlatAlloc, + interface : Vec, errors : ErrorCollector, module : &'fl Module, @@ -124,7 +129,7 @@ struct InstantiationContext<'fl, 'l> { impl<'fl, 'l> InstantiationContext<'fl, 'l> { fn compute_constant(&self, wire : FlatID) -> Value { - let Instantiation::Constant { typ, value } = &self.module.flattened.instantiations[wire] else {todo!()}; + let Instantiation::Constant { typ : _, value } = &self.module.flattened.instantiations[wire] else {todo!()}; value.clone() } fn concretize_type(&self, typ : &Type) -> ConcreteType { @@ -166,21 +171,30 @@ impl<'fl, 'l> InstantiationContext<'fl, 'l> { todo!(); } - let RealWire{absolute_latency : _, typ : _, original_wire: _, source : RealWireDataSource::Multiplexer { sources }} = &mut self.wires[self.instance_map[to.root].extract_wire()] else {unreachable!("Should only be a writeable wire here")}; + let RealWire{latency : _, typ : _, original_wire: _, source : RealWireDataSource::Multiplexer { sources }} = &mut self.wires[self.instance_map[to.root].extract_wire()] else {unreachable!("Should only be a writeable wire here")}; sources.push(MultiplexerSource{from, path : new_path}) } fn add_wire(&mut self, typ : &Type, original_wire : FlatID, source : RealWireDataSource) -> SubModuleOrWire { - SubModuleOrWire::Wire(self.wires.alloc(RealWire{ absolute_latency : LAETNCY_NOT_SET_YET, typ : self.concretize_type(typ), original_wire, source})) + SubModuleOrWire::Wire(self.wires.alloc(RealWire{ latency : i64::MIN /* Invalid */, typ : self.concretize_type(typ), original_wire, source})) } + fn compute_absolute_latencies(&mut self) { + + + + + } + + fn instantiate_flattened_module(&mut self) { for (original_wire, inst) in &self.module.flattened.instantiations { let instance_to_add : SubModuleOrWire = match inst { Instantiation::SubModule{module_uuid, typ_span, interface_wires} => { + let instance = self.linker.instantiate(*module_uuid); let interface_real_wires = interface_wires.iter().map(|port| { - InterfacePort { is_input: port.is_input, id: self.instance_map[port.id].extract_wire()} + self.instance_map[port.id].extract_wire() }).collect(); - SubModuleOrWire::SubModule(self.submodules.alloc(SubModuleInstance{module_uuid : *module_uuid, instance : self.linker.instantiate(*module_uuid), interface_wires : interface_real_wires})) + SubModuleOrWire::SubModule(self.submodules.alloc(SubModule { original_flat: original_wire, instance, wires : interface_real_wires})) }, Instantiation::PlainWire{read_only, typ, decl_id} => { let source = if *read_only { @@ -252,7 +266,12 @@ impl InstantiationList { context.instantiate_flattened_module(); - cache_borrow.push(Rc::new(InstantiatedModule{wires : context.wires, submodules : context.submodules, interface : context.interface, errors : context.errors})); + cache_borrow.push(Rc::new(InstantiatedModule{ + wires : context.wires, + submodules : context.submodules, + interface : context.interface, + errors : context.errors + })); } let instance_id = 0; // Temporary, will always be 0 while not template arguments @@ -270,5 +289,3 @@ impl InstantiationList { self.cache.borrow_mut().clear() } } - - diff --git a/src/linker.rs b/src/linker.rs index f85d097..aa0e21e 100644 --- a/src/linker.rs +++ b/src/linker.rs @@ -175,6 +175,12 @@ pub struct Links { name_colissions : Vec<(NamedUUID, NamedUUID)> } +impl Links { + pub fn get_obj_by_name(&self, name : &str) -> Option<&Named> { + self.global_namespace.get(name).map(|id| &self.globals[*id]) + } +} + // Represents the fully linked set of all files. Incremental operations such as adding and removing files can be performed pub struct Linker { pub links : Links, @@ -538,7 +544,7 @@ impl Linker { if let Named::Module(md) = named_object { println!("[[{}]]:", md.link_info.name); md.print_flattened_module(self); - let inst = self.instantiate(id); + let inst = self.instantiate(id); } } } diff --git a/src/main.rs b/src/main.rs index 5c48275..66bf466 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,6 +20,7 @@ use std::env; use std::error::Error; use std::path::PathBuf; use dev_aid::syntax_highlighting::*; +use linker::Named; fn main() -> Result<(), Box> { @@ -29,18 +30,18 @@ fn main() -> Result<(), Box> { let mut file_paths : Vec = Vec::new(); let mut is_lsp = false; - let mut codegen = true; + let mut codegen = None; let mut settings = SyntaxHighlightSettings{ show_tokens : false }; - for arg in args { + while let Some(arg) = args.next() { match arg.as_str() { "--lsp" => { is_lsp = true; } "--codegen" => { - codegen = true; + codegen = Some(args.next().expect("Expected a module name after --codegen")); } "--tokens" => { settings.show_tokens = true; @@ -51,11 +52,6 @@ fn main() -> Result<(), Box> { } } - #[cfg(feature = "codegen")] - if codegen { - let gen_ctx = codegen::GenerationContext::new(); - gen_ctx.to_circt(); - } #[cfg(feature = "lsp")] if is_lsp { return dev_aid::lsp::lsp_main(25000); @@ -65,7 +61,30 @@ fn main() -> Result<(), Box> { file_paths.push(PathBuf::from("resetNormalizer.sus")); //file_paths.push(PathBuf::from("multiply_add.sus")); } - syntax_highlight_file(file_paths, &settings); + + let (linker, paths_arena) = compile_all(file_paths); + print_all_errors(&linker, &paths_arena); + for (id, path) in &paths_arena { + println!("\n\n[{}]: ", path.to_string_lossy()); + syntax_highlight_file(&linker, id, &settings); + } + + #[cfg(feature = "codegen")] + if let Some(module_name) = codegen { + let gen_ctx = codegen::GenerationContext::new(); + + let Some(named_obj) = linker.links.get_obj_by_name(&module_name) else { + panic!("Module {module_name} does not exist!"); + }; + + let Named::Module(md) = named_obj else { + panic!("{module_name} is not a Module!"); + }; + + + + //gen_ctx.to_circt(); + } Ok(()) } diff --git a/src/parser.rs b/src/parser.rs index d53775d..fdc7c28 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -221,6 +221,11 @@ struct ASTParserRollbackable { original_global_references_size : usize } +struct LeftExpression { + expr : SpanExpression, + num_regs : i64 +} + impl<'g, 'file> ASTParserContext<'g, 'file> { fn add_global_reference(&mut self, name_span : Span) -> usize { let idx = self.global_references.len(); @@ -498,12 +503,12 @@ impl<'g, 'file> ASTParserContext<'g, 'file> { } - let mut left_expressions : Vec<(SpanExpression, u32)> = Vec::new(); + let mut left_expressions : Vec = Vec::new(); let mut all_decls = true; loop { // Loop over a number of declarations possibly - let mut reg_count = 0; + let mut num_regs = 0; while let Some(_tok) = token_stream.eat_is_plain(kw("reg")) { - reg_count += 1; + num_regs += 1; } let mut tok_stream_copy = token_stream.clone(); @@ -512,13 +517,13 @@ impl<'g, 'file> ASTParserContext<'g, 'file> { if let Some((name, span)) = self.try_parse_declaration(&mut tok_stream_copy, declarations, scope) { // Maybe it's a declaration? *token_stream = tok_stream_copy; - left_expressions.push(((Expression::Named(LocalOrGlobal::Local(name)), span), reg_count)); + left_expressions.push(LeftExpression{expr : (Expression::Named(LocalOrGlobal::Local(name)), span), num_regs}); code_block.statements.push((Statement::Declaration(name), span)); } else { self.rollback(rollback_ctx); - if let Some(sp_expr) = self.parse_expression(token_stream, scope) { + if let Some(expr) = self.parse_expression(token_stream, scope) { // It's an expression instead! - left_expressions.push((sp_expr, reg_count)); + left_expressions.push(LeftExpression{expr, num_regs}); all_decls = false; } else { // Also not, error then @@ -572,13 +577,13 @@ impl<'g, 'file> ASTParserContext<'g, 'file> { } } - fn parse_statement_handle_equals(&mut self, left_expressions: Vec<(SpanExpression, u32)>, assign_pos: usize, token_stream: &mut TokenStream<'_>, scope: &mut LocalVariableContext<'_, 'file>, statements: &mut Vec<(Statement, Span)>, start_at: usize) -> Option<()> { + fn parse_statement_handle_equals(&mut self, left_expressions: Vec, assign_pos: usize, token_stream: &mut TokenStream<'_>, scope: &mut LocalVariableContext<'_, 'file>, statements: &mut Vec<(Statement, Span)>, start_at: usize) -> Option<()> { if left_expressions.len() == 0 { self.error_unexpected_token(&[TOKEN_IDENTIFIER], kw("="), assign_pos, "statement"); None } else if let Some(value) = self.parse_expression(token_stream, scope) { - let converted_left : Vec = left_expressions.into_iter().filter_map(&mut |(expr, num_regs)| { - Some(AssignableExpressionWithModifiers{expr : self.convert_expression_to_assignable_expression(expr)?, num_regs}) + let converted_left : Vec = left_expressions.into_iter().filter_map(&mut |le: LeftExpression| { + Some(AssignableExpressionWithModifiers{expr : self.convert_expression_to_assignable_expression(le.expr)?, num_regs : le.num_regs}) }).collect(); let end_at = value.1.1; statements.push((Statement::Assign{to : converted_left, eq_sign_position : Some(assign_pos), expr : value}, Span(start_at, end_at))); @@ -591,7 +596,7 @@ impl<'g, 'file> ASTParserContext<'g, 'file> { } } - fn parse_statement_handle_end(&mut self, left_expressions: Vec<(SpanExpression, u32)>, all_decls: bool, statements: &mut Vec<(Statement, Span)>) -> Option<()> { + fn parse_statement_handle_end(&mut self, left_expressions: Vec, all_decls: bool, statements: &mut Vec<(Statement, Span)>) -> Option<()> { // Declarations or single expression only // T a; // myFunc(x, y); @@ -599,17 +604,17 @@ impl<'g, 'file> ASTParserContext<'g, 'file> { return None } else if left_expressions.len() == 1 { // Is a single big expression, or a single declaration - let (expr, _reg_count) = left_expressions.into_iter().next().unwrap(); + let le = left_expressions.into_iter().next().unwrap(); if all_decls { // decls have been taken care of during try_parse_declaration step return Some(()); } else { - let expr_span = expr.1; - statements.push((Statement::Assign{to : Vec::new(), eq_sign_position : None, expr}, expr_span)); + let expr_span = le.expr.1; + statements.push((Statement::Assign{to : Vec::new(), eq_sign_position : None, expr : le.expr}, expr_span)); return None; } } else { - self.errors.error_basic(Span(left_expressions[1].0.1.0, left_expressions[left_expressions.len()-1].0.1.1), "Multiple declarations are only allowed in function call syntax: int a, int b = f(x);"); + self.errors.error_basic(Span(left_expressions[1].expr.1.0, left_expressions[left_expressions.len()-1].expr.1.1), "Multiple declarations are only allowed in function call syntax: int a, int b = f(x);"); return None; } }