Skip to content

Commit b3f1aa6

Browse files
committed
Hand-roll the string interner
* existing libraries did not quite fit * generational and/or * reference instead of index and/or * "too complex" (different intended use) and/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 a 32-sized array of vecs to map `TypeId`s corresp. to the generic type parameter to chunks
1 parent 5166015 commit b3f1aa6

File tree

40 files changed

+862
-693
lines changed

40 files changed

+862
-693
lines changed

Cargo.lock

+1-42
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

compiler/ast/src/format.rs

+12-6
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,13 @@ impl Format for super::NumberLiteral {
431431
.field(
432432
"literal",
433433
// @Task also print span of literal
434-
&AdHoc(|f, _| write!(f, "{}", self.literal.bare.color(color_palette::INVALID))),
434+
&AdHoc(|f, _| {
435+
write!(
436+
f,
437+
"{}",
438+
self.literal.bare.to_str().color(color_palette::INVALID)
439+
)
440+
}),
435441
)
436442
.finish()
437443
}
@@ -454,7 +460,7 @@ impl Format for super::TextLiteral {
454460
.field(
455461
"literal",
456462
// @Task also print span of literal
457-
&AdHoc(|f, _| format_text_literal(&self.literal.bare, f)),
463+
&AdHoc(|f, _| format_text_literal(self.literal.bare.to_str(), f)),
458464
)
459465
.finish()
460466
}
@@ -665,7 +671,7 @@ impl Format for Identifier {
665671
FormatStruct::new(f, indentation)
666672
.name("Identifier")
667673
.finish()?;
668-
write!(f, " {}", self.as_str().color(color_palette::VERBATIM))
674+
write!(f, " {}", self.to_str().color(color_palette::VERBATIM))
669675
}
670676
}
671677

@@ -674,7 +680,7 @@ impl fmt::Display for Identifier {
674680
write!(
675681
f,
676682
"{:width$}",
677-
self.as_str(),
683+
self.to_str(),
678684
width = f.width().unwrap_or_default()
679685
)
680686
}
@@ -724,14 +730,14 @@ impl Format for super::BareAttributeArgument {
724730
FormatStruct::new(f, indentation)
725731
.name("Number-Literal")
726732
.finish()?;
727-
write!(f, " {}", number.color(color_palette::VERBATIM))
733+
write!(f, " {}", number.to_str().color(color_palette::VERBATIM))
728734
}
729735
Self::TextLiteral(text) => {
730736
FormatStruct::new(f, indentation)
731737
.name("Text-Literal")
732738
.finish()?;
733739
write!(f, " ")?;
734-
format_text_literal(text, f)
740+
format_text_literal(text.to_str(), f)
735741
}
736742
Self::Path(path) => path.format(f, indentation),
737743
Self::Named(named) => named.format(f, indentation),

compiler/ast/src/lib.rs

+15-23
Original file line numberDiff line numberDiff line change
@@ -705,12 +705,12 @@ impl Path {
705705
}
706706

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

713-
Some(&self.segments[0])
713+
Some(self.segments[0])
714714
}
715715
}
716716

@@ -791,37 +791,34 @@ impl TryFrom<BareToken> for BareHanger {
791791
}
792792

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

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

803-
pub fn as_atom(&self) -> &Atom {
804-
&self.0.bare
805-
}
806-
807-
pub fn into_atom(self) -> Atom {
804+
pub fn bare(self) -> Atom {
808805
self.0.bare
809806
}
810807

811-
pub fn as_str(&self) -> &str {
812-
self.as_atom()
808+
pub fn to_str(self) -> &'static str {
809+
self.0.bare.to_str()
813810
}
814811

815-
pub fn as_spanned_str(&self) -> Spanned<&str> {
816-
self.0.as_ref().map(|atom| &**atom)
812+
pub fn into_inner(self) -> Spanned<Atom> {
813+
self.0
817814
}
818815

819-
pub fn is_symbol(&self) -> bool {
816+
pub fn is_symbol(self) -> bool {
820817
// either all characters are symbols or none
821-
token::is_symbol(self.as_atom().chars().next().unwrap())
818+
token::is_symbol(self.to_str().chars().next().unwrap())
822819
}
823820

824-
pub fn is_word(&self) -> bool {
821+
pub fn is_word(self) -> bool {
825822
// either all characters are letters or none
826823
!self.is_symbol()
827824
}
@@ -849,12 +846,7 @@ impl TryFrom<Identifier> for Spanned<Word> {
849846
fn try_from(identifier: Identifier) -> Result<Self, Self::Error> {
850847
identifier
851848
.is_word()
852-
.then(|| {
853-
Self::new(
854-
identifier.span(),
855-
Word::new_unchecked(identifier.into_atom()),
856-
)
857-
})
849+
.then(|| Self::new(identifier.span(), Word::new_unchecked(identifier.bare())))
858850
.ok_or(())
859851
}
860852
}
@@ -867,15 +859,15 @@ impl Spanning for Identifier {
867859

868860
impl PartialEq for Identifier {
869861
fn eq(&self, other: &Self) -> bool {
870-
self.as_atom() == other.as_atom()
862+
self.bare() == other.bare()
871863
}
872864
}
873865

874866
impl Eq for Identifier {}
875867

876868
impl Hash for Identifier {
877869
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
878-
self.as_atom().hash(state);
870+
self.bare().hash(state);
879871
}
880872
}
881873

compiler/codegen_cranelift/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ cranelift-object = "0.93.1"
1313
diagnostics = { path = "../diagnostics" }
1414
hir = { path = "../hir" }
1515
session = { path = "../session" }
16+
utilities = { path = "../utilities" }

compiler/codegen_cranelift/src/lib.rs

+12-6
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@ use std::{
1515
path::{Path, PathBuf},
1616
process::Command,
1717
};
18-
19-
const PROGRAM_ENTRY_NAME: &str = "main";
18+
use utilities::PROGRAM_ENTRY;
2019

2120
pub fn compile_and_link(
2221
options: Options,
@@ -42,13 +41,20 @@ fn compile(
4241
_component_root: &hir::Declaration,
4342
session: &Session<'_>,
4443
) -> PathBuf {
44+
let program_entry_name = PROGRAM_ENTRY.to_str();
45+
4546
let isa = cranelift_native::builder()
4647
.unwrap()
4748
.finish(Flags::new(settings::builder()))
4849
.unwrap();
4950

5051
let mut module = ObjectModule::new(
51-
ObjectBuilder::new(isa, "main", cranelift_module::default_libcall_names()).unwrap(),
52+
ObjectBuilder::new(
53+
isa,
54+
program_entry_name,
55+
cranelift_module::default_libcall_names(),
56+
)
57+
.unwrap(),
5258
);
5359
let mut context = module.make_context();
5460

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

8389
let function_id = module
84-
.declare_function(PROGRAM_ENTRY_NAME, Linkage::Export, &context.func.signature)
90+
.declare_function(program_entry_name, Linkage::Export, &context.func.signature)
8591
.unwrap();
8692
module.define_function(function_id, &mut context).unwrap();
8793

8894
let product = module.finish();
8995

90-
let name = session.component().name().as_str();
96+
let name = session.component().name().to_str();
9197

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

113119
// @Task error handling!
114120
let output = Command::new("clang")

compiler/codegen_llvm/Cargo.toml

-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ publish = false
99
diagnostics = { path = "../diagnostics" }
1010
hir = { path = "../hir" }
1111
hir_format = { path = "../hir_format" }
12-
resolver = { path = "../resolver" }
1312
session = { path = "../session" }
1413
utilities = { path = "../utilities" }
1514

compiler/codegen_llvm/src/lib.rs

+6-10
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ use inkwell::{
1313
types::{FunctionType, IntType},
1414
values::{BasicValueEnum, FunctionValue, GlobalValue, IntValue, UnnamedAddress},
1515
};
16-
use resolver::ProgramEntryExt;
1716
use session::{Session, OUTPUT_FOLDER_NAME};
1817
use std::{
1918
cell::RefCell,
@@ -22,9 +21,7 @@ use std::{
2221
path::{Path, PathBuf},
2322
process::{Command, Stdio},
2423
};
25-
use utilities::{FormatError, HashMap, Str};
26-
27-
const PROGRAM_ENTRY_NAME: &str = "main";
24+
use utilities::{FormatError, HashMap, Str, PROGRAM_ENTRY};
2825

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

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

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

196192
let classification = function.expression.as_ref().map(|expression| {
@@ -220,7 +216,7 @@ impl<'a, 'ctx> Generator<'a, 'ctx> {
220216
// @Beacon @Task simplify
221217
Some((Thunk, _)) => {
222218
let name = if is_program_entry {
223-
PROGRAM_ENTRY_NAME.into()
219+
PROGRAM_ENTRY.to_str().into()
224220
} else {
225221
self.name(index)
226222
};
@@ -437,7 +433,7 @@ impl<'a, 'ctx> Generator<'a, 'ctx> {
437433
}
438434
Number(number) => Some(self.compile_number(number).into()),
439435
Text(_) => todo!("compiling text"),
440-
Binding(binding) if self.session.specials().is(&binding.0, Type::Type) => None,
436+
Binding(binding) if self.session.specials().is(binding.0, Type::Type) => None,
441437
Binding(binding) => {
442438
use hir::Index::*;
443439

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

0 commit comments

Comments
 (0)