rexlang_engine/libraries/
types.rs1use std::collections::{HashMap, HashSet};
2use std::fmt;
3use std::path::{Path, PathBuf};
4
5use rexlang_ast::expr::{Symbol, intern};
6use rexlang_typesystem::Type;
7
8use crate::Pointer;
9
10#[derive(Clone, Debug, PartialEq, Eq, Hash)]
11pub enum LibraryId {
12 Local { path: PathBuf },
13 Remote(String),
14 Virtual(String),
15}
16
17impl fmt::Display for LibraryId {
18 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
19 match self {
20 LibraryId::Local { path } => write!(f, "file:{}", path.display()),
21 LibraryId::Remote(url) => write!(f, "{url}"),
22 LibraryId::Virtual(name) => write!(f, "virtual:{name}"),
23 }
24 }
25}
26
27#[derive(Clone, Debug)]
28pub struct ResolveRequest {
29 pub library_name: String,
30 pub importer: Option<LibraryId>,
31}
32
33#[derive(Clone, Debug)]
34pub struct ResolvedLibrary {
35 pub id: LibraryId,
36 pub source: String,
37}
38
39#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
40pub struct LibraryKey(u64);
41
42impl LibraryKey {
43 pub fn as_u64(self) -> u64 {
44 self.0
45 }
46}
47
48#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
49pub enum SymbolKind {
50 Value,
51 Type,
52 Class,
53}
54
55#[derive(Clone, Debug, PartialEq, Eq, Hash)]
56pub struct CanonicalSymbol {
57 pub library: LibraryKey,
58 pub kind: SymbolKind,
59 pub local: Symbol,
60 symbol: Symbol,
61}
62
63impl CanonicalSymbol {
64 pub fn new(library: LibraryKey, kind: SymbolKind, local: Symbol) -> Self {
65 let symbol = intern(&format!(
66 "{}.{}",
67 prefix_for_library_key(library),
68 local.as_ref()
69 ));
70 Self {
71 library,
72 kind,
73 local,
74 symbol,
75 }
76 }
77
78 pub fn from_symbol(
79 library: LibraryKey,
80 kind: SymbolKind,
81 local: Symbol,
82 symbol: Symbol,
83 ) -> Self {
84 Self {
85 library,
86 kind,
87 local,
88 symbol,
89 }
90 }
91
92 pub fn symbol(&self) -> &Symbol {
93 &self.symbol
94 }
95}
96
97#[derive(Clone)]
98pub struct LibraryExports {
99 pub values: HashMap<Symbol, CanonicalSymbol>,
100 pub types: HashMap<Symbol, CanonicalSymbol>,
101 pub classes: HashMap<Symbol, CanonicalSymbol>,
102}
103
104#[derive(Clone, Default)]
105pub struct ReplState {
106 pub(crate) alias_exports: HashMap<Symbol, LibraryExports>,
107 pub(crate) imported_values: HashMap<Symbol, CanonicalSymbol>,
108 pub(crate) defined_values: HashSet<Symbol>,
109 pub(crate) importer_path: Option<PathBuf>,
110}
111
112impl ReplState {
113 pub fn new() -> Self {
114 Self::default()
115 }
116
117 pub fn with_importer_path(path: impl AsRef<Path>) -> Self {
118 Self {
119 importer_path: Some(path.as_ref().to_path_buf()),
120 ..Self::default()
121 }
122 }
123}
124
125#[derive(Clone)]
126pub struct LibraryInstance {
127 pub id: LibraryId,
128 pub exports: LibraryExports,
129 pub init_value: Pointer,
130 pub init_type: Type,
131 pub source_fingerprint: Option<String>,
132}
133
134pub(crate) fn library_key_for_library(id: &LibraryId) -> LibraryKey {
135 let mut hash: u64 = 0xcbf29ce484222325;
140 hash_library_identity(&mut hash, id);
141 LibraryKey(hash)
142}
143
144fn hash_library_identity(state: &mut u64, id: &LibraryId) {
145 fn hash_bytes(state: &mut u64, bytes: &[u8]) {
146 for b in bytes {
147 *state ^= u64::from(*b);
148 *state = state.wrapping_mul(0x0000_0100_0000_01B3);
149 }
150 }
151
152 match id {
153 LibraryId::Local { path } => {
154 hash_bytes(state, b"local:");
155 hash_bytes(state, path.as_os_str().as_encoded_bytes());
156 }
157 LibraryId::Remote(url) => {
158 hash_bytes(state, b"remote:");
159 hash_bytes(state, url.as_bytes());
160 }
161 LibraryId::Virtual(name) => {
162 hash_bytes(state, b"virtual:");
163 hash_bytes(state, name.as_bytes());
164 }
165 }
166}
167
168pub(crate) fn prefix_for_library_key(key: LibraryKey) -> String {
169 format!("@m{:016x}", key.as_u64())
170}
171
172pub(crate) fn prefix_for_library(id: &LibraryId) -> String {
173 prefix_for_library_key(library_key_for_library(id))
174}
175
176pub(crate) fn qualify(prefix: &str, name: &Symbol) -> Symbol {
177 intern(&format!("{prefix}.{}", name.as_ref()))
178}
179
180pub fn virtual_export_name(library: &str, export: &str) -> String {
181 let id = LibraryId::Virtual(library.to_string());
182 let key = library_key_for_library(&id);
183 CanonicalSymbol::new(key, SymbolKind::Value, intern(export))
184 .symbol()
185 .to_string()
186}