diff --git a/src/codegen_fallback.rs b/src/codegen_fallback.rs index 169bfb5..cd02986 100644 --- a/src/codegen_fallback.rs +++ b/src/codegen_fallback.rs @@ -1,6 +1,6 @@ use std::{iter::zip, ops::Deref}; -use crate::{ast::Module, flattening::Instruction, instantiation::{ConnectToPathElem, InstantiatedModule, RealWire, RealWireDataSource, WireID}, linker::{get_builtin_type, TypeUUID}, tokenizer::get_token_type_name, typing::ConcreteType}; +use crate::{ast::Module, flattening::Instruction, instantiation::{ConnectToPathElem, InstantiatedModule, RealWire, RealWireDataSource, WireID}, linker::{get_builtin_type, TypeUUID}, typing::ConcreteType}; fn get_type_name_size(id : TypeUUID) -> u64 { if id == get_builtin_type("int") { @@ -130,10 +130,10 @@ impl<'g, 'out, Stream : std::fmt::Write> CodeGenerationContext<'g, 'out, Stream> match &w.source { RealWireDataSource::UnaryOp { op, right } => { - writeln!(self.program_text, " = {}{};", get_token_type_name(op.op_typ), self.wire_name(*right, w.absolute_latency))?; + writeln!(self.program_text, " = {}{};", op.op_text(), self.wire_name(*right, w.absolute_latency))?; } RealWireDataSource::BinaryOp { op, left, right } => { - writeln!(self.program_text, " = {} {} {};", self.wire_name(*left, w.absolute_latency), get_token_type_name(op.op_typ), self.wire_name(*right, w.absolute_latency))?; + writeln!(self.program_text, " = {} {} {};", self.wire_name(*left, w.absolute_latency), op.op_text(), self.wire_name(*right, w.absolute_latency))?; } RealWireDataSource::ArrayAccess { arr, arr_idx } => { writeln!(self.program_text, " = {}[{}];", self.wire_name(*arr, w.absolute_latency), self.wire_name(*arr_idx, w.absolute_latency))?; diff --git a/src/flattening/mod.rs b/src/flattening/mod.rs index 45e3718..257a967 100644 --- a/src/flattening/mod.rs +++ b/src/flattening/mod.rs @@ -1,19 +1,13 @@ pub mod name_context; -use std::{iter::zip, num::NonZeroU16, ops::Deref}; +use std::{iter::zip, num::NonZeroU16, ops::Deref, path::Display, str::FromStr}; -use tree_sitter::{Node, TreeCursor}; +use num::BigInt; +use tree_sitter::TreeCursor; use crate::{ - arena_alloc::{ArenaAllocator, FlatAlloc, UUIDMarker, UUIDRange, UUID}, - ast::{AssignableExpressionModifiers, CodeBlock, Expression, Identifier, IdentifierType, InterfacePorts, LeftExpression, Module, Operator, SignalDeclaration, SpanExpression, SpanTypeExpression, Statement, TypeExpression}, - errors::{error_info, ErrorCollector, ErrorInfo}, - file_position::{BracketSpan, Span}, - linker::{ConstantUUID, FileUUID, GlobalResolver, Linker, ModuleUUID, NameElem, NamedConstant, NamedType, ResolvedGlobals, ResolvedNameElem, TypeUUIDMarker}, - parser::SUS, - typing::{get_binary_operator_types, typecheck, typecheck_is_array_indexer, typecheck_unary_operator, Type, WrittenType, BOOL_TYPE, INT_TYPE}, - value::Value + arena_alloc::{ArenaAllocator, FlatAlloc, UUIDMarker, UUIDRange, UUID}, ast::{AssignableExpressionModifiers, CodeBlock, Expression, IdentifierType, InterfacePorts, LeftExpression, Module, Operator, SignalDeclaration, SpanExpression, SpanTypeExpression, Statement, TypeExpression}, errors::{error_info, ErrorCollector, ErrorInfo}, file_position::{BracketSpan, Span}, linker::{ConstantUUID, FileUUID, GlobalResolver, Linker, ModuleUUID, NameElem, NamedConstant, NamedType, ResolvedGlobals, ResolvedNameElem, TypeUUIDMarker}, parser::SUS, tokenizer::kw, typing::{get_binary_operator_types, typecheck, typecheck_is_array_indexer, typecheck_unary_operator, Type, WrittenType, BOOL_TYPE, INT_TYPE}, value::Value }; use self::name_context::LocalVariableContext; @@ -58,11 +52,120 @@ pub struct Write { pub to : ConnectionWrite } +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum UnaryOperator { + And, + Or, + Xor, + Not, + Sum, + Product, + Negate, +} +impl UnaryOperator { + pub fn from_text(op_text : &str) -> Self { + match op_text { + "+" => UnaryOperator::Sum, + "*" => UnaryOperator::Product, + "-" => UnaryOperator::Negate, + "&" => UnaryOperator::And, + "|" => UnaryOperator::Or, + "^" => UnaryOperator::Xor, + "!" => UnaryOperator::Not, + _ => unreachable!() + } + } + pub fn op_text(&self) -> &'static str { + match self { + UnaryOperator::And => "&", + UnaryOperator::Or => "|", + UnaryOperator::Xor => "^", + UnaryOperator::Not => "!", + UnaryOperator::Sum => "+", + UnaryOperator::Product => "*", + UnaryOperator::Negate => "-", + } + } +} +impl core::fmt::Display for UnaryOperator { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(self.op_text()) + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum BinaryOperator { + And, + Or, + Xor, + Add, + ShiftLeft, + ShiftRight, + Subtract, + Multiply, + Divide, + Modulo, + Equals, + NotEquals, + Greater, + GreaterEq, + Lesser, + LesserEq +} +impl BinaryOperator { + pub fn from_text(op_text : &str) -> Self { + match op_text { + "&" => BinaryOperator::And, + "|" => BinaryOperator::Or, + "^" => BinaryOperator::Xor, + "<<" => BinaryOperator::ShiftLeft, + ">>" => BinaryOperator::ShiftRight, + "+" => BinaryOperator::Add, + "-" => BinaryOperator::Subtract, + "*" => BinaryOperator::Multiply, + "/" => BinaryOperator::Divide, + "%" => BinaryOperator::Modulo, + "==" => BinaryOperator::Equals, + "!=" => BinaryOperator::NotEquals, + ">" => BinaryOperator::Greater, + ">=" => BinaryOperator::GreaterEq, + "<" => BinaryOperator::Lesser, + "<=" => BinaryOperator::LesserEq, + _ => unreachable!() + } + } + pub fn op_text(&self) -> &'static str { + match self { + BinaryOperator::And => "&", + BinaryOperator::Or => "|", + BinaryOperator::Xor => "^", + BinaryOperator::ShiftLeft => "<<", + BinaryOperator::ShiftRight => ">>", + BinaryOperator::Add => "+", + BinaryOperator::Subtract => "-", + BinaryOperator::Multiply => "*", + BinaryOperator::Divide => "/", + BinaryOperator::Modulo => "%", + BinaryOperator::Equals => "==", + BinaryOperator::NotEquals => "!=", + BinaryOperator::Greater => ">", + BinaryOperator::GreaterEq => ">=", + BinaryOperator::Lesser => "<", + BinaryOperator::LesserEq => "<=", + } + } +} +impl core::fmt::Display for BinaryOperator { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(self.op_text()) + } +} + #[derive(Debug)] pub enum WireSource { WireRead(FlatID), // Used to add a span to the reference of a wire. - UnaryOp{op : Operator, right : FlatID}, - BinaryOp{op : Operator, left : FlatID, right : FlatID}, + UnaryOp{op : UnaryOperator, right : FlatID}, + BinaryOp{op : BinaryOperator, left : FlatID, right : FlatID}, ArrayAccess{arr : FlatID, arr_idx : FlatID}, Constant(Value), NamedConstant(ConstantUUID), @@ -289,14 +392,14 @@ impl<'l> FlatteningContext<'l> { inst_id } - fn resolve_identifier(&self, identifier : &Identifier) -> LocalOrGlobal { + fn resolve_identifier(&self, identifier_span : Span) -> LocalOrGlobal { // Possibly local - let name_text = &self.linker.file.file_text[identifier.span]; + let name_text = &self.linker.file.file_text[identifier_span]; if let Some(decl_id) = self.local_variable_context.get_declaration_for(name_text) { return LocalOrGlobal::Local(decl_id); } // Global identifier - LocalOrGlobal::Global(self.linker.resolve_global(identifier.span, &self.errors)) + LocalOrGlobal::Global(self.linker.resolve_global(identifier_span, &self.errors)) } fn initialize_interface(&mut self) -> InterfacePorts { let ports : Box<[FlatID]> = self.module.interface.ports.iter().enumerate().map(|(idx, port_decl)|{ @@ -344,7 +447,7 @@ impl<'l> FlatteningContext<'l> { self.errors.error_basic(*name_expr_span, "Function call name must be a simple identifier"); return None; }; - let func_instantiation_id = match self.resolve_identifier(name) { + let func_instantiation_id = match self.resolve_identifier(name.span) { LocalOrGlobal::Local(id) => id, LocalOrGlobal::Global(global) => { let module_id = global.expect_module()?; @@ -389,7 +492,7 @@ impl<'l> FlatteningContext<'l> { fn flatten_expr(&mut self, (expr, expr_span) : &SpanExpression) -> FlatID { let source = match expr { Expression::Named(name) => { - match self.resolve_identifier(name) { + match self.resolve_identifier(name.span) { LocalOrGlobal::Local(id) => { WireSource::WireRead(id) } @@ -406,15 +509,45 @@ impl<'l> FlatteningContext<'l> { WireSource::Constant(cst.clone()) } Expression::UnaryOp(op_box) => { - let (op, _op_pos, operate_on) = op_box.deref(); + let (op_tok, _op_pos, operate_on) = op_box.deref(); let right = self.flatten_expr(operate_on); - WireSource::UnaryOp{op : *op, right} + let op = match op_tok.op_typ { + t if t == kw("+") => UnaryOperator::Sum, + t if t == kw("*") => UnaryOperator::Product, + t if t == kw("-") => UnaryOperator::Negate, + t if t == kw("&") => UnaryOperator::And, + t if t == kw("|") => UnaryOperator::Or, + t if t == kw("^") => UnaryOperator::Xor, + t if t == kw("!") => UnaryOperator::Not, + _ => unreachable!() + }; + WireSource::UnaryOp{op, right} } Expression::BinOp(binop_box) => { let (left_expr, op, _op_pos, right_expr) = binop_box.deref(); let left = self.flatten_expr(left_expr); let right = self.flatten_expr(right_expr); - WireSource::BinaryOp{op : *op, left, right} + + let op = match op.op_typ { + t if t == kw("&") => BinaryOperator::And, + t if t == kw("|") => BinaryOperator::Or, + t if t == kw("^") => BinaryOperator::Xor, + t if t == kw("<<") => BinaryOperator::ShiftLeft, + t if t == kw(">>") => BinaryOperator::ShiftRight, + t if t == kw("+") => BinaryOperator::Add, + t if t == kw("-") => BinaryOperator::Subtract, + t if t == kw("*") => BinaryOperator::Multiply, + t if t == kw("/") => BinaryOperator::Divide, + t if t == kw("%") => BinaryOperator::Modulo, + t if t == kw("==") => BinaryOperator::Equals, + t if t == kw("!=") => BinaryOperator::NotEquals, + t if t == kw(">") => BinaryOperator::Greater, + t if t == kw(">=") => BinaryOperator::GreaterEq, + t if t == kw("<") => BinaryOperator::Lesser, + t if t == kw("<=") => BinaryOperator::LesserEq, + _ => unreachable!() + }; + WireSource::BinaryOp{op, left, right} } Expression::Array(arr_box) => { let (left, right, _bracket_span) = arr_box.deref(); @@ -452,7 +585,7 @@ impl<'l> FlatteningContext<'l> { fn flatten_assignable_expr(&mut self, expr : &Expression, span : Span) -> Option { match expr { Expression::Named(local_idx) => { - let root = self.resolve_identifier(local_idx).expect_local("assignments")?; + let root = self.resolve_identifier(local_idx.span).expect_local("assignments")?; Some(ConnectionWrite{root, root_span : span, path : Vec::new(), span, is_declared_in_this_module : self.is_declared_in_this_module}) } @@ -587,118 +720,189 @@ impl<'l> FlatteningContext<'l> { } } - /*fn flatten_code_tree(&mut self, node : Node) { - assert_eq!(node.kind_id(), SUS.block_kind, "Was {} instead", node.kind()); + fn flatten_expr_tree(&mut self) -> FlatID { + let node = self.cursor.node(); + let expr_span : Span = node.byte_range().into(); + let kind = node.kind_id(); - let mut inner_context = FlatteningContext{ - instructions: self.instructions, - errors: self.errors, - is_declared_in_this_module: self.is_declared_in_this_module, - local_variable_context: self.local_variable_context.extend(), - linker: self.linker, - type_list_for_naming: self.type_list_for_naming, - module: self.module + let source = if kind == SUS.identifier_kind { + match self.resolve_identifier(expr_span) { + LocalOrGlobal::Local(id) => { + WireSource::WireRead(id) + } + LocalOrGlobal::Global(global) => { + if let Some(cst) = global.expect_constant() { + WireSource::NamedConstant(cst) + } else { + WireSource::Constant(Value::Error) + } + } + } + } else if kind == SUS.number_kind { + let text = &self.linker.file.file_text[expr_span]; + WireSource::Constant(Value::Integer(BigInt::from_str(text).unwrap())) + } else if kind == SUS.unary_op_kind { + self.cursor.goto_first_child(); + self.goto_field(SUS.operator_field); + let op_text = &self.linker.file.file_text[self.cursor.node().byte_range().into()]; + let op = UnaryOperator::from_text(op_text); + + self.goto_field(SUS.right_field); + let right = self.flatten_expr_tree(); + + WireSource::UnaryOp{op, right} + } else if kind == SUS.binary_op_kind { + self.goto_field(SUS.left_field); + let left = self.flatten_expr_tree(); + self.goto_field(SUS.operator_field); + let op_text = &self.linker.file.file_text[self.cursor.node().byte_range().into()]; + let op = BinaryOperator::from_text(op_text); + self.goto_field(SUS.right_field); + let right = self.flatten_expr_tree(); + + WireSource::BinaryOp{op, left, right} + } else if kind == SUS.array_op_kind { + self.goto_field(SUS.arr_field); + let arr = self.flatten_expr_tree(); + self.goto_field(SUS.arr_idx_field); + let arr_idx = self.flatten_expr_tree(); + WireSource::ArrayAccess{arr, arr_idx} + } else if kind == SUS.func_call_kind { + //todo!() + //Expression::FuncCall(func_and_args) => { + /*if let Some((md, interface_wires)) = self.desugar_func_call(func_and_args, BracketSpan::from_outer(*expr_span)) { + let output_range = interface_wires.func_call_syntax_outputs(); + + if output_range.len() != 1 { + let info = error_info(md.link_info.span, md.link_info.file, "Module Defined here"); + self.errors.error_with_info(*expr_span, "A function called in this context may only return one result. Split this function call into a separate line instead.", vec![info]); + } + + if output_range.len() >= 1 { + return interface_wires.ports[output_range.start]; + } + }*/ + // Function desugaring or using threw an error + WireSource::Constant(Value::Error) + } else { + unreachable!("Don't know yet, ERROR node? Other node? ") }; - inner_context.flatten_code_keep_context_tree(node); - } - fn flatten_code_keep_context_tree(&mut self, node : Node) { - assert_eq!(node.kind_id(), SUS.block_kind, "Was {} instead", node.kind()); - let mut cursor = node.walk(); - - for (stmt, stmt_span) in node.children_by_field_id(field_id, cursor) { - match stmt { - Statement::Assign{to, expr : Some((Expression::FuncCall(func_and_args), func_span)), eq_sign_position} => { - let Some((md, interface)) = self.desugar_func_call(&func_and_args, BracketSpan::from_outer(*func_span)) else {continue}; - let output_range = interface.func_call_syntax_outputs(); - let outputs = &interface.ports[output_range]; - let func_name_span = func_and_args[0].1; - let num_func_outputs = outputs.len(); - let num_targets = to.len(); - if num_targets != num_func_outputs { - let info = vec![error_info(md.link_info.span, md.link_info.file, "Module Defined here")]; - if num_targets > num_func_outputs { - let excess_results_span = Span::new_overarching(to[num_func_outputs].span, to.last().unwrap().span); - self.errors.error_with_info(excess_results_span, format!("Excess output targets. Function returns {num_func_outputs} results, but {num_targets} targets were given."), info); - } else { - let too_few_targets_pos = if let Some(eq) = eq_sign_position {eq.into()} else {func_name_span}; - self.errors.error_with_info(too_few_targets_pos, format!("Too few output targets. Function returns {num_func_outputs} results, but {num_targets} targets were given."), info); - } - } + let wire_instance = WireInstance{ + typ : Type::Unknown, + is_compiletime : IS_GEN_UNINIT, + span: expr_span, + source, + is_declared_in_this_module : self.is_declared_in_this_module + }; + self.instructions.alloc(Instruction::Wire(wire_instance)) + } - for (field, to_i) in zip(outputs, to) { - let module_port_wire_decl = self.instructions[*field].extract_wire_declaration(); - let module_port_proxy = self.instructions.alloc(Instruction::Wire(WireInstance{typ : module_port_wire_decl.typ.clone(), is_compiletime : IS_GEN_UNINIT, span : *func_span, is_declared_in_this_module : self.is_declared_in_this_module, source : WireSource::WireRead(*field)})); - let Some(write_side) = self.flatten_left_expr(&to_i.expr, to_i.span, true) else {continue}; + fn flatten_code_tree(&mut self) { + let old_frame = self.local_variable_context.new_frame(); + + self.flatten_code_keep_context_tree(); - let write_type = self.flatten_assignment_modifiers(&to_i.modifiers); - self.instructions.alloc(Instruction::Write(Write{write_type, from: module_port_proxy, to: write_side})); - } - }, - Statement::Assign{to, expr : non_func_expr, eq_sign_position : _} => { - let read_side = non_func_expr.as_ref().map(|some_expr| self.flatten_expr(some_expr)); - if to.len() == 1 { - let t = &to[0]; - let Some(write_side) = self.flatten_left_expr(&t.expr, t.span, non_func_expr.is_some()) else {continue}; - let write_type = self.flatten_assignment_modifiers(&t.modifiers); - if let Some(read_side) = read_side { - self.instructions.alloc(Instruction::Write(Write{write_type, from: read_side, to: write_side})); - } + self.local_variable_context.pop_frame(old_frame); + } + fn flatten_code_keep_context_tree(&mut self) { + if !self.try_go_down(SUS.block_kind) {return;} + + loop { + let cur_node = self.cursor.node(); + + let kind = cur_node.kind_id(); + if kind == SUS.decl_assign_statement_kind { + //todo!(); + //Statement::Assign{to, expr : Some((Expression::FuncCall(func_and_args), func_span)), eq_sign_position} => { + /*let Some((md, interface)) = self.desugar_func_call(&func_and_args, BracketSpan::from_outer(*func_span)) else {continue}; + let output_range = interface.func_call_syntax_outputs(); + let outputs = &interface.ports[output_range]; + + let func_name_span = func_and_args[0].1; + let num_func_outputs = outputs.len(); + let num_targets = to.len(); + if num_targets != num_func_outputs { + let info = vec![error_info(md.link_info.span, md.link_info.file, "Module Defined here")]; + if num_targets > num_func_outputs { + let excess_results_span = Span::new_overarching(to[num_func_outputs].span, to.last().unwrap().span); + self.errors.error_with_info(excess_results_span, format!("Excess output targets. Function returns {num_func_outputs} results, but {num_targets} targets were given."), info); } else { - self.errors.error_basic(*stmt_span, format!("Non-function assignments must only output exactly 1 instead of {}", to.len())); + let too_few_targets_pos = if let Some(eq) = eq_sign_position {eq.into()} else {func_name_span}; + self.errors.error_with_info(too_few_targets_pos, format!("Too few output targets. Function returns {num_func_outputs} results, but {num_targets} targets were given."), info); } - }, - Statement::Block(inner_code) => { - self.flatten_code(inner_code); - }, - Statement::If{condition : condition_expr, then, els} => { - let condition = self.flatten_expr(condition_expr); - - let if_id = self.instructions.alloc(Instruction::IfStatement(IfStatement{condition, then_start : UUID::PLACEHOLDER, then_end_else_start : UUID::PLACEHOLDER, else_end : UUID::PLACEHOLDER})); - let then_start = self.instructions.get_next_alloc_id(); + } - self.flatten_code(then); - let then_end_else_start = self.instructions.get_next_alloc_id(); - if let Some(e) = els { - self.flatten_code(e); + for (field, to_i) in zip(outputs, to) { + let module_port_wire_decl = self.instructions[*field].extract_wire_declaration(); + let module_port_proxy = self.instructions.alloc(Instruction::Wire(WireInstance{typ : module_port_wire_decl.typ.clone(), is_compiletime : IS_GEN_UNINIT, span : *func_span, is_declared_in_this_module : self.is_declared_in_this_module, source : WireSource::WireRead(*field)})); + let Some(write_side) = self.flatten_left_expr(&to_i.expr, to_i.span, true) else {continue}; + + let write_type = self.flatten_assignment_modifiers(&to_i.modifiers); + self.instructions.alloc(Instruction::Write(Write{write_type, from: module_port_proxy, to: write_side})); + }*/ + } else if kind == SUS.decl_assign_statement_kind { + //Statement::Assign{to, expr : non_func_expr, eq_sign_position : _} => { + /*let read_side = non_func_expr.as_ref().map(|some_expr| self.flatten_expr(some_expr)); + if to.len() == 1 { + let t = &to[0]; + let Some(write_side) = self.flatten_left_expr(&t.expr, t.span, non_func_expr.is_some()) else {continue}; + let write_type = self.flatten_assignment_modifiers(&t.modifiers); + if let Some(read_side) = read_side { + self.instructions.alloc(Instruction::Write(Write{write_type, from: read_side, to: write_side})); } - let else_end = self.instructions.get_next_alloc_id(); - - let Instruction::IfStatement(if_stmt) = &mut self.instructions[if_id] else {unreachable!()}; - if_stmt.then_start = then_start; - if_stmt.then_end_else_start = then_end_else_start; - if_stmt.else_end = else_end; + } else { + self.errors.error_basic(*stmt_span, format!("Non-function assignments must only output exactly 1 instead of {}", to.len())); + }*/ + } else if kind == SUS.block_kind { + //Statement::Block(inner_code) => { + self.flatten_code_tree(); + } else if kind == SUS.if_statement_kind { + //Statement::If{condition : condition_expr, then, els} => { + /*let condition = self.flatten_expr(condition_expr); + + let if_id = self.instructions.alloc(Instruction::IfStatement(IfStatement{condition, then_start : UUID::PLACEHOLDER, then_end_else_start : UUID::PLACEHOLDER, else_end : UUID::PLACEHOLDER})); + let then_start = self.instructions.get_next_alloc_id(); + + self.flatten_code(then); + let then_end_else_start = self.instructions.get_next_alloc_id(); + if let Some(e) = els { + self.flatten_code(e); } - Statement::For{var, range, code} => { - let loop_var_decl = self.flatten_declaration::(var, true, true); - - let start = self.flatten_expr(&range.from); - let end = self.flatten_expr(&range.to); - - let for_id = self.instructions.alloc(Instruction::ForStatement(ForStatement{loop_var_decl, start, end, loop_body: UUIDRange(UUID::PLACEHOLDER, UUID::PLACEHOLDER)})); + let else_end = self.instructions.get_next_alloc_id(); + + let Instruction::IfStatement(if_stmt) = &mut self.instructions[if_id] else {unreachable!()}; + if_stmt.then_start = then_start; + if_stmt.then_end_else_start = then_end_else_start; + if_stmt.else_end = else_end;*/ + } else if kind == SUS.for_statement_kind { + //Statement::For{var, range, code} => { + /*let loop_var_decl = self.flatten_declaration::(var, true, true); + + let start = self.flatten_expr(&range.from); + let end = self.flatten_expr(&range.to); + + let for_id = self.instructions.alloc(Instruction::ForStatement(ForStatement{loop_var_decl, start, end, loop_body: UUIDRange(UUID::PLACEHOLDER, UUID::PLACEHOLDER)})); - let code_start = self.instructions.get_next_alloc_id(); + let code_start = self.instructions.get_next_alloc_id(); - self.flatten_code(code); - - let code_end = self.instructions.get_next_alloc_id(); + self.flatten_code(code); + + let code_end = self.instructions.get_next_alloc_id(); - let Instruction::ForStatement(for_stmt) = &mut self.instructions[for_id] else {unreachable!()}; + let Instruction::ForStatement(for_stmt) = &mut self.instructions[for_id] else {unreachable!()}; - for_stmt.loop_body = UUIDRange(code_start, code_end); - } + for_stmt.loop_body = UUIDRange(code_start, code_end);*/ } } - }*/ + } fn flatten_interface_ports_tree(&mut self) { } - /// If field is found, cursor is now at field position - /// - /// If field is not found, cursor remains in place - fn goto_field(&mut self, field_id : NonZeroU16) -> bool { + #[must_use] + fn goto_optional_field(&mut self, field_id : NonZeroU16) -> bool { let mut shift_count = 0; loop { @@ -717,15 +921,46 @@ impl<'l> FlatteningContext<'l> { false } + /// If field is found, cursor is now at field position + /// + /// If field is not found, cursor remains in place + fn goto_field(&mut self, field_id : NonZeroU16) { + let v = self.goto_optional_field(field_id); + assert!(v); + } + + fn go_down(&mut self, kind : u16) { + let node = self.cursor.node(); + assert_eq!(node.kind_id(), kind, "Was {} instead", node.kind()); + + let r = self.cursor.goto_first_child(); + assert!(r); + } + + /// Returns true if successful + fn try_go_down(&mut self, kind : u16) -> bool { + let node = self.cursor.node(); + assert_eq!(node.kind_id(), kind, "Was {} instead", node.kind()); + + self.cursor.goto_first_child() + } + + fn go_up(&mut self) { + let r = self.cursor.goto_parent(); + assert!(r); + } + fn flatten_module_tree(&mut self) { - let module_node = self.cursor.node(); - assert_eq!(module_node.kind_id(), SUS.module_kind, "{}", module_node.kind()); + self.go_down(SUS.module_kind); + println!("TREE SITTER module!"); - //let interface = module_node.child_by_field_id(SUS.interface_ports_field); - //let code = module_node.child_by_field_id(SUS.block_field).unwrap(); - - self.flatten_interface_ports_tree(); - //self.flatten_code_tree(code); + if self.goto_optional_field(SUS.interface_ports_field) { + self.flatten_interface_ports_tree(); + } + self.goto_field(SUS.block_field); + self.flatten_code_tree(); + + self.go_up(); } diff --git a/src/instantiation/mod.rs b/src/instantiation/mod.rs index 489b52f..47c2e3b 100644 --- a/src/instantiation/mod.rs +++ b/src/instantiation/mod.rs @@ -2,7 +2,7 @@ use std::{cell::RefCell, cmp::max, iter::zip, ops::Deref, rc::Rc}; use num::BigInt; -use crate::{arena_alloc::{FlatAlloc, UUIDMarker, UUIDRange, UUID}, ast::{IdentifierType, InterfacePorts, Operator}, errors::ErrorCollector, file_position::Span, flattening::{ConnectionWritePathElement, ConnectionWritePathElementComputed, FlatID, FlatIDMarker, FlatIDRange, FlattenedModule, Instruction, WireInstance, WireSource, Write, WriteType}, instantiation::latency_algorithm::{convert_fanin_to_fanout, solve_latencies, FanInOut, LatencyCountingError}, linker::{Linker, NamedConstant}, list_of_lists::ListOfLists, tokenizer::kw, typing::{ConcreteType, Type, BOOL_CONCRETE_TYPE, INT_CONCRETE_TYPE}, value::{compute_binary_op, compute_unary_op, Value}}; +use crate::{arena_alloc::{FlatAlloc, UUIDMarker, UUIDRange, UUID}, ast::{IdentifierType, InterfacePorts}, errors::ErrorCollector, file_position::Span, flattening::{BinaryOperator, ConnectionWritePathElement, ConnectionWritePathElementComputed, FlatID, FlatIDMarker, FlatIDRange, FlattenedModule, Instruction, UnaryOperator, WireInstance, WireSource, Write, WriteType}, instantiation::latency_algorithm::{convert_fanin_to_fanout, solve_latencies, FanInOut, LatencyCountingError}, linker::{Linker, NamedConstant}, list_of_lists::ListOfLists, typing::{ConcreteType, Type, BOOL_CONCRETE_TYPE, INT_CONCRETE_TYPE}, value::{compute_binary_op, compute_unary_op, Value}}; use self::latency_algorithm::SpecifiedLatency; @@ -57,8 +57,8 @@ impl MultiplexerSource { pub enum RealWireDataSource { ReadOnly, Multiplexer{is_state : Option, sources : Vec}, - UnaryOp{op : Operator, right : WireID}, - BinaryOp{op : Operator, left : WireID, right : WireID}, + UnaryOp{op : UnaryOperator, right : WireID}, + BinaryOp{op : BinaryOperator, left : WireID, right : WireID}, ArrayAccess{arr : WireID, arr_idx : WireID}, ConstArrayAccess{arr : WireID, arr_idx : u64}, Constant{value : Value} @@ -365,12 +365,12 @@ impl<'fl, 'l> InstantiationContext<'fl, 'l> { } &WireSource::UnaryOp{op, right} => { let right = self.get_wire_or_constant_as_wire(right)?; - RealWireDataSource::UnaryOp{op: op, right} + RealWireDataSource::UnaryOp{op, right} } &WireSource::BinaryOp{op, left, right} => { let left = self.get_wire_or_constant_as_wire(left)?; let right = self.get_wire_or_constant_as_wire(right)?; - RealWireDataSource::BinaryOp{op: op, left, right} + RealWireDataSource::BinaryOp{op, left, right} } &WireSource::ArrayAccess{arr, arr_idx} => { let arr = self.get_wire_or_constant_as_wire(arr)?; @@ -400,7 +400,7 @@ impl<'fl, 'l> InstantiationContext<'fl, 'l> { name : self.get_unique_name(), original_wire, source : RealWireDataSource::BinaryOp{ - op: Operator{op_typ : kw("&")}, + op: BinaryOperator::And, left : condition, right : additional_condition }, @@ -492,7 +492,7 @@ impl<'fl, 'l> InstantiationContext<'fl, 'l> { name : self.get_unique_name(), original_wire, source : RealWireDataSource::UnaryOp{ - op : Operator{op_typ : kw("!")}, + op : UnaryOperator::Not, right : condition_wire }, absolute_latency : CALCULATE_LATENCY_LATER, needed_until : CALCULATE_LATENCY_LATER diff --git a/src/parser.rs b/src/parser.rs index 6a57805..27565db 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -806,6 +806,7 @@ pub struct SusTreeSitterSingleton { pub binary_op_kind : u16, pub array_op_kind : u16, pub func_call_kind : u16, + pub parenthesis_expression_kind : u16, pub range_kind : u16, pub block_kind : u16, pub decl_assign_statement_kind : u16, @@ -829,7 +830,7 @@ pub struct SusTreeSitterSingleton { pub operator_field : NonZeroU16, pub arr_field : NonZeroU16, pub arr_idx_field : NonZeroU16, - pub func_arguments_field : NonZeroU16, + pub argument_field : NonZeroU16, pub from_field : NonZeroU16, pub to_field : NonZeroU16, pub assign_to_field : NonZeroU16, @@ -857,6 +858,7 @@ impl SusTreeSitterSingleton { binary_op_kind : language.id_for_node_kind("binary_op", true), array_op_kind : language.id_for_node_kind("array_op", true), func_call_kind : language.id_for_node_kind("func_call", true), + parenthesis_expression_kind : language.id_for_node_kind("parenthesis_expression", true), range_kind : language.id_for_node_kind("range", true), block_kind : language.id_for_node_kind("block", true), decl_assign_statement_kind : language.id_for_node_kind("decl_assign_statement", true), @@ -880,7 +882,7 @@ impl SusTreeSitterSingleton { operator_field : language.field_id_for_name("operator").unwrap(), arr_field : language.field_id_for_name("arr").unwrap(), arr_idx_field : language.field_id_for_name("arr_idx").unwrap(), - func_arguments_field : language.field_id_for_name("func_arguments").unwrap(), + argument_field : language.field_id_for_name("argument").unwrap(), from_field : language.field_id_for_name("from").unwrap(), to_field : language.field_id_for_name("to").unwrap(), assign_to_field : language.field_id_for_name("assign_to").unwrap(), diff --git a/src/typing.rs b/src/typing.rs index a89d110..410e7c4 100644 --- a/src/typing.rs +++ b/src/typing.rs @@ -1,6 +1,6 @@ use std::ops::Deref; -use crate::{arena_alloc::ArenaAllocator, ast::Operator, errors::ErrorCollector, file_position::Span, flattening::FlatID, linker::{get_builtin_type, Linkable, Linker, NamedType, TypeUUID, TypeUUIDMarker}, tokenizer::kw, value::Value}; +use crate::{arena_alloc::ArenaAllocator, errors::ErrorCollector, file_position::Span, flattening::{BinaryOperator, FlatID, UnaryOperator}, linker::{get_builtin_type, Linkable, Linker, NamedType, TypeUUID, TypeUUIDMarker}, value::Value}; // These are #[derive(Debug, Clone)] @@ -113,20 +113,20 @@ pub const INT_TYPE : Type = Type::Named(get_builtin_type("int")); pub const BOOL_CONCRETE_TYPE : ConcreteType = ConcreteType::Named(get_builtin_type("bool")); pub const INT_CONCRETE_TYPE : ConcreteType = ConcreteType::Named(get_builtin_type("int")); -pub fn typecheck_unary_operator(op : Operator, input_typ : &Type, span : Span, linker_types : &ArenaAllocator, errors : &ErrorCollector) -> Type { - if op.op_typ == kw("!") { +pub fn typecheck_unary_operator(op : UnaryOperator, input_typ : &Type, span : Span, linker_types : &ArenaAllocator, errors : &ErrorCollector) -> Type { + if op == UnaryOperator::Not { typecheck(input_typ, span, &BOOL_TYPE, "! input", linker_types, errors); BOOL_TYPE - } else if op.op_typ == kw("-") { + } else if op == UnaryOperator::Negate { typecheck(input_typ, span, &INT_TYPE, "- input", linker_types, errors); INT_TYPE } else { - let gather_type = match op.op_typ { - x if x == kw("&") => BOOL_TYPE, - x if x == kw("|") => BOOL_TYPE, - x if x == kw("^") => BOOL_TYPE, - x if x == kw("+") => INT_TYPE, - x if x == kw("*") => INT_TYPE, + let gather_type = match op { + UnaryOperator::And => BOOL_TYPE, + UnaryOperator::Or => BOOL_TYPE, + UnaryOperator::Xor => BOOL_TYPE, + UnaryOperator::Sum => INT_TYPE, + UnaryOperator::Product => INT_TYPE, _ => unreachable!() }; if let Some(arr_content_typ) = typecheck_is_array_indexer(input_typ, span, linker_types, errors) { @@ -135,22 +135,22 @@ pub fn typecheck_unary_operator(op : Operator, input_typ : &Type, span : Span, l gather_type } } -pub fn get_binary_operator_types(op : Operator) -> ((Type, Type), Type) { - match op.op_typ { - x if x == kw("&") => ((BOOL_TYPE, BOOL_TYPE), BOOL_TYPE), - x if x == kw("|") => ((BOOL_TYPE, BOOL_TYPE), BOOL_TYPE), - x if x == kw("^") => ((BOOL_TYPE, BOOL_TYPE), BOOL_TYPE), - x if x == kw("+") => ((INT_TYPE, INT_TYPE), INT_TYPE), - x if x == kw("-") => ((INT_TYPE, INT_TYPE), INT_TYPE), - x if x == kw("*") => ((INT_TYPE, INT_TYPE), INT_TYPE), - x if x == kw("/") => ((INT_TYPE, INT_TYPE), INT_TYPE), - x if x == kw("%") => ((INT_TYPE, INT_TYPE), INT_TYPE), - x if x == kw("==") => ((INT_TYPE, INT_TYPE), BOOL_TYPE), - x if x == kw("!=") => ((INT_TYPE, INT_TYPE), BOOL_TYPE), - x if x == kw(">=") => ((INT_TYPE, INT_TYPE), BOOL_TYPE), - x if x == kw("<=") => ((INT_TYPE, INT_TYPE), BOOL_TYPE), - x if x == kw(">") => ((INT_TYPE, INT_TYPE), BOOL_TYPE), - x if x == kw("<") => ((INT_TYPE, INT_TYPE), BOOL_TYPE), +pub fn get_binary_operator_types(op : BinaryOperator) -> ((Type, Type), Type) { + match op { + BinaryOperator::And => ((BOOL_TYPE, BOOL_TYPE), BOOL_TYPE), + BinaryOperator::Or => ((BOOL_TYPE, BOOL_TYPE), BOOL_TYPE), + BinaryOperator::Xor => ((BOOL_TYPE, BOOL_TYPE), BOOL_TYPE), + BinaryOperator::Add => ((INT_TYPE, INT_TYPE), INT_TYPE), + BinaryOperator::Subtract => ((INT_TYPE, INT_TYPE), INT_TYPE), + BinaryOperator::Multiply => ((INT_TYPE, INT_TYPE), INT_TYPE), + BinaryOperator::Divide => ((INT_TYPE, INT_TYPE), INT_TYPE), + BinaryOperator::Modulo => ((INT_TYPE, INT_TYPE), INT_TYPE), + BinaryOperator::Equals => ((INT_TYPE, INT_TYPE), BOOL_TYPE), + BinaryOperator::NotEquals => ((INT_TYPE, INT_TYPE), BOOL_TYPE), + BinaryOperator::GreaterEq => ((INT_TYPE, INT_TYPE), BOOL_TYPE), + BinaryOperator::Greater => ((INT_TYPE, INT_TYPE), BOOL_TYPE), + BinaryOperator::LesserEq => ((INT_TYPE, INT_TYPE), BOOL_TYPE), + BinaryOperator::Lesser => ((INT_TYPE, INT_TYPE), BOOL_TYPE), _ => unreachable!() } } diff --git a/src/value.rs b/src/value.rs index 5d05f13..b426ee0 100644 --- a/src/value.rs +++ b/src/value.rs @@ -2,7 +2,7 @@ use std::ops::Deref; use num::BigInt; -use crate::{typing::{Type, ConcreteType, BOOL_TYPE, INT_TYPE, INT_CONCRETE_TYPE, BOOL_CONCRETE_TYPE}, ast::Operator, tokenizer::kw}; +use crate::{flattening::{BinaryOperator, UnaryOperator}, typing::{ConcreteType, Type, BOOL_CONCRETE_TYPE, BOOL_TYPE, INT_CONCRETE_TYPE, INT_TYPE}}; #[derive(Debug,Clone,PartialEq,Eq)] pub enum Value { @@ -91,59 +91,57 @@ impl Value { } } -pub fn compute_unary_op(op : Operator, v : &Value) -> Value { +pub fn compute_unary_op(op : UnaryOperator, v : &Value) -> Value { if *v == Value::Error { return Value::Error } - match op.op_typ { - typ if typ == kw("|") => { + match op { + UnaryOperator::Or => { todo!("Array Values") } - typ if typ == kw("&") => { + UnaryOperator::And => { todo!("Array Values") } - typ if typ == kw("^") => { + UnaryOperator::Xor => { todo!("Array Values") } - typ if typ == kw("-") => { - let Value::Integer(v) = v else {panic!()}; - Value::Integer(-v) + UnaryOperator::Not => { + let Value::Bool(b) = v else {panic!()}; + Value::Bool(!*b) } - typ if typ == kw("+") => { + UnaryOperator::Sum => { todo!("Array Values") } - typ if typ == kw("*") => { + UnaryOperator::Product => { todo!("Array Values") } - typ if typ == kw("!") => { - let Value::Bool(b) = v else {panic!()}; - Value::Bool(!*b) + UnaryOperator::Negate => { + let Value::Integer(v) = v else {panic!()}; + Value::Integer(-v) } - _other => unreachable!() } } -pub fn compute_binary_op(left : &Value, op : Operator, right : &Value) -> Value { +pub fn compute_binary_op(left : &Value, op : BinaryOperator, right : &Value) -> Value { if *left == Value::Error || *right == Value::Error { return Value::Error } - match op.op_typ { - typ if typ == kw("<=") => Value::Bool(left.extract_integer() <= right.extract_integer()), - typ if typ == kw(">=") => Value::Bool(left.extract_integer() >= right.extract_integer()), - typ if typ == kw("<") => Value::Bool(left.extract_integer() < right.extract_integer()), - typ if typ == kw(">") => Value::Bool(left.extract_integer() > right.extract_integer()), - typ if typ == kw("==") => Value::Bool(left == right), - typ if typ == kw("!=") => Value::Bool(left != right), - typ if typ == kw("<<") => todo!(), // Still a bit iffy about shift operator inclusion - typ if typ == kw(">>") => todo!(), - typ if typ == kw("+") => Value::Integer(left.extract_integer() + right.extract_integer()), - typ if typ == kw("-") => Value::Integer(left.extract_integer() - right.extract_integer()), - typ if typ == kw("*") => Value::Integer(left.extract_integer() * right.extract_integer()), - typ if typ == kw("/") => Value::Integer(left.extract_integer() / right.extract_integer()), - typ if typ == kw("%") => Value::Integer(left.extract_integer() % right.extract_integer()), - typ if typ == kw("&") => Value::Bool(left.extract_bool() & right.extract_bool()), - typ if typ == kw("|") => Value::Bool(left.extract_bool() & right.extract_bool()), - typ if typ == kw("^") => Value::Bool(left.extract_bool() & right.extract_bool()), - _other => unreachable!() + match op { + BinaryOperator::Equals => Value::Bool(left == right), + BinaryOperator::NotEquals => Value::Bool(left != right), + BinaryOperator::GreaterEq => Value::Bool(left.extract_integer() >= right.extract_integer()), + BinaryOperator::Greater => Value::Bool(left.extract_integer() > right.extract_integer()), + BinaryOperator::LesserEq => Value::Bool(left.extract_integer() <= right.extract_integer()), + BinaryOperator::Lesser => Value::Bool(left.extract_integer() < right.extract_integer()), + BinaryOperator::Add => Value::Integer(left.extract_integer() + right.extract_integer()), + BinaryOperator::Subtract => Value::Integer(left.extract_integer() - right.extract_integer()), + BinaryOperator::Multiply => Value::Integer(left.extract_integer() * right.extract_integer()), + BinaryOperator::Divide => Value::Integer(left.extract_integer() / right.extract_integer()), + BinaryOperator::Modulo => Value::Integer(left.extract_integer() % right.extract_integer()), + BinaryOperator::And => Value::Bool(left.extract_bool() & right.extract_bool()), + BinaryOperator::Or => Value::Bool(left.extract_bool() & right.extract_bool()), + BinaryOperator::Xor => Value::Bool(left.extract_bool() & right.extract_bool()), + BinaryOperator::ShiftLeft => todo!(), // Still a bit iffy about shift operator inclusion + BinaryOperator::ShiftRight => todo!() } } diff --git a/tree-sitter-sus b/tree-sitter-sus index be7ab81..8b4d109 160000 --- a/tree-sitter-sus +++ b/tree-sitter-sus @@ -1 +1 @@ -Subproject commit be7ab816fdead6956bc9bc18eb724eeba46bdcbf +Subproject commit 8b4d109a0168a072a8202799f3e377e56b9f3ab6