Skip to content

Commit

Permalink
Hand-roll the string interner
Browse files Browse the repository at this point in the history
* existing libraries did not quite fit
  * generational or
  * reference instead of index or
  * "too complex" (different intended usage) or
  * didn't feature a nice way to prefill the interner
    * probably I could've hand-rolled that specific part but meh
* still no arena allocation in the compiler yet however
* gets rid of `string_cache`
* still using `internment` for interning `CanonicalPath` though that
  overhead is not worth it, we should probably hand-roll that too
  (it allocates an 32-sized array of vecs to map `TypeId`s corresp.
  to the generic type parameter to chunks
  • Loading branch information
fmease committed Apr 3, 2023
1 parent 5166015 commit 298866c
Show file tree
Hide file tree
Showing 40 changed files with 864 additions and 693 deletions.
43 changes: 1 addition & 42 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 12 additions & 6 deletions compiler/ast/src/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,13 @@ impl Format for super::NumberLiteral {
.field(
"literal",
// @Task also print span of literal
&AdHoc(|f, _| write!(f, "{}", self.literal.bare.color(color_palette::INVALID))),
&AdHoc(|f, _| {
write!(
f,
"{}",
self.literal.bare.to_str().color(color_palette::INVALID)
)
}),
)
.finish()
}
Expand All @@ -454,7 +460,7 @@ impl Format for super::TextLiteral {
.field(
"literal",
// @Task also print span of literal
&AdHoc(|f, _| format_text_literal(&self.literal.bare, f)),
&AdHoc(|f, _| format_text_literal(self.literal.bare.to_str(), f)),
)
.finish()
}
Expand Down Expand Up @@ -665,7 +671,7 @@ impl Format for Identifier {
FormatStruct::new(f, indentation)
.name("Identifier")
.finish()?;
write!(f, " {}", self.as_str().color(color_palette::VERBATIM))
write!(f, " {}", self.to_str().color(color_palette::VERBATIM))
}
}

Expand All @@ -674,7 +680,7 @@ impl fmt::Display for Identifier {
write!(
f,
"{:width$}",
self.as_str(),
self.to_str(),
width = f.width().unwrap_or_default()
)
}
Expand Down Expand Up @@ -724,14 +730,14 @@ impl Format for super::BareAttributeArgument {
FormatStruct::new(f, indentation)
.name("Number-Literal")
.finish()?;
write!(f, " {}", number.color(color_palette::VERBATIM))
write!(f, " {}", number.to_str().color(color_palette::VERBATIM))
}
Self::TextLiteral(text) => {
FormatStruct::new(f, indentation)
.name("Text-Literal")
.finish()?;
write!(f, " ")?;
format_text_literal(text, f)
format_text_literal(text.to_str(), f)
}
Self::Path(path) => path.format(f, indentation),
Self::Named(named) => named.format(f, indentation),
Expand Down
38 changes: 15 additions & 23 deletions compiler/ast/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -705,12 +705,12 @@ impl Path {
}

/// The path head if it is an identifier.
pub fn identifier_head(&self) -> Option<&Identifier> {
pub fn identifier_head(&self) -> Option<Identifier> {
if self.hanger.is_some() {
return None;
}

Some(&self.segments[0])
Some(self.segments[0])
}
}

Expand Down Expand Up @@ -791,37 +791,34 @@ impl TryFrom<BareToken> for BareHanger {
}

/// Either a [word](Word) or a symbol.
#[derive(Clone, Debug)]
#[derive(Clone, Copy, Debug)]
pub struct Identifier(Spanned<Atom>);

impl Identifier {
/// Create a new identifier without checking if it is a valid word or symbol.
// @Task swap args
pub const fn new_unchecked(atom: Atom, span: Span) -> Self {
Self(Spanned::new(span, atom))
}

pub fn as_atom(&self) -> &Atom {
&self.0.bare
}

pub fn into_atom(self) -> Atom {
pub fn bare(self) -> Atom {
self.0.bare
}

pub fn as_str(&self) -> &str {
self.as_atom()
pub fn to_str(self) -> &'static str {
self.0.bare.to_str()
}

pub fn as_spanned_str(&self) -> Spanned<&str> {
self.0.as_ref().map(|atom| &**atom)
pub fn into_inner(self) -> Spanned<Atom> {
self.0
}

pub fn is_symbol(&self) -> bool {
pub fn is_symbol(self) -> bool {
// either all characters are symbols or none
token::is_symbol(self.as_atom().chars().next().unwrap())
token::is_symbol(self.to_str().chars().next().unwrap())
}

pub fn is_word(&self) -> bool {
pub fn is_word(self) -> bool {
// either all characters are letters or none
!self.is_symbol()
}
Expand Down Expand Up @@ -849,12 +846,7 @@ impl TryFrom<Identifier> for Spanned<Word> {
fn try_from(identifier: Identifier) -> Result<Self, Self::Error> {
identifier
.is_word()
.then(|| {
Self::new(
identifier.span(),
Word::new_unchecked(identifier.into_atom()),
)
})
.then(|| Self::new(identifier.span(), Word::new_unchecked(identifier.bare())))
.ok_or(())
}
}
Expand All @@ -867,15 +859,15 @@ impl Spanning for Identifier {

impl PartialEq for Identifier {
fn eq(&self, other: &Self) -> bool {
self.as_atom() == other.as_atom()
self.bare() == other.bare()
}
}

impl Eq for Identifier {}

impl Hash for Identifier {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.as_atom().hash(state);
self.bare().hash(state);
}
}

Expand Down
1 change: 1 addition & 0 deletions compiler/codegen_cranelift/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ cranelift-object = "0.93.1"
diagnostics = { path = "../diagnostics" }
hir = { path = "../hir" }
session = { path = "../session" }
utilities = { path = "../utilities" }
18 changes: 12 additions & 6 deletions compiler/codegen_cranelift/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ use std::{
path::{Path, PathBuf},
process::Command,
};

const PROGRAM_ENTRY_NAME: &str = "main";
use utilities::PROGRAM_ENTRY;

pub fn compile_and_link(
options: Options,
Expand All @@ -42,13 +41,20 @@ fn compile(
_component_root: &hir::Declaration,
session: &Session<'_>,
) -> PathBuf {
let program_entry_name = PROGRAM_ENTRY.to_str();

let isa = cranelift_native::builder()
.unwrap()
.finish(Flags::new(settings::builder()))
.unwrap();

let mut module = ObjectModule::new(
ObjectBuilder::new(isa, "main", cranelift_module::default_libcall_names()).unwrap(),
ObjectBuilder::new(
isa,
program_entry_name,
cranelift_module::default_libcall_names(),
)
.unwrap(),
);
let mut context = module.make_context();

Expand Down Expand Up @@ -81,13 +87,13 @@ fn compile(
// println!("{}", context.func.display());

let function_id = module
.declare_function(PROGRAM_ENTRY_NAME, Linkage::Export, &context.func.signature)
.declare_function(program_entry_name, Linkage::Export, &context.func.signature)
.unwrap();
module.define_function(function_id, &mut context).unwrap();

let product = module.finish();

let name = session.component().name().as_str();
let name = session.component().name().to_str();

let path = match session.root_package() {
// @Task ensure that the build folder exists
Expand All @@ -108,7 +114,7 @@ fn compile(
// @Task support linkers other than clang
// (e.g. "`cc`", `gcc` (requires us to manually link to `libc` I think))
fn link(path: &Path, session: &Session<'_>) -> Result {
let name = session.component().name().as_str();
let name = session.component().name().to_str();

// @Task error handling!
let output = Command::new("clang")
Expand Down
1 change: 0 additions & 1 deletion compiler/codegen_llvm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ publish = false
diagnostics = { path = "../diagnostics" }
hir = { path = "../hir" }
hir_format = { path = "../hir_format" }
resolver = { path = "../resolver" }
session = { path = "../session" }
utilities = { path = "../utilities" }

Expand Down
16 changes: 6 additions & 10 deletions compiler/codegen_llvm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ use inkwell::{
types::{FunctionType, IntType},
values::{BasicValueEnum, FunctionValue, GlobalValue, IntValue, UnnamedAddress},
};
use resolver::ProgramEntryExt;
use session::{Session, OUTPUT_FOLDER_NAME};
use std::{
cell::RefCell,
Expand All @@ -22,9 +21,7 @@ use std::{
path::{Path, PathBuf},
process::{Command, Stdio},
};
use utilities::{FormatError, HashMap, Str};

const PROGRAM_ENTRY_NAME: &str = "main";
use utilities::{FormatError, HashMap, Str, PROGRAM_ENTRY};

pub fn compile_and_link(
options: Options,
Expand Down Expand Up @@ -93,7 +90,7 @@ fn compile<'ctx>(
// (e.g. "`cc`", `gcc` (requires the use of `llc`))
fn link(module: inkwell::module::Module<'_>, session: &Session<'_>) -> Result<(), LinkingError> {
let buffer = module.write_bitcode_to_memory();
let name = session.component().name().as_str();
let name = session.component().name().to_str();

let output_file_path = match session.root_package() {
// @Task ensure that the build folder exists
Expand Down Expand Up @@ -189,8 +186,7 @@ impl<'a, 'ctx> Generator<'a, 'ctx> {
let index = function.binder.index.declaration().unwrap();

// @Task somewhere store the info if we've already found the program entry or not
let is_program_entry = function.binder.as_str()
== Session::PROGRAM_ENTRY_IDENTIFIER
let is_program_entry = function.binder.bare() == PROGRAM_ENTRY
&& self.session.parent_of(index).unwrap() == self.session.component().root();

let classification = function.expression.as_ref().map(|expression| {
Expand Down Expand Up @@ -220,7 +216,7 @@ impl<'a, 'ctx> Generator<'a, 'ctx> {
// @Beacon @Task simplify
Some((Thunk, _)) => {
let name = if is_program_entry {
PROGRAM_ENTRY_NAME.into()
PROGRAM_ENTRY.to_str().into()
} else {
self.name(index)
};
Expand Down Expand Up @@ -437,7 +433,7 @@ impl<'a, 'ctx> Generator<'a, 'ctx> {
}
Number(number) => Some(self.compile_number(number).into()),
Text(_) => todo!("compiling text"),
Binding(binding) if self.session.specials().is(&binding.0, Type::Type) => None,
Binding(binding) if self.session.specials().is(binding.0, Type::Type) => None,
Binding(binding) => {
use hir::Index::*;

Expand Down Expand Up @@ -575,7 +571,7 @@ impl ExpressionExt for hir::Expression {
},
Application(_) | IntrinsicApplication(_) => Thunk,
Number(_) | Text(_) => Constant,
Binding(binding) if session.specials().is(&binding.0, Type::Type) => Constant,
Binding(binding) if session.specials().is(binding.0, Type::Type) => Constant,
// @Note we could make this more nuanced (prefering Constant if possible)
Binding(_) => Thunk,
Lambda(lambda) => Function(lambda),
Expand Down
Loading

0 comments on commit 298866c

Please sign in to comment.