Unify u32-based identifiers into common code

Create a new type Id<T> paramaterized by whatever specific class of IDs
is relevant to a domain; create stores and macros to support this; and
repace the existing Id types.
This commit is contained in:
Greg Shuflin 2021-10-25 17:13:34 -07:00
parent a3463f5519
commit d65233240a
6 changed files with 96 additions and 75 deletions

View File

@ -4,4 +4,5 @@ use_small_heuristics = "max"
imports_indent = "block"
imports_granularity = "crate"
group_imports = "stdexternalcrate"
match_arm_blocks = false
where_single_line = true

View File

@ -2,7 +2,6 @@
#![allow(clippy::enum_variant_names)]
use std::rc::Rc;
use std::fmt;
use std::convert::{AsRef, From};
mod visitor;
@ -13,41 +12,19 @@ pub use visitor::*;
use crate::derivative::Derivative;
use crate::tokenizing::Location;
use crate::identifier::{Id, define_id_kind};
/// An abstract identifier for an AST node. Note that
/// the u32 index limits the size of an AST to 2^32 nodes.
#[derive(Debug, PartialEq, Eq, Hash, Clone, Default)]
pub struct ItemId {
pub idx: u32,
define_id_kind!(ASTItem);
/*
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Default)]
pub struct ASTItem;
impl IdKind for ASTItem {
fn tag() -> &'static str { "ASTItem" }
}
*/
impl ItemId {
fn new(n: u32) -> ItemId {
ItemId { idx: n }
}
}
impl fmt::Display for ItemId {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "ItemId:{}", self.idx)
}
}
pub struct ItemIdStore {
last_idx: u32
}
impl ItemIdStore {
pub fn new() -> ItemIdStore {
ItemIdStore { last_idx: 0 }
}
pub fn fresh(&mut self) -> ItemId {
let idx = self.last_idx;
self.last_idx += 1;
ItemId::new(idx)
}
}
pub type ItemId = Id<ASTItem>;
#[derive(Derivative, Debug)]
#[derivative(PartialEq)]

View File

@ -0,0 +1,74 @@
use std::{
fmt::{self, Debug},
hash::Hash,
marker::PhantomData,
};
pub trait IdKind: Debug + Copy + Clone + Hash + PartialEq + Eq + Default {
fn tag() -> &'static str;
}
/// A generalized abstract identifier type of up to 2^32-1 entries.
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Default)]
pub struct Id<T>
where T: IdKind
{
idx: u32,
t: PhantomData<T>,
}
impl<T> Id<T>
where T: IdKind
{
fn new(n: u32) -> Self {
Self { idx: n, t: PhantomData }
}
#[allow(dead_code)]
pub fn as_u32(&self) -> u32 {
self.idx
}
}
impl<T> fmt::Display for Id<T>
where T: IdKind
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}:{}", self.idx, T::tag())
}
}
pub struct IdStore<T>
where T: IdKind
{
last_idx: u32,
t: PhantomData<T>,
}
impl<T> IdStore<T>
where T: IdKind
{
pub fn new() -> Self {
Self { last_idx: 0, t: PhantomData }
}
pub fn fresh(&mut self) -> Id<T> {
let idx = self.last_idx;
self.last_idx += 1;
Id::new(idx)
}
}
macro_rules! define_id_kind {
($name:ident) => {
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Default)]
pub struct $name;
impl crate::identifier::IdKind for $name {
fn tag() -> &'static str {
stringify!($name)
}
}
};
}
pub(crate) use define_id_kind;

View File

@ -23,10 +23,10 @@ mod tokenizing;
mod symbol_table;
mod builtin;
mod error;
//mod eval;
//mod reduced_ast;
mod reduced_ir;
mod tree_walk_eval;
#[macro_use]
mod identifier;
mod schala;

View File

@ -170,6 +170,7 @@ use crate::tokenizing::TokenKind::*;
use crate::tokenizing::Location;
use crate::ast::*;
use crate::identifier::IdStore;
/// Represents a parsing error
#[derive(Debug)]
@ -201,7 +202,7 @@ pub struct Parser {
parse_record: Vec<ParseRecord>,
parse_level: u32,
restrictions: ParserRestrictions,
id_store: ItemIdStore,
id_store: IdStore<ASTItem>,
}
@ -252,7 +253,7 @@ impl Parser {
parse_record: vec![],
parse_level: 0,
restrictions: ParserRestrictions { no_struct_literal: false },
id_store: ItemIdStore::new(),
id_store: IdStore::new(),
}
}

View File

@ -14,42 +14,10 @@ mod resolver;
mod symbol_trie;
use symbol_trie::SymbolTrie;
mod test;
use crate::identifier::{Id, IdStore, define_id_kind};
//TODO parameterize different types of ID
/// ID used for definitions
#[derive(Debug, PartialEq, Eq, Hash, Clone, Default)]
pub struct DefId {
idx: u32,
}
impl DefId {
pub fn as_u32(&self) -> u32 {
self.idx
}
}
impl fmt::Display for DefId {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "DefId:{}", self.idx)
}
}
pub struct DefIdStore {
last_idx: u32
}
impl DefIdStore {
pub fn new() -> Self {
Self { last_idx: 0 }
}
pub fn fresh(&mut self) -> DefId {
let idx = self.last_idx;
self.last_idx += 1;
DefId { idx }
}
}
define_id_kind!(DefItem);
pub type DefId = Id<DefItem>;
/// Fully-qualified symbol name
#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
@ -170,7 +138,7 @@ impl<K> NameTable<K> {
//cf. p. 150 or so of Language Implementation Patterns
pub struct SymbolTable {
def_id_store: DefIdStore,
def_id_store: IdStore<DefItem>,
/// Used for import resolution.
symbol_trie: SymbolTrie,
@ -190,7 +158,7 @@ pub struct SymbolTable {
impl SymbolTable {
pub fn new() -> SymbolTable {
SymbolTable {
def_id_store: DefIdStore::new(),
def_id_store: IdStore::new(),
symbol_trie: SymbolTrie::new(),
fq_names: NameTable::new(),
types: NameTable::new(),