conlang: Use interned strings (Sym
) for all symbols
This commit is contained in:
parent
ede00c3c86
commit
40ec9b30e4
@ -11,6 +11,8 @@
|
||||
//! - [Path]: Path expressions
|
||||
use cl_structures::span::*;
|
||||
|
||||
pub use cl_structures::arena::global_intern::Sym;
|
||||
|
||||
/// Whether a binding ([Static] or [Let]) or reference is mutable or not
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
|
||||
pub enum Mutability {
|
||||
@ -30,7 +32,7 @@ pub enum Visibility {
|
||||
// TODO: Capture token?
|
||||
/// A name
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct Identifier(pub String);
|
||||
pub struct Identifier(pub Sym);
|
||||
|
||||
/// A [Literal]: 0x42, 1e123, 2.4, "Hello"
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
|
@ -6,6 +6,7 @@ use super::{
|
||||
temp_type_impl::ConValue,
|
||||
BuiltIn, Callable,
|
||||
};
|
||||
use cl_ast::Sym;
|
||||
use std::{
|
||||
io::{stdout, Write},
|
||||
rc::Rc,
|
||||
@ -68,7 +69,7 @@ builtins! {
|
||||
Ok(match (lhs, rhs) {
|
||||
(ConValue::Empty, ConValue::Empty) => ConValue::Empty,
|
||||
(ConValue::Int(a), ConValue::Int(b)) => ConValue::Int(a + b),
|
||||
(ConValue::String(a), ConValue::String(b)) => (a.to_string() + b).into(),
|
||||
(ConValue::String(a), ConValue::String(b)) => (a.to_string() + &b.to_string()).into(),
|
||||
_ => Err(Error::TypeError)?
|
||||
})
|
||||
}
|
||||
@ -230,7 +231,7 @@ macro builtins (
|
||||
$(let [$($arg),*] = to_args(args)?;)?
|
||||
$body
|
||||
}
|
||||
fn name(&self) -> &str { stringify!($name) }
|
||||
fn name(&self) -> Sym { stringify!($name).into() }
|
||||
}
|
||||
)*
|
||||
}
|
||||
@ -242,7 +243,7 @@ macro cmp ($a:expr, $b:expr, $empty:literal, $op:tt) {
|
||||
(ConValue::Int(a), ConValue::Int(b)) => Ok(ConValue::Bool(a $op b)),
|
||||
(ConValue::Bool(a), ConValue::Bool(b)) => Ok(ConValue::Bool(a $op b)),
|
||||
(ConValue::Char(a), ConValue::Char(b)) => Ok(ConValue::Bool(a $op b)),
|
||||
(ConValue::String(a), ConValue::String(b)) => Ok(ConValue::Bool(a $op b)),
|
||||
(ConValue::String(a), ConValue::String(b)) => Ok(ConValue::Bool(a.get() $op b.get())),
|
||||
_ => Err(Error::TypeError)
|
||||
}
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ impl Interpret for Let {
|
||||
fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
|
||||
let Let { mutable: _, name: Identifier(name), ty: _, init } = self;
|
||||
let init = init.as_ref().map(|i| i.interpret(env)).transpose()?;
|
||||
env.insert(name, init);
|
||||
env.insert(*name, init);
|
||||
Ok(ConValue::Empty)
|
||||
}
|
||||
}
|
||||
@ -172,7 +172,7 @@ impl Interpret for Assign {
|
||||
};
|
||||
// Get the initializer and the tail
|
||||
let init = tail.interpret(env)?;
|
||||
let target = env.get_mut(head)?;
|
||||
let target = env.get_mut(*head)?;
|
||||
|
||||
if let AssignKind::Plain = op {
|
||||
use std::mem::discriminant as variant;
|
||||
@ -187,7 +187,7 @@ impl Interpret for Assign {
|
||||
return Ok(ConValue::Empty);
|
||||
}
|
||||
let Some(target) = target else {
|
||||
return Err(Error::NotInitialized(head.into()));
|
||||
return Err(Error::NotInitialized(*head));
|
||||
};
|
||||
|
||||
match op {
|
||||
@ -302,9 +302,9 @@ impl Interpret for Unary {
|
||||
let Unary { kind, tail } = self;
|
||||
let operand = tail.interpret(env)?;
|
||||
match kind {
|
||||
UnaryKind::Deref => env.call("deref", &[operand]),
|
||||
UnaryKind::Neg => env.call("neg", &[operand]),
|
||||
UnaryKind::Not => env.call("not", &[operand]),
|
||||
UnaryKind::Deref => env.call("deref".into(), &[operand]),
|
||||
UnaryKind::Neg => env.call("neg".into(), &[operand]),
|
||||
UnaryKind::Not => env.call("not".into(), &[operand]),
|
||||
UnaryKind::At => {
|
||||
println!("{operand}");
|
||||
Ok(operand)
|
||||
@ -335,7 +335,7 @@ impl Interpret for Path {
|
||||
if parts.len() == 1 {
|
||||
match parts.last().expect("parts should not be empty") {
|
||||
PathPart::SuperKw | PathPart::SelfKw => todo!("Path navigation"),
|
||||
PathPart::Ident(Identifier(s)) => env.get(s),
|
||||
PathPart::Ident(Identifier(name)) => env.get(*name),
|
||||
}
|
||||
} else {
|
||||
todo!("Path navigation!")
|
||||
@ -469,7 +469,7 @@ impl Interpret for For {
|
||||
loop {
|
||||
let mut env = env.frame("loop variable");
|
||||
if let Some(loop_var) = bounds.next() {
|
||||
env.insert(name, Some(loop_var.into()));
|
||||
env.insert(*name, Some(loop_var.into()));
|
||||
match pass.interpret(&mut env) {
|
||||
Err(Error::Break(value)) => return Ok(value),
|
||||
Err(Error::Continue) => continue,
|
||||
|
@ -2,6 +2,7 @@
|
||||
#![warn(clippy::all)]
|
||||
#![feature(decl_macro)]
|
||||
|
||||
use cl_ast::Sym;
|
||||
use env::Environment;
|
||||
use error::{Error, IResult};
|
||||
use interpret::Interpret;
|
||||
@ -13,7 +14,7 @@ pub trait Callable: std::fmt::Debug {
|
||||
/// The Callable is responsible for checking the argument count and validating types
|
||||
fn call(&self, interpreter: &mut Environment, args: &[ConValue]) -> IResult<ConValue>;
|
||||
/// Returns the common name of this identifier.
|
||||
fn name(&self) -> &str;
|
||||
fn name(&self) -> Sym;
|
||||
}
|
||||
|
||||
/// [BuiltIn]s are [Callable]s with bespoke definitions
|
||||
@ -25,6 +26,8 @@ pub mod temp_type_impl {
|
||||
//! Temporary implementations of Conlang values
|
||||
//!
|
||||
//! The most permanent fix is a temporary one.
|
||||
use cl_ast::Sym;
|
||||
|
||||
use super::{
|
||||
error::{Error, IResult},
|
||||
function::Function,
|
||||
@ -50,7 +53,7 @@ pub mod temp_type_impl {
|
||||
/// A unicode character
|
||||
Char(char),
|
||||
/// A string
|
||||
String(Rc<str>),
|
||||
String(Sym),
|
||||
/// A reference
|
||||
Ref(Rc<ConValue>),
|
||||
/// An Array
|
||||
@ -120,11 +123,11 @@ pub mod temp_type_impl {
|
||||
}
|
||||
|
||||
impl Callable for ConValue {
|
||||
fn name(&self) -> &str {
|
||||
fn name(&self) -> Sym {
|
||||
match self {
|
||||
ConValue::Function(func) => func.name(),
|
||||
ConValue::BuiltIn(func) => func.name(),
|
||||
_ => "",
|
||||
_ => "".into(),
|
||||
}
|
||||
}
|
||||
fn call(&self, interpreter: &mut Environment, args: &[ConValue]) -> IResult<ConValue> {
|
||||
@ -145,7 +148,7 @@ pub mod temp_type_impl {
|
||||
(Self::Int(a), Self::Int(b)) => Ok(Self::Bool(a $op b)),
|
||||
(Self::Bool(a), Self::Bool(b)) => Ok(Self::Bool(a $op b)),
|
||||
(Self::Char(a), Self::Char(b)) => Ok(Self::Bool(a $op b)),
|
||||
(Self::String(a), Self::String(b)) => Ok(Self::Bool(a $op b)),
|
||||
(Self::String(a), Self::String(b)) => Ok(Self::Bool(a.get() $op b.get())),
|
||||
_ => Err(Error::TypeError)
|
||||
}
|
||||
}
|
||||
@ -162,10 +165,16 @@ pub mod temp_type_impl {
|
||||
fn from(value: $T) -> Self { $v(value.into()) }
|
||||
})*
|
||||
}
|
||||
impl From<&Sym> for ConValue {
|
||||
fn from(value: &Sym) -> Self {
|
||||
ConValue::String(*value)
|
||||
}
|
||||
}
|
||||
from! {
|
||||
Integer => ConValue::Int,
|
||||
bool => ConValue::Bool,
|
||||
char => ConValue::Char,
|
||||
Sym => ConValue::String,
|
||||
&str => ConValue::String,
|
||||
String => ConValue::String,
|
||||
Rc<str> => ConValue::String,
|
||||
@ -202,7 +211,7 @@ pub mod temp_type_impl {
|
||||
Add: add = [
|
||||
(ConValue::Empty, ConValue::Empty) => ConValue::Empty,
|
||||
(ConValue::Int(a), ConValue::Int(b)) => ConValue::Int(a + b),
|
||||
(ConValue::String(a), ConValue::String(b)) => (a.to_string() + &b).into(),
|
||||
(ConValue::String(a), ConValue::String(b)) => (a.to_string() + &b.to_string()).into(),
|
||||
_ => Err(Error::TypeError)?
|
||||
]
|
||||
BitAnd: bitand = [
|
||||
@ -302,7 +311,7 @@ pub mod function {
|
||||
//! Represents a block of code which lives inside the Interpreter
|
||||
|
||||
use super::{Callable, ConValue, Environment, Error, IResult, Interpret};
|
||||
use cl_ast::{Function as FnDecl, Identifier, Param};
|
||||
use cl_ast::{Function as FnDecl, Identifier, Param, Sym};
|
||||
use std::rc::Rc;
|
||||
/// Represents a block of code which persists inside the Interpreter
|
||||
#[derive(Clone, Debug)]
|
||||
@ -323,8 +332,8 @@ pub mod function {
|
||||
}
|
||||
|
||||
impl Callable for Function {
|
||||
fn name(&self) -> &str {
|
||||
let FnDecl { name: Identifier(ref name), .. } = *self.decl;
|
||||
fn name(&self) -> Sym {
|
||||
let FnDecl { name: Identifier(name), .. } = *self.decl;
|
||||
name
|
||||
}
|
||||
fn call(&self, env: &mut Environment, args: &[ConValue]) -> IResult<ConValue> {
|
||||
@ -334,12 +343,12 @@ pub mod function {
|
||||
return Err(Error::ArgNumber { want: bind.len(), got: args.len() });
|
||||
}
|
||||
let Some(body) = body else {
|
||||
return Err(Error::NotDefined(name.into()));
|
||||
return Err(Error::NotDefined(*name));
|
||||
};
|
||||
// TODO: completely refactor data storage
|
||||
let mut frame = env.frame("fn args");
|
||||
for (Param { mutability: _, name: Identifier(name) }, value) in bind.iter().zip(args) {
|
||||
frame.insert(name, Some(value.clone()));
|
||||
frame.insert(*name, Some(value.clone()));
|
||||
}
|
||||
match body.interpret(&mut frame) {
|
||||
Err(Error::Return(value)) => Ok(value),
|
||||
@ -361,14 +370,14 @@ pub mod env {
|
||||
temp_type_impl::ConValue,
|
||||
BuiltIn, Callable, Interpret,
|
||||
};
|
||||
use cl_ast::{Function as FnDecl, Identifier};
|
||||
use cl_ast::{Function as FnDecl, Identifier, Sym};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
fmt::Display,
|
||||
ops::{Deref, DerefMut},
|
||||
};
|
||||
|
||||
type StackFrame = HashMap<String, Option<ConValue>>;
|
||||
type StackFrame = HashMap<Sym, Option<ConValue>>;
|
||||
|
||||
/// Implements a nested lexical scope
|
||||
#[derive(Clone, Debug)]
|
||||
@ -404,10 +413,8 @@ pub mod env {
|
||||
}
|
||||
}
|
||||
}
|
||||
fn to_hashmap(from: &[&'static dyn BuiltIn]) -> HashMap<String, Option<ConValue>> {
|
||||
from.iter()
|
||||
.map(|&v| (v.name().into(), Some(v.into())))
|
||||
.collect()
|
||||
fn to_hashmap(from: &[&'static dyn BuiltIn]) -> HashMap<Sym, Option<ConValue>> {
|
||||
from.iter().map(|&v| (v.name(), Some(v.into()))).collect()
|
||||
}
|
||||
|
||||
impl Environment {
|
||||
@ -425,7 +432,7 @@ pub mod env {
|
||||
|
||||
/// Calls a function inside the interpreter's scope,
|
||||
/// and returns the result
|
||||
pub fn call(&mut self, name: &str, args: &[ConValue]) -> IResult<ConValue> {
|
||||
pub fn call(&mut self, name: Sym, args: &[ConValue]) -> IResult<ConValue> {
|
||||
// FIXME: Clone to satisfy the borrow checker
|
||||
let function = self.get(name)?.clone();
|
||||
function.call(self, args)
|
||||
@ -439,39 +446,39 @@ pub mod env {
|
||||
/// Resolves a variable mutably.
|
||||
///
|
||||
/// Returns a mutable reference to the variable's record, if it exists.
|
||||
pub fn get_mut(&mut self, id: &str) -> IResult<&mut Option<ConValue>> {
|
||||
pub fn get_mut(&mut self, id: Sym) -> IResult<&mut Option<ConValue>> {
|
||||
for (frame, _) in self.frames.iter_mut().rev() {
|
||||
if let Some(var) = frame.get_mut(id) {
|
||||
if let Some(var) = frame.get_mut(&id) {
|
||||
return Ok(var);
|
||||
}
|
||||
}
|
||||
Err(Error::NotDefined(id.into()))
|
||||
Err(Error::NotDefined(id))
|
||||
}
|
||||
/// Resolves a variable immutably.
|
||||
///
|
||||
/// Returns a reference to the variable's contents, if it is defined and initialized.
|
||||
pub fn get(&self, id: &str) -> IResult<ConValue> {
|
||||
pub fn get(&self, id: Sym) -> IResult<ConValue> {
|
||||
for (frame, _) in self.frames.iter().rev() {
|
||||
match frame.get(id) {
|
||||
match frame.get(&id) {
|
||||
Some(Some(var)) => return Ok(var.clone()),
|
||||
Some(None) => return Err(Error::NotInitialized(id.into())),
|
||||
Some(None) => return Err(Error::NotInitialized(id)),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
Err(Error::NotDefined(id.into()))
|
||||
Err(Error::NotDefined(id))
|
||||
}
|
||||
/// Inserts a new [ConValue] into this [Environment]
|
||||
pub fn insert(&mut self, id: &str, value: Option<ConValue>) {
|
||||
pub fn insert(&mut self, id: Sym, value: Option<ConValue>) {
|
||||
if let Some((frame, _)) = self.frames.last_mut() {
|
||||
frame.insert(id.into(), value);
|
||||
frame.insert(id, value);
|
||||
}
|
||||
}
|
||||
/// A convenience function for registering a [FnDecl] as a [Function]
|
||||
pub fn insert_fn(&mut self, decl: &FnDecl) {
|
||||
let FnDecl { name: Identifier(name), .. } = decl;
|
||||
let (name, function) = (name.clone(), Some(Function::new(decl).into()));
|
||||
let (name, function) = (name, Some(Function::new(decl).into()));
|
||||
if let Some((frame, _)) = self.frames.last_mut() {
|
||||
frame.insert(name, function);
|
||||
frame.insert(*name, function);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -525,6 +532,8 @@ pub mod env {
|
||||
pub mod error {
|
||||
//! The [Error] type represents any error thrown by the [Environment](super::Environment)
|
||||
|
||||
use cl_ast::Sym;
|
||||
|
||||
use super::temp_type_impl::ConValue;
|
||||
|
||||
pub type IResult<T> = Result<T, Error>;
|
||||
@ -556,9 +565,9 @@ pub mod error {
|
||||
/// An expression is not assignable
|
||||
NotAssignable,
|
||||
/// A name was not defined in scope before being used
|
||||
NotDefined(String),
|
||||
NotDefined(Sym),
|
||||
/// A name was defined but not initialized
|
||||
NotInitialized(String),
|
||||
NotInitialized(Sym),
|
||||
/// A value was called, but is not callable
|
||||
NotCallable(ConValue),
|
||||
/// A function was called with the wrong number of arguments
|
||||
|
@ -127,7 +127,7 @@ mod macros {
|
||||
}
|
||||
|
||||
pub macro env_ne($env:ident.$var:ident, $expr:expr) {{
|
||||
let evaluated = $env.get(stringify!($var))
|
||||
let evaluated = $env.get(stringify!($var).into())
|
||||
.expect(stringify!($var should be defined and initialized));
|
||||
if !conv_cmp!(neq, evaluated, $expr) {
|
||||
panic!("assertion {} ({evaluated}) != {} failed.", stringify!($var), stringify!($expr))
|
||||
@ -135,7 +135,7 @@ mod macros {
|
||||
}}
|
||||
|
||||
pub macro env_eq($env:ident.$var:ident, $expr:expr) {{
|
||||
let evaluated = $env.get(stringify!($var))
|
||||
let evaluated = $env.get(stringify!($var).into())
|
||||
.expect(stringify!($var should be defined and initialized));
|
||||
if !conv_cmp!(eq, evaluated, $expr) {
|
||||
panic!("assertion {} ({evaluated}) == {} failed.", stringify!($var), stringify!($expr))
|
||||
@ -190,7 +190,7 @@ mod fn_declarations {
|
||||
"fn empty_fn () {\n \n}",
|
||||
format!(
|
||||
"{}",
|
||||
env.get("empty_fn")
|
||||
env.get("empty_fn".into())
|
||||
.expect(stringify!(empty_fn should be defined and initialized))
|
||||
)
|
||||
)
|
||||
|
@ -64,7 +64,8 @@ impl Fold for ModuleInliner {
|
||||
/// Traverses down the module tree, entering ever nested directories
|
||||
fn fold_module(&mut self, m: Module) -> Module {
|
||||
let Module { name, kind } = m;
|
||||
self.path.push(&name.0); // cd ./name
|
||||
let sym = name.0.get().expect("Could not get name!");
|
||||
self.path.push(sym); // cd ./name
|
||||
|
||||
let kind = self.fold_module_kind(kind);
|
||||
|
||||
|
@ -471,7 +471,7 @@ pub mod yamlify {
|
||||
}
|
||||
impl Yamlify for Fielder {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
let Self { name: Identifier(name), init } = self;
|
||||
let Self { name, init } = self;
|
||||
y.key("Fielder").pair("name", name).pair("init", init);
|
||||
}
|
||||
}
|
||||
|
@ -45,10 +45,7 @@ pub fn run(args: Args) -> Result<(), Box<dyn Error>> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn load_file(
|
||||
env: &mut Environment,
|
||||
path: impl AsRef<Path>,
|
||||
) -> Result<ConValue, Box<dyn Error>> {
|
||||
fn load_file(env: &mut Environment, path: impl AsRef<Path>) -> Result<ConValue, Box<dyn Error>> {
|
||||
let file = std::fs::read_to_string(path)?;
|
||||
let code = Parser::new(Lexer::new(&file)).file()?;
|
||||
Ok(env.eval(&code)?)
|
||||
@ -79,8 +76,8 @@ fn run_code(code: &str, env: &mut Environment) -> Result<(), Box<dyn Error>> {
|
||||
ConValue::Empty => {}
|
||||
ret => println!("{ret}"),
|
||||
}
|
||||
if env.get("main").is_ok() {
|
||||
match env.call("main", &[])? {
|
||||
if env.get("main".into()).is_ok() {
|
||||
match env.call("main".into(), &[])? {
|
||||
ConValue::Empty => {}
|
||||
ret => println!("{ret}"),
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
//! A global intern pool for strings, represented by the [GlobalSym] symbol
|
||||
//! A global intern pool for strings, represented by the [Sym] symbol
|
||||
|
||||
use super::{intern::Interner, symbol::Symbol};
|
||||
use std::{
|
||||
@ -7,19 +7,19 @@ use std::{
|
||||
sync::{OnceLock, RwLock},
|
||||
};
|
||||
|
||||
/// Holds a globally accessible [Interner] which uses [GlobalSym] as its [Symbol]
|
||||
static GLOBAL_INTERNER: OnceLock<RwLock<Interner<GlobalSym>>> = OnceLock::new();
|
||||
/// Holds a globally accessible [Interner] which uses [Sym] as its [Symbol]
|
||||
static GLOBAL_INTERNER: OnceLock<RwLock<Interner<Sym>>> = OnceLock::new();
|
||||
|
||||
/// A unique identifier corresponding to a particular interned [String].
|
||||
/// A unique identifier corresponding to a particular globally-interned [String].
|
||||
///
|
||||
/// Copies of that string can be obtained with [GlobalSym::get] or [String::try_from].
|
||||
/// Copies of that string can be obtained with [Sym::get] or [String::try_from].
|
||||
///
|
||||
/// New strings can be interned with [GlobalSym::new] or [GlobalSym::from]
|
||||
/// New strings can be interned with [Sym::new] or [Sym::from]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct GlobalSym(NonZeroU32);
|
||||
pub struct Sym(NonZeroU32);
|
||||
|
||||
impl GlobalSym {
|
||||
/// Gets the interned [GlobalSym] for the given value, or interns a new one.
|
||||
impl Sym {
|
||||
/// Gets the interned [Sym] for the given value, or interns a new one.
|
||||
///
|
||||
/// # Blocks
|
||||
/// This conversion blocks if the Global Interner lock is held.
|
||||
@ -33,25 +33,25 @@ impl GlobalSym {
|
||||
.expect("global interner should not be poisoned in another thread")
|
||||
.get_or_insert(value)
|
||||
}
|
||||
/// Gets a [GlobalSym] associated with the given string, if one already exists
|
||||
/// Gets a [Sym] associated with the given string, if one already exists
|
||||
pub fn try_from_str(value: &str) -> Option<Self> {
|
||||
GLOBAL_INTERNER.get()?.read().ok()?.get(value)
|
||||
}
|
||||
|
||||
/// Gets a copy of the value of the [GlobalSym]
|
||||
/// Gets a copy of the value of the [Sym]
|
||||
// TODO: Make this copy-less
|
||||
pub fn get(self) -> Option<String> {
|
||||
String::try_from(self).ok()
|
||||
}
|
||||
|
||||
/// Looks up the string associated with this [GlobalSym],
|
||||
/// Looks up the string associated with this [Sym],
|
||||
/// and performs a transformation on it if it exists.
|
||||
pub fn map<T>(&self, f: impl Fn(&str) -> T) -> Option<T> {
|
||||
Some(f(GLOBAL_INTERNER.get()?.read().ok()?.get_str(*self)?))
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for GlobalSym {
|
||||
impl Display for Sym {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let Some(interner) = GLOBAL_INTERNER.get() else {
|
||||
return write!(f, "[sym@{} (uninitialized)]", self.0);
|
||||
@ -66,7 +66,7 @@ impl Display for GlobalSym {
|
||||
}
|
||||
}
|
||||
|
||||
impl Symbol for GlobalSym {
|
||||
impl Symbol for Sym {
|
||||
const MAX: usize = u32::MAX as usize - 1;
|
||||
fn try_from_usize(value: usize) -> Option<Self> {
|
||||
Some(Self(NonZeroU32::try_from_usize(value)?))
|
||||
@ -76,7 +76,7 @@ impl Symbol for GlobalSym {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: AsRef<str>> From<T> for GlobalSym {
|
||||
impl<T: AsRef<str>> From<T> for Sym {
|
||||
/// Converts to this type from the input type.
|
||||
///
|
||||
/// # Blocks
|
||||
@ -89,36 +89,37 @@ impl<T: AsRef<str>> From<T> for GlobalSym {
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<GlobalSym> for String {
|
||||
type Error = GlobalSymError;
|
||||
impl TryFrom<Sym> for String {
|
||||
type Error = SymError;
|
||||
|
||||
fn try_from(value: GlobalSym) -> Result<Self, Self::Error> {
|
||||
fn try_from(value: Sym) -> Result<Self, Self::Error> {
|
||||
let Some(interner) = GLOBAL_INTERNER.get() else {
|
||||
Err(GlobalSymError::Uninitialized)?
|
||||
Err(SymError::Uninitialized)?
|
||||
};
|
||||
let Ok(interner) = interner.write() else {
|
||||
Err(GlobalSymError::Poisoned)?
|
||||
Err(SymError::Poisoned)?
|
||||
};
|
||||
match interner.get_str(value) {
|
||||
None => Err(GlobalSymError::Unseen(value)),
|
||||
None => Err(SymError::Unseen(value)),
|
||||
Some(string) => Ok(string.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Describes an error in [Sym] to [String] lookup
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum GlobalSymError {
|
||||
pub enum SymError {
|
||||
Uninitialized,
|
||||
Poisoned,
|
||||
Unseen(GlobalSym),
|
||||
Unseen(Sym),
|
||||
}
|
||||
impl std::error::Error for GlobalSymError {}
|
||||
impl Display for GlobalSymError {
|
||||
impl std::error::Error for SymError {}
|
||||
impl Display for SymError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
GlobalSymError::Uninitialized => "String pool was not initialized".fmt(f),
|
||||
GlobalSymError::Poisoned => "String pool was held by panicking thread".fmt(f),
|
||||
GlobalSymError::Unseen(sym) => {
|
||||
SymError::Uninitialized => "String pool was not initialized".fmt(f),
|
||||
SymError::Poisoned => "String pool was held by panicking thread".fmt(f),
|
||||
SymError::Unseen(sym) => {
|
||||
write!(f, "Symbol {sym:?} not present in String pool")
|
||||
}
|
||||
}
|
||||
|
@ -3,32 +3,32 @@ use super::*;
|
||||
|
||||
#[test]
|
||||
fn globalsym_from_returns_unique_value_for_unique_keys() {
|
||||
let foo_bar = GlobalSym::from("foo_bar");
|
||||
let foo_baz = GlobalSym::from("foo_baz");
|
||||
let foo_bar = Sym::from("foo_bar");
|
||||
let foo_baz = Sym::from("foo_baz");
|
||||
assert_ne!(foo_bar, foo_baz);
|
||||
assert_eq!(foo_bar, GlobalSym::from("foo_bar"));
|
||||
assert_eq!(foo_baz, GlobalSym::from("foo_baz"));
|
||||
assert_eq!(foo_bar, Sym::from("foo_bar"));
|
||||
assert_eq!(foo_baz, Sym::from("foo_baz"));
|
||||
}
|
||||
#[test]
|
||||
fn try_from_str_returns_none_before_init() {
|
||||
if let Some(value) = GlobalSym::try_from_str("") {
|
||||
if let Some(value) = Sym::try_from_str("") {
|
||||
panic!("{value}")
|
||||
}
|
||||
}
|
||||
#[test]
|
||||
fn try_from_str_returns_some_when_key_exists() {
|
||||
let _ = GlobalSym::from("foo_bar");
|
||||
assert!(dbg!(GlobalSym::try_from_str("foo_bar")).is_some());
|
||||
let _ = Sym::from("foo_bar");
|
||||
assert!(dbg!(Sym::try_from_str("foo_bar")).is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn try_from_str_returns_the_same_thing_as_globalsym_from() {
|
||||
let foo_bar = GlobalSym::from("foo_bar");
|
||||
assert_eq!(Some(foo_bar), GlobalSym::try_from_str("foo_bar"));
|
||||
let foo_bar = Sym::from("foo_bar");
|
||||
assert_eq!(Some(foo_bar), Sym::try_from_str("foo_bar"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn map_works() {
|
||||
let foo_bar = GlobalSym::from("foo_bar");
|
||||
let foo_bar = Sym::from("foo_bar");
|
||||
assert!(foo_bar.map(|sym| "foo_bar" == sym).unwrap());
|
||||
}
|
||||
|
@ -131,9 +131,6 @@ fn list_types(prj: &mut Project) {
|
||||
println!(" name\x1b[30G type");
|
||||
for (idx, Def { name, vis, kind, .. }) in prj.pool.iter().enumerate() {
|
||||
print!("{idx:3}: {vis}");
|
||||
if name.is_empty() {
|
||||
print!("\x1b[30m_\x1b[0m")
|
||||
}
|
||||
println!("{name}\x1b[30G| {kind}");
|
||||
}
|
||||
}
|
||||
|
@ -35,16 +35,16 @@ pub enum DefSource<'a> {
|
||||
}
|
||||
|
||||
impl<'a> DefSource<'a> {
|
||||
pub fn name(&self) -> Option<&'a str> {
|
||||
pub fn name(&self) -> Option<Sym> {
|
||||
match self {
|
||||
DefSource::Module(v) => Some(v.name.0.as_str()),
|
||||
DefSource::Alias(v) => Some(v.to.0.as_str()),
|
||||
DefSource::Enum(v) => Some(v.name.0.as_str()),
|
||||
DefSource::Struct(v) => Some(v.name.0.as_str()),
|
||||
DefSource::Const(v) => Some(v.name.0.as_str()),
|
||||
DefSource::Static(v) => Some(v.name.0.as_str()),
|
||||
DefSource::Function(v) => Some(v.name.0.as_str()),
|
||||
DefSource::Local(l) => Some(l.name.0.as_str()),
|
||||
DefSource::Module(v) => Some(v.name.0),
|
||||
DefSource::Alias(v) => Some(v.to.0),
|
||||
DefSource::Enum(v) => Some(v.name.0),
|
||||
DefSource::Struct(v) => Some(v.name.0),
|
||||
DefSource::Const(v) => Some(v.name.0),
|
||||
DefSource::Static(v) => Some(v.name.0),
|
||||
DefSource::Function(v) => Some(v.name.0),
|
||||
DefSource::Local(l) => Some(l.name.0),
|
||||
DefSource::Impl(_) | DefSource::Use(_) | DefSource::Ty(_) => None,
|
||||
}
|
||||
}
|
||||
|
@ -1,24 +1,24 @@
|
||||
use crate::{key::DefID, module::Module};
|
||||
use cl_ast::{Item, Meta, Visibility};
|
||||
use cl_ast::{Item, Meta, Sym, Visibility};
|
||||
use std::{fmt::Debug, str::FromStr};
|
||||
|
||||
mod display;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct Def<'a> {
|
||||
pub name: &'a str,
|
||||
pub name: Sym,
|
||||
pub vis: Visibility,
|
||||
pub meta: &'a [Meta],
|
||||
pub kind: DefKind<'a>,
|
||||
pub kind: DefKind,
|
||||
pub source: Option<&'a Item>,
|
||||
pub module: Module<'a>,
|
||||
pub module: Module,
|
||||
}
|
||||
|
||||
mod builder_functions {
|
||||
use super::*;
|
||||
|
||||
impl<'a> Def<'a> {
|
||||
pub fn set_name(&mut self, name: &'a str) -> &mut Self {
|
||||
pub fn set_name(&mut self, name: Sym) -> &mut Self {
|
||||
self.name = name;
|
||||
self
|
||||
}
|
||||
@ -30,7 +30,7 @@ mod builder_functions {
|
||||
self.meta = meta;
|
||||
self
|
||||
}
|
||||
pub fn set_kind(&mut self, kind: DefKind<'a>) -> &mut Self {
|
||||
pub fn set_kind(&mut self, kind: DefKind) -> &mut Self {
|
||||
self.kind = kind;
|
||||
self
|
||||
}
|
||||
@ -38,7 +38,7 @@ mod builder_functions {
|
||||
self.source = Some(source);
|
||||
self
|
||||
}
|
||||
pub fn set_module(&mut self, module: Module<'a>) -> &mut Self {
|
||||
pub fn set_module(&mut self, module: Module) -> &mut Self {
|
||||
self.module = module;
|
||||
self
|
||||
}
|
||||
@ -48,7 +48,7 @@ mod builder_functions {
|
||||
impl Default for Def<'_> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
name: Default::default(),
|
||||
name: "".into(),
|
||||
vis: Visibility::Public,
|
||||
meta: Default::default(),
|
||||
kind: Default::default(),
|
||||
@ -59,7 +59,7 @@ impl Default for Def<'_> {
|
||||
}
|
||||
|
||||
#[derive(Clone, Default, Debug, PartialEq, Eq)]
|
||||
pub enum DefKind<'a> {
|
||||
pub enum DefKind {
|
||||
/// An unevaluated definition
|
||||
#[default]
|
||||
Undecided,
|
||||
@ -68,7 +68,7 @@ pub enum DefKind<'a> {
|
||||
/// A use tree, and its parent
|
||||
Use(DefID),
|
||||
/// A type, such as a `type`, `struct`, or `enum`
|
||||
Type(TypeKind<'a>),
|
||||
Type(TypeKind),
|
||||
/// A value, such as a `const`, `static`, or `fn`
|
||||
Value(ValueKind),
|
||||
}
|
||||
@ -84,13 +84,13 @@ pub enum ValueKind {
|
||||
/// A [TypeKind] represents an item in the Type Namespace
|
||||
/// (a component of a [Project](crate::project::Project)).
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum TypeKind<'a> {
|
||||
pub enum TypeKind {
|
||||
/// An alias for an already-defined type
|
||||
Alias(Option<DefID>),
|
||||
/// A primitive type, built-in to the compiler
|
||||
Intrinsic(Intrinsic),
|
||||
/// A user-defined aromatic data type
|
||||
Adt(Adt<'a>),
|
||||
Adt(Adt),
|
||||
/// A reference to an already-defined type: &T
|
||||
Ref(u16, DefID),
|
||||
/// A contiguous view of dynamically sized memory
|
||||
@ -113,16 +113,16 @@ pub enum TypeKind<'a> {
|
||||
|
||||
/// A user-defined Aromatic Data Type
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum Adt<'a> {
|
||||
pub enum Adt {
|
||||
/// A union-like enum type
|
||||
Enum(Vec<(&'a str, Option<DefID>)>),
|
||||
Enum(Vec<(Sym, Option<DefID>)>),
|
||||
/// A C-like enum
|
||||
CLikeEnum(Vec<(&'a str, u128)>),
|
||||
CLikeEnum(Vec<(Sym, u128)>),
|
||||
/// An enum with no fields, which can never be constructed
|
||||
FieldlessEnum,
|
||||
|
||||
/// A structural product type with named members
|
||||
Struct(Vec<(&'a str, Visibility, DefID)>),
|
||||
Struct(Vec<(Sym, Visibility, DefID)>),
|
||||
/// A structural product type with unnamed members
|
||||
TupleStruct(Vec<(Visibility, DefID)>),
|
||||
/// A structural product type of neither named nor unnamed members
|
||||
@ -130,7 +130,7 @@ pub enum Adt<'a> {
|
||||
|
||||
/// A choose your own undefined behavior type
|
||||
/// TODO: should unions be a language feature?
|
||||
Union(Vec<(&'a str, DefID)>),
|
||||
Union(Vec<(Sym, DefID)>),
|
||||
}
|
||||
|
||||
/// The set of compiler-intrinsic types.
|
||||
|
@ -44,7 +44,7 @@ impl Display for Def<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for DefKind<'_> {
|
||||
impl Display for DefKind {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
DefKind::Undecided => write!(f, "undecided"),
|
||||
@ -66,7 +66,7 @@ impl std::fmt::Display for ValueKind {
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for TypeKind<'_> {
|
||||
impl Display for TypeKind {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
TypeKind::Alias(def) => match def {
|
||||
@ -99,7 +99,7 @@ impl Display for TypeKind<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Adt<'_> {
|
||||
impl Display for Adt {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Adt::Enum(variants) => {
|
||||
|
@ -1,5 +1,6 @@
|
||||
//! A [Module] is a node in the Module Tree (a component of a
|
||||
//! [Project](crate::project::Project))
|
||||
use cl_ast::Sym;
|
||||
use cl_structures::intern_pool::InternKey;
|
||||
|
||||
use crate::key::DefID;
|
||||
@ -8,14 +9,14 @@ use std::collections::HashMap;
|
||||
/// A [Module] is a node in the Module Tree (a component of a
|
||||
/// [Project](crate::project::Project)).
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq)]
|
||||
pub struct Module<'a> {
|
||||
pub struct Module {
|
||||
pub parent: Option<DefID>,
|
||||
pub types: HashMap<&'a str, DefID>,
|
||||
pub values: HashMap<&'a str, DefID>,
|
||||
pub types: HashMap<Sym, DefID>,
|
||||
pub values: HashMap<Sym, DefID>,
|
||||
pub imports: Vec<DefID>,
|
||||
}
|
||||
|
||||
impl<'a> Module<'a> {
|
||||
impl Module {
|
||||
pub fn new(parent: DefID) -> Self {
|
||||
Self { parent: Some(parent), ..Default::default() }
|
||||
}
|
||||
@ -23,29 +24,29 @@ impl<'a> Module<'a> {
|
||||
Self { parent, ..Default::default() }
|
||||
}
|
||||
|
||||
pub fn get(&self, name: &'a str) -> (Option<DefID>, Option<DefID>) {
|
||||
pub fn get(&self, name: Sym) -> (Option<DefID>, Option<DefID>) {
|
||||
(self.get_type(name), self.get_value(name))
|
||||
}
|
||||
pub fn get_type(&self, name: &'a str) -> Option<DefID> {
|
||||
self.types.get(name).copied()
|
||||
pub fn get_type(&self, name: Sym) -> Option<DefID> {
|
||||
self.types.get(&name).copied()
|
||||
}
|
||||
pub fn get_value(&self, name: &'a str) -> Option<DefID> {
|
||||
self.values.get(name).copied()
|
||||
pub fn get_value(&self, name: Sym) -> Option<DefID> {
|
||||
self.values.get(&name).copied()
|
||||
}
|
||||
|
||||
/// Inserts a type with the provided [name](str) and [id](DefID)
|
||||
pub fn insert_type(&mut self, name: &'a str, id: DefID) -> Option<DefID> {
|
||||
pub fn insert_type(&mut self, name: Sym, id: DefID) -> Option<DefID> {
|
||||
self.types.insert(name, id)
|
||||
}
|
||||
|
||||
/// Inserts a value with the provided [name](str) and [id](DefID)
|
||||
pub fn insert_value(&mut self, name: &'a str, id: DefID) -> Option<DefID> {
|
||||
pub fn insert_value(&mut self, name: Sym, id: DefID) -> Option<DefID> {
|
||||
self.values.insert(name, id)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Module<'_> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
impl std::fmt::Display for Module {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
let Self { parent, types, values, imports } = self;
|
||||
if let Some(parent) = parent {
|
||||
writeln!(f, "Parent: {}", parent.get())?;
|
||||
|
@ -50,8 +50,8 @@ impl<'a> NameCollectable<'a> for Module {
|
||||
let Self { name: Identifier(name), kind } = self;
|
||||
let module =
|
||||
c.pool
|
||||
.insert(Def { name, module: Mod::new(parent), ..Default::default() });
|
||||
c[parent].module.types.insert(name, module);
|
||||
.insert(Def { name: *name, module: Mod::new(parent), ..Default::default() });
|
||||
c[parent].module.types.insert(*name, module);
|
||||
|
||||
match kind {
|
||||
ModuleKind::Inline(file) => file.collect(c, module)?,
|
||||
@ -87,10 +87,10 @@ impl<'a> NameCollectable<'a> for Alias {
|
||||
fn collect(&'a self, c: &mut Prj<'a>, parent: DefID) -> Result<DefID, &'static str> {
|
||||
let Alias { to: Identifier(name), .. } = self;
|
||||
|
||||
let def = Def { name, module: Mod::new(parent), ..Default::default() };
|
||||
let def = Def { name: *name, module: Mod::new(parent), ..Default::default() };
|
||||
let id = c.pool.insert(def);
|
||||
|
||||
c[parent].module.types.insert(name, id);
|
||||
c[parent].module.types.insert(*name, id);
|
||||
Ok(id)
|
||||
}
|
||||
}
|
||||
@ -98,10 +98,10 @@ impl<'a> NameCollectable<'a> for Enum {
|
||||
fn collect(&'a self, c: &mut Prj<'a>, parent: DefID) -> Result<DefID, &'static str> {
|
||||
let Enum { name: Identifier(name), .. } = self;
|
||||
|
||||
let def = Def { name, module: Mod::new(parent), ..Default::default() };
|
||||
let def = Def { name: *name, module: Mod::new(parent), ..Default::default() };
|
||||
let id = c.pool.insert(def);
|
||||
|
||||
c[parent].module.types.insert(name, id);
|
||||
c[parent].module.types.insert(*name, id);
|
||||
Ok(id)
|
||||
}
|
||||
}
|
||||
@ -109,10 +109,10 @@ impl<'a> NameCollectable<'a> for Struct {
|
||||
fn collect(&'a self, c: &mut Prj<'a>, parent: DefID) -> Result<DefID, &'static str> {
|
||||
let Struct { name: Identifier(name), .. } = self;
|
||||
|
||||
let def = Def { name, module: Mod::new(parent), ..Default::default() };
|
||||
let def = Def { name: *name, module: Mod::new(parent), ..Default::default() };
|
||||
let id = c.pool.insert(def);
|
||||
|
||||
c[parent].module.types.insert(name, id);
|
||||
c[parent].module.types.insert(*name, id);
|
||||
Ok(id)
|
||||
}
|
||||
}
|
||||
@ -122,10 +122,10 @@ impl<'a> NameCollectable<'a> for Const {
|
||||
|
||||
let kind = DefKind::Undecided;
|
||||
|
||||
let def = Def { name, kind, module: Mod::new(parent), ..Default::default() };
|
||||
let def = Def { name: *name, kind, module: Mod::new(parent), ..Default::default() };
|
||||
let id = c.pool.insert(def);
|
||||
|
||||
c[parent].module.values.insert(name, id);
|
||||
c[parent].module.values.insert(*name, id);
|
||||
init.collect(c, id)?;
|
||||
|
||||
Ok(id)
|
||||
@ -137,10 +137,10 @@ impl<'a> NameCollectable<'a> for Static {
|
||||
|
||||
let kind = DefKind::Undecided;
|
||||
|
||||
let def = Def { name, kind, module: Mod::new(parent), ..Default::default() };
|
||||
let def = Def { name: *name, kind, module: Mod::new(parent), ..Default::default() };
|
||||
let id = c.pool.insert(def);
|
||||
|
||||
c[parent].module.values.insert(name, id);
|
||||
c[parent].module.values.insert(*name, id);
|
||||
init.collect(c, id)?;
|
||||
|
||||
Ok(id)
|
||||
@ -152,10 +152,10 @@ impl<'a> NameCollectable<'a> for Function {
|
||||
|
||||
let kind = DefKind::Undecided;
|
||||
|
||||
let def = Def { name, kind, module: Mod::new(parent), ..Default::default() };
|
||||
let def = Def { name: *name, kind, module: Mod::new(parent), ..Default::default() };
|
||||
let id = c.pool.insert(def);
|
||||
|
||||
c[parent].module.values.insert(name, id);
|
||||
c[parent].module.values.insert(*name, id);
|
||||
body.collect(c, id)?;
|
||||
|
||||
Ok(id)
|
||||
|
@ -18,7 +18,7 @@ use self::evaluate::EvaluableTypeExpression;
|
||||
pub struct Project<'a> {
|
||||
pub pool: Pool<Def<'a>, DefID>,
|
||||
/// Stores anonymous tuples, function pointer types, etc.
|
||||
pub anon_types: HashMap<TypeKind<'a>, DefID>,
|
||||
pub anon_types: HashMap<TypeKind, DefID>,
|
||||
pub root: DefID,
|
||||
}
|
||||
|
||||
@ -32,21 +32,21 @@ impl Default for Project<'_> {
|
||||
fn default() -> Self {
|
||||
let mut pool = Pool::default();
|
||||
let root = pool.insert(Def {
|
||||
name: "🌳 root 🌳",
|
||||
name: "🌳 root 🌳".into(),
|
||||
kind: DefKind::Type(TypeKind::Module),
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
// Insert the Never(!) type
|
||||
let never = pool.insert(Def {
|
||||
name: "!",
|
||||
name: "!".into(),
|
||||
vis: Visibility::Public,
|
||||
kind: DefKind::Type(TypeKind::Never),
|
||||
module: module::Module::new(root),
|
||||
..Default::default()
|
||||
});
|
||||
let empty = pool.insert(Def {
|
||||
name: "()",
|
||||
name: "()".into(),
|
||||
vis: Visibility::Public,
|
||||
kind: DefKind::Type(TypeKind::Empty),
|
||||
module: module::Module::new(root),
|
||||
@ -54,7 +54,7 @@ impl Default for Project<'_> {
|
||||
});
|
||||
// TODO: Self is not a real type!
|
||||
let selfty = pool.insert(Def {
|
||||
name: "Self",
|
||||
name: "Self".into(),
|
||||
vis: Visibility::Public,
|
||||
kind: DefKind::Type(TypeKind::SelfTy),
|
||||
module: module::Module::new(root),
|
||||
@ -92,11 +92,11 @@ impl<'a> Project<'a> {
|
||||
match path.as_ref() {
|
||||
[] => Some((Some(within), None, path)),
|
||||
[PathPart::Ident(Identifier(name))] => {
|
||||
let (ty, val) = self[within].module.get(name);
|
||||
let (ty, val) = self[within].module.get(*name);
|
||||
Some((ty, val, path.pop_front()?))
|
||||
}
|
||||
[PathPart::Ident(Identifier(name)), ..] => {
|
||||
let ty = self[within].module.get_type(name)?;
|
||||
let ty = self[within].module.get_type(*name)?;
|
||||
self.get(path.pop_front()?, ty)
|
||||
}
|
||||
[PathPart::SelfKw, ..] => self.get(path.pop_front()?, within),
|
||||
@ -114,7 +114,7 @@ impl<'a> Project<'a> {
|
||||
match front {
|
||||
PathPart::SelfKw => self.get_type(path.pop_front()?, within),
|
||||
PathPart::SuperKw => self.get_type(path.pop_front()?, module.parent?),
|
||||
PathPart::Ident(Identifier(name)) => match module.types.get(name.as_str()) {
|
||||
PathPart::Ident(Identifier(name)) => match module.types.get(name) {
|
||||
Some(&submodule) => self.get_type(path.pop_front()?, submodule),
|
||||
None => Some((within, path)),
|
||||
},
|
||||
@ -127,7 +127,7 @@ impl<'a> Project<'a> {
|
||||
pub fn get_value<'p>(&self, path: Path<'p>, within: DefID) -> Option<(DefID, Path<'p>)> {
|
||||
match path.front()? {
|
||||
PathPart::Ident(Identifier(name)) => Some((
|
||||
self[within].module.values.get(name.as_str()).copied()?,
|
||||
self[within].module.values.get(name).copied()?,
|
||||
path.pop_front()?,
|
||||
)),
|
||||
_ => None,
|
||||
@ -139,7 +139,7 @@ impl<'a> Project<'a> {
|
||||
/// Assumes `kind` uniquely identifies the type!
|
||||
pub fn insert_anonymous_type(
|
||||
&mut self,
|
||||
kind: TypeKind<'a>,
|
||||
kind: TypeKind,
|
||||
def: impl FnOnce() -> Def<'a>,
|
||||
) -> DefID {
|
||||
*(self
|
||||
@ -171,7 +171,7 @@ pub mod evaluate {
|
||||
//! or an intermediate result of expression evaluation.
|
||||
|
||||
use super::*;
|
||||
use cl_ast::Ty;
|
||||
use cl_ast::{Sym, Ty};
|
||||
|
||||
/// Things that can be evaluated as a type expression
|
||||
pub trait EvaluableTypeExpression {
|
||||
@ -203,8 +203,7 @@ pub mod evaluate {
|
||||
if path.is_empty() {
|
||||
id
|
||||
} else {
|
||||
let (id, path) =
|
||||
prj.get_value(path, id).ok_or("Failed to get value")?;
|
||||
let (id, path) = prj.get_value(path, id).ok_or("Failed to get value")?;
|
||||
path.is_empty()
|
||||
.then_some(id)
|
||||
.ok_or("Path not fully resolved")?
|
||||
@ -220,7 +219,7 @@ pub mod evaluate {
|
||||
}
|
||||
}
|
||||
|
||||
impl EvaluableTypeExpression for str {
|
||||
impl EvaluableTypeExpression for Sym {
|
||||
type Out = DefID;
|
||||
|
||||
fn evaluate(&self, prj: &mut Project, parent: DefID) -> Result<Self::Out, String> {
|
||||
@ -298,7 +297,7 @@ pub mod evaluate {
|
||||
.parent_of(parent)
|
||||
.ok_or_else(|| "Attempt to get super of root".into()),
|
||||
PathPart::SelfKw => Ok(parent),
|
||||
PathPart::Ident(Identifier(name)) => name.as_str().evaluate(prj, parent),
|
||||
PathPart::Ident(Identifier(name)) => name.evaluate(prj, parent),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ pub trait TypeResolvable<'a> {
|
||||
}
|
||||
|
||||
impl<'a> TypeResolvable<'a> for Item {
|
||||
type Out = DefKind<'a>;
|
||||
type Out = DefKind;
|
||||
fn resolve_type(&'a self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
|
||||
let Self { attrs: Attrs { meta }, kind, .. } = self;
|
||||
for meta in meta {
|
||||
@ -58,11 +58,12 @@ impl<'a> TypeResolvable<'a> for Item {
|
||||
}
|
||||
|
||||
impl<'a> TypeResolvable<'a> for Meta {
|
||||
type Out = DefKind<'a>;
|
||||
type Out = DefKind;
|
||||
|
||||
#[allow(unused_variables)]
|
||||
fn resolve_type(&'a self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
|
||||
let Self { name: Identifier(name), kind } = self;
|
||||
let name = name.get().unwrap_or_default();
|
||||
match (name.as_str(), kind) {
|
||||
("intrinsic", MetaKind::Equals(Literal::String(intrinsic))) => Ok(DefKind::Type(
|
||||
TypeKind::Intrinsic(intrinsic.parse().map_err(|_| "unknown intrinsic type")?),
|
||||
@ -76,7 +77,7 @@ impl<'a> TypeResolvable<'a> for Meta {
|
||||
}
|
||||
|
||||
impl<'a> TypeResolvable<'a> for ItemKind {
|
||||
type Out = DefKind<'a>;
|
||||
type Out = DefKind;
|
||||
fn resolve_type(&'a self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
|
||||
if prj[id].source.map(|s| &s.kind as *const _) != Some(self as *const _) {
|
||||
return Err("id is not self!");
|
||||
@ -96,7 +97,7 @@ impl<'a> TypeResolvable<'a> for ItemKind {
|
||||
}
|
||||
|
||||
impl<'a> TypeResolvable<'a> for Module {
|
||||
type Out = DefKind<'a>;
|
||||
type Out = DefKind;
|
||||
#[allow(unused_variables)]
|
||||
fn resolve_type(&'a self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
|
||||
Ok(DefKind::Type(TypeKind::Module))
|
||||
@ -104,7 +105,7 @@ impl<'a> TypeResolvable<'a> for Module {
|
||||
}
|
||||
|
||||
impl<'a> TypeResolvable<'a> for Impl {
|
||||
type Out = DefKind<'a>;
|
||||
type Out = DefKind;
|
||||
|
||||
fn resolve_type(&'a self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
|
||||
let parent = prj.parent_of(id).unwrap_or(id);
|
||||
@ -122,7 +123,7 @@ impl<'a> TypeResolvable<'a> for Impl {
|
||||
}
|
||||
|
||||
impl<'a> TypeResolvable<'a> for Use {
|
||||
type Out = DefKind<'a>;
|
||||
type Out = DefKind;
|
||||
|
||||
fn resolve_type(&'a self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
|
||||
todo!("Resolve types for {self} with ID {id} in {prj:?}")
|
||||
@ -130,7 +131,7 @@ impl<'a> TypeResolvable<'a> for Use {
|
||||
}
|
||||
|
||||
impl<'a> TypeResolvable<'a> for Alias {
|
||||
type Out = DefKind<'a>;
|
||||
type Out = DefKind;
|
||||
|
||||
fn resolve_type(&'a self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
|
||||
let parent = prj.parent_of(id).unwrap_or(id);
|
||||
@ -149,7 +150,7 @@ impl<'a> TypeResolvable<'a> for Alias {
|
||||
}
|
||||
|
||||
impl<'a> TypeResolvable<'a> for Enum {
|
||||
type Out = DefKind<'a>;
|
||||
type Out = DefKind;
|
||||
|
||||
fn resolve_type(&'a self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
|
||||
let Self { name: _, kind } = self;
|
||||
@ -159,7 +160,7 @@ impl<'a> TypeResolvable<'a> for Enum {
|
||||
let mut fields = vec![];
|
||||
for v @ Variant { name: Identifier(name), kind: _ } in v {
|
||||
let id = v.resolve_type(prj, id)?;
|
||||
fields.push((name.as_str(), id))
|
||||
fields.push((*name, id))
|
||||
}
|
||||
Ok(DefKind::Type(TypeKind::Adt(Adt::Enum(fields))))
|
||||
}
|
||||
@ -185,7 +186,7 @@ impl<'a> TypeResolvable<'a> for Variant {
|
||||
};
|
||||
|
||||
let def = Def {
|
||||
name,
|
||||
name: *name,
|
||||
kind: DefKind::Type(TypeKind::Adt(adt)),
|
||||
module: module::Module::new(id),
|
||||
..Default::default()
|
||||
@ -193,14 +194,14 @@ impl<'a> TypeResolvable<'a> for Variant {
|
||||
|
||||
let new_id = prj.pool.insert(def);
|
||||
// Insert the struct variant type into the enum's namespace
|
||||
prj[id].module.types.insert(name, new_id);
|
||||
prj[id].module.types.insert(*name, new_id);
|
||||
|
||||
Ok(Some(new_id))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> TypeResolvable<'a> for Struct {
|
||||
type Out = DefKind<'a>;
|
||||
type Out = DefKind;
|
||||
fn resolve_type(&'a self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
|
||||
let parent = prj.parent_of(id).unwrap_or(id);
|
||||
let Self { name: _, kind } = self;
|
||||
@ -225,7 +226,7 @@ impl<'a> TypeResolvable<'a> for Struct {
|
||||
}
|
||||
|
||||
impl<'a> TypeResolvable<'a> for StructMember {
|
||||
type Out = (&'a str, Visibility, DefID);
|
||||
type Out = (Sym, Visibility, DefID);
|
||||
|
||||
fn resolve_type(&'a self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
|
||||
let parent = prj.parent_of(id).unwrap_or(id);
|
||||
@ -235,12 +236,12 @@ impl<'a> TypeResolvable<'a> for StructMember {
|
||||
.evaluate(prj, parent)
|
||||
.map_err(|_| "Invalid type while resolving StructMember")?;
|
||||
|
||||
Ok((name, *vis, ty))
|
||||
Ok((*name, *vis, ty))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> TypeResolvable<'a> for Const {
|
||||
type Out = DefKind<'a>;
|
||||
type Out = DefKind;
|
||||
|
||||
fn resolve_type(&'a self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
|
||||
let Self { ty, .. } = self;
|
||||
@ -251,7 +252,7 @@ impl<'a> TypeResolvable<'a> for Const {
|
||||
}
|
||||
}
|
||||
impl<'a> TypeResolvable<'a> for Static {
|
||||
type Out = DefKind<'a>;
|
||||
type Out = DefKind;
|
||||
|
||||
fn resolve_type(&'a self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
|
||||
let parent = prj.parent_of(id).unwrap_or(id);
|
||||
@ -264,7 +265,7 @@ impl<'a> TypeResolvable<'a> for Static {
|
||||
}
|
||||
|
||||
impl<'a> TypeResolvable<'a> for Function {
|
||||
type Out = DefKind<'a>;
|
||||
type Out = DefKind;
|
||||
|
||||
fn resolve_type(&'a self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
|
||||
let parent = prj.parent_of(id).unwrap_or(id);
|
||||
|
@ -1,5 +1,5 @@
|
||||
//! WIP use-item importer. This performs eager import resolution on the AST
|
||||
//!
|
||||
//!
|
||||
//! # TODOs:
|
||||
//! - [ ] Resolve imports using a graph traversal rather than linear iteration
|
||||
//! - [ ] Separate imported items from natively declared items
|
||||
@ -7,7 +7,6 @@
|
||||
//! - [ ] Report errors in a meaningful way
|
||||
//! - [ ] Lazy import resolution using graph-edge traversal during name lookup?
|
||||
//! - It doesn't seem to me like the imports in a given scope *can change*.
|
||||
//!
|
||||
|
||||
#![allow(unused)]
|
||||
use std::fmt::format;
|
||||
@ -74,20 +73,15 @@ impl<'a> Project<'a> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn visit_use_leaf(
|
||||
&mut self,
|
||||
part: &'a Identifier,
|
||||
parent: DefID,
|
||||
c: DefID,
|
||||
) -> UseResult {
|
||||
pub fn visit_use_leaf(&mut self, part: &'a Identifier, parent: DefID, c: DefID) -> UseResult {
|
||||
let Identifier(name) = part;
|
||||
self.visit_use_alias(name, name, parent, c)
|
||||
}
|
||||
|
||||
pub fn visit_use_alias(
|
||||
&mut self,
|
||||
from: &'a str,
|
||||
name: &'a str,
|
||||
from: &Sym,
|
||||
name: &Sym,
|
||||
parent: DefID,
|
||||
c: DefID,
|
||||
) -> UseResult {
|
||||
@ -100,12 +94,12 @@ impl<'a> Project<'a> {
|
||||
let parent = &mut self[parent].module;
|
||||
|
||||
if let Some(tid) = tid {
|
||||
parent.types.insert(name, tid);
|
||||
parent.types.insert(*name, tid);
|
||||
imported = true;
|
||||
}
|
||||
|
||||
if let Some(vid) = vid {
|
||||
parent.values.insert(name, vid);
|
||||
parent.values.insert(*name, vid);
|
||||
imported = true;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user