Skip to content

Commit

Permalink
Syntax highlighting now uses Flattened representation
Browse files Browse the repository at this point in the history
Finally got rid of the syntax tree walking code!
  • Loading branch information
VonTum committed Jan 5, 2024
1 parent e746ec5 commit a3bde49
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 118 deletions.
115 changes: 8 additions & 107 deletions src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use crate::{tokenizer::{TokenTypeIdx, get_token_type_name}, linker::{NamedUUID, FileUUID, Linker}, flattening::FlattenedModule, arena_alloc::{UUIDMarker, UUID, FlatAlloc}, instantiation::InstantiationList, value::Value};
use core::ops::Range;
use std::{fmt::Display, ops::Deref, cell::RefCell};
use std::{fmt::Display, cell::RefCell};

// Token span. Indices are INCLUSIVE
#[derive(Clone,Copy,Debug,PartialEq,Eq)]
Expand All @@ -21,6 +21,11 @@ impl Span {
let max = tokens[self.1].end.clone();
min..max
}
#[track_caller]
pub fn assert_is_single_token(&self) -> usize {
assert!(self.1 == self.0, "Span is not singleton! {}..{}", self.0, self.1);
self.0
}
}

impl IntoIterator for Span {
Expand All @@ -39,7 +44,8 @@ pub enum IdentifierType {
Output,
Local,
State,
Generative
Generative,
Virtual // Generated at the interfaces of submodule instantiations
}

impl From<usize> for Span {
Expand Down Expand Up @@ -175,108 +181,3 @@ pub struct GlobalReference(pub Span, pub Option<NamedUUID>); // token index, and
pub struct ASTRoot {
pub modules : Vec<Module>
}

pub trait IterIdentifiers {
fn for_each_value<F>(&self, func : &mut F) where F : FnMut(LocalOrGlobal, usize) -> ();
}

impl IterIdentifiers for SpanExpression {
fn for_each_value<F>(&self, func : &mut F) where F : FnMut(LocalOrGlobal, usize) -> () {
let (expr, span) = self;
match expr {
Expression::Named(id) => {
assert!(span.0 == span.1);
func(*id, span.0);
}
Expression::Constant(_v) => {}
Expression::UnaryOp(b) => {
let (_operator, _operator_pos, right) = &**b;
right.for_each_value(func);
}
Expression::BinOp(b) => {
let (left, _operator, _operator_pos, right) = &**b;
left.for_each_value(func);
right.for_each_value(func);
}
Expression::FuncCall(args) => {
for arg in args {
arg.for_each_value(func);
}
}
Expression::Array(b) => {
let (array, idx, _bracket_span) = &**b;
array.for_each_value(func);
idx.for_each_value(func);
}
}
}
}

impl IterIdentifiers for SpanAssignableExpression {
fn for_each_value<F>(&self, func : &mut F) where F : FnMut(LocalOrGlobal, usize) -> () {
let (expr, span) = self;
match expr {
AssignableExpression::Named{local_idx: id} => {
assert!(span.0 == span.1);
func(LocalOrGlobal::Local(*id), span.0);
}
AssignableExpression::ArrayIndex(b) => {
let (array, idx, _bracket_span) = &**b;
array.for_each_value(func);
idx.for_each_value(func);
}
}
}
}

impl IterIdentifiers for CodeBlock {
fn for_each_value<F>(&self, func : &mut F) where F : FnMut(LocalOrGlobal, usize) -> () {
for (stmt, _span) in &self.statements {
match stmt {
Statement::Assign{to, eq_sign_position : _, expr} => {
for assign_to in to {
assign_to.expr.for_each_value(func);
}
expr.for_each_value(func);
},
Statement::Block(b) => {
b.for_each_value(func);
},
Statement::Declaration(_) => {} // Declarations are handled outside of this block
Statement::If { condition, then, els } => {
condition.for_each_value(func);
then.for_each_value(func);
if let Some(e) = &els {
e.for_each_value(func);
}
}
Statement::TimelineStage(_) => {}
}
}
}
}

impl IterIdentifiers for SpanTypeExpression {
fn for_each_value<F>(&self, func : &mut F) where F : FnMut(LocalOrGlobal, usize) -> () {
match &self.0 {
TypeExpression::Named(n) => {
func(LocalOrGlobal::Global(*n), self.1.0);
}
TypeExpression::Array(arr_box) => {
let (arr, arr_idx) = arr_box.deref();
arr.for_each_value(func);
arr_idx.for_each_value(func);
}
}
}
}

impl IterIdentifiers for Module {
fn for_each_value<F>(&self, func : &mut F) where F : FnMut(LocalOrGlobal, usize) -> () {
for (pos, decl) in &self.declarations {
func(LocalOrGlobal::Local(pos), decl.span.1);
decl.typ.for_each_value(func);
}
self.code.for_each_value(func);
}
}
2 changes: 1 addition & 1 deletion src/codegen_fallback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ pub fn gen_verilog_code(md : &Module, instance : &InstantiatedModule) -> String
// Don't print named inputs and outputs, already did that in interface
match wire_decl.identifier_type {
IdentifierType::Input | IdentifierType::Output => {continue;}
IdentifierType::Local | IdentifierType::State | IdentifierType::Generative => {}
IdentifierType::Local | IdentifierType::State | IdentifierType::Generative | IdentifierType::Virtual => {}
}
}
let wire_or_reg = if let RealWireDataSource::Multiplexer{is_state: initial_value, sources: _} = &w.source {
Expand Down
1 change: 1 addition & 0 deletions src/dev_aid/lsp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ fn get_semantic_token_type_from_ide_token(tok : &IDEToken) -> u32 {
IDETokenType::Identifier(IDEIdentifierType::Value(IdentifierType::State)) => 3,
IDETokenType::Identifier(IDEIdentifierType::Value(IdentifierType::Local)) => 3,
IDETokenType::Identifier(IDEIdentifierType::Value(IdentifierType::Generative)) => 3,
IDETokenType::Identifier(IDEIdentifierType::Value(IdentifierType::Virtual)) => unreachable!(),
IDETokenType::Identifier(IDEIdentifierType::Constant) => 9, // make it 'OPERATOR'?
IDETokenType::Identifier(IDEIdentifierType::Unknown) => 2, // make it 'OPERATOR'?
IDETokenType::Identifier(IDEIdentifierType::Interface) => 7, // FUNCTION
Expand Down
33 changes: 25 additions & 8 deletions src/dev_aid/syntax_highlighting.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

use std::{ops::Range, path::PathBuf};

use crate::{ast::*, tokenizer::*, parser::*, linker::{PreLinker, FileData, Links, NamedUUID, Named, Linkable, Linker, FileUUIDMarker, FileUUID}, arena_alloc::ArenaVector};
use crate::{ast::*, tokenizer::*, parser::*, linker::{PreLinker, FileData, Links, NamedUUID, Named, Linkable, Linker, FileUUIDMarker, FileUUID}, arena_alloc::ArenaVector, flattening::{Instantiation, WireSource}};

use ariadne::FileCache;
use console::Style;
Expand Down Expand Up @@ -75,6 +75,7 @@ fn pretty_print(file_text : &str, tokens : &[Token], ide_infos : &[IDEToken]) {
IDETokenType::Identifier(IDEIdentifierType::Value(IdentifierType::Input)) => Style::new().blue().bright(),
IDETokenType::Identifier(IDEIdentifierType::Value(IdentifierType::Output)) => Style::new().blue().dim(),
IDETokenType::Identifier(IDEIdentifierType::Value(IdentifierType::Generative)) => Style::new().blue().bright().bold(),
IDETokenType::Identifier(IDEIdentifierType::Value(IdentifierType::Virtual)) => unreachable!(),
IDETokenType::Identifier(IDEIdentifierType::Constant) => Style::new().blue().bold(),
IDETokenType::Identifier(IDEIdentifierType::Type) => Style::new().magenta().bright(),
IDETokenType::Identifier(IDEIdentifierType::Interface) => Style::new().yellow(),
Expand Down Expand Up @@ -118,13 +119,29 @@ fn walk_name_color(all_objects : &[NamedUUID], links : &Links, result : &mut [ID
let object = &links.globals[*obj_uuid];
match object {
Named::Module(module) => {
module.for_each_value(&mut |name, position| {
result[position].typ = IDETokenType::Identifier(if let LocalOrGlobal::Local(l) = name {
IDEIdentifierType::Value(module.declarations[l].identifier_type)
} else {
IDEIdentifierType::Unknown
});
});
let flattened = module.flattened.borrow();
for (_id, item) in &flattened.instantiations {
match item {
Instantiation::Wire(w) => {
if let &WireSource::WireRead{from_wire} = &w.source {
let decl = flattened.instantiations[from_wire].extract_wire_declaration();
if decl.identifier_type == IdentifierType::Virtual {continue;} // Virtual wires don't appear in the program text
result[w.span.assert_is_single_token()].typ = IDETokenType::Identifier(IDEIdentifierType::Value(decl.identifier_type));
}
}
Instantiation::WireDeclaration(decl) => {
if decl.identifier_type == IdentifierType::Virtual {continue;} // Virtual wires don't appear in the program text
let Some(name_token) = decl.name_token else {continue};
result[name_token].typ = IDETokenType::Identifier(IDEIdentifierType::Value(decl.identifier_type));
}
Instantiation::Connection(conn) => {
let decl = flattened.instantiations[conn.to.root].extract_wire_declaration();
if decl.identifier_type == IdentifierType::Virtual {continue;} // Virtual wires don't appear in the program text
result[conn.to.span.0].typ = IDETokenType::Identifier(IDEIdentifierType::Value(decl.identifier_type));
}
Instantiation::SubModule(_) => {}
}
}
}
_other => {}
}
Expand Down
5 changes: 3 additions & 2 deletions src/flattening.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ impl<'l, 'm, 'fl> FlatteningContext<'l, 'm, 'fl> {
typ: port.typ.clone(),
typ_span,
read_only : port_idx >= flattened_borrow.interface.outputs_start,
identifier_type : IdentifierType::Local,
identifier_type : IdentifierType::Virtual,
name : format!("{}_{}", &name, &port.port_name).into_boxed_str(),
name_token : None
}))
Expand Down Expand Up @@ -517,7 +517,8 @@ impl FlattenedModule {
let is_input = match decl.identifier_type {
IdentifierType::Input => true,
IdentifierType::Output => false,
IdentifierType::Local | IdentifierType::State | IdentifierType::Generative => continue
IdentifierType::Local | IdentifierType::State | IdentifierType::Generative => continue,
IdentifierType::Virtual => unreachable!()
};

let typ = context.map_to_type(&decl.typ.0, &module.link_info.global_references);
Expand Down

0 comments on commit a3bde49

Please sign in to comment.