rexlang_engine/libraries/
types.rs1use std::collections::{HashMap, HashSet};
2use std::fmt;
3use std::path::{Path, PathBuf};
4
5use rexlang_ast::expr::{Program, 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 enum ResolvedLibraryContent {
35 Source(String),
36 Program(Program),
37}
38
39#[derive(Clone, Debug)]
40pub struct ResolvedLibrary {
41 pub id: LibraryId,
42 pub content: ResolvedLibraryContent,
43}
44
45#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
46pub struct LibraryKey(u64);
47
48impl LibraryKey {
49 pub fn as_u64(self) -> u64 {
50 self.0
51 }
52}
53
54#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
55pub enum SymbolKind {
56 Value,
57 Type,
58 Class,
59}
60
61#[derive(Clone, Debug, PartialEq, Eq, Hash)]
62pub struct CanonicalSymbol {
63 pub library: LibraryKey,
64 pub kind: SymbolKind,
65 pub local: Symbol,
66 symbol: Symbol,
67}
68
69impl CanonicalSymbol {
70 pub fn new(library: LibraryKey, kind: SymbolKind, local: Symbol) -> Self {
71 let symbol = intern(&format!(
72 "{}.{}",
73 prefix_for_library_key(library),
74 local.as_ref()
75 ));
76 Self {
77 library,
78 kind,
79 local,
80 symbol,
81 }
82 }
83
84 pub fn from_symbol(
85 library: LibraryKey,
86 kind: SymbolKind,
87 local: Symbol,
88 symbol: Symbol,
89 ) -> Self {
90 Self {
91 library,
92 kind,
93 local,
94 symbol,
95 }
96 }
97
98 pub fn symbol(&self) -> &Symbol {
99 &self.symbol
100 }
101}
102
103#[derive(Clone)]
104pub struct LibraryExports {
105 pub values: HashMap<Symbol, CanonicalSymbol>,
106 pub types: HashMap<Symbol, CanonicalSymbol>,
107 pub classes: HashMap<Symbol, CanonicalSymbol>,
108}
109
110#[derive(Clone)]
111pub struct VirtualLibraryModule {
112 pub exports: LibraryExports,
113 pub decls: Vec<rexlang_ast::expr::Decl>,
114 pub source: Option<String>,
115}
116
117#[derive(Clone, Default)]
118pub struct ReplState {
119 pub(crate) alias_exports: HashMap<Symbol, LibraryExports>,
120 pub(crate) imported_values: HashMap<Symbol, CanonicalSymbol>,
121 pub(crate) defined_values: HashSet<Symbol>,
122 pub(crate) importer_path: Option<PathBuf>,
123}
124
125impl ReplState {
126 pub fn new() -> Self {
127 Self::default()
128 }
129
130 pub fn with_importer_path(path: impl AsRef<Path>) -> Self {
131 Self {
132 importer_path: Some(path.as_ref().to_path_buf()),
133 ..Self::default()
134 }
135 }
136}
137
138#[derive(Clone)]
139pub struct LibraryInstance {
140 pub id: LibraryId,
141 pub exports: LibraryExports,
142 pub init_value: Pointer,
143 pub init_type: Type,
144 pub source_fingerprint: Option<String>,
145}
146
147pub(crate) fn library_key_for_library(id: &LibraryId) -> LibraryKey {
148 let mut hash: u64 = 0xcbf29ce484222325;
153 hash_library_identity(&mut hash, id);
154 LibraryKey(hash)
155}
156
157fn hash_library_identity(state: &mut u64, id: &LibraryId) {
158 fn hash_bytes(state: &mut u64, bytes: &[u8]) {
159 for b in bytes {
160 *state ^= u64::from(*b);
161 *state = state.wrapping_mul(0x0000_0100_0000_01B3);
162 }
163 }
164
165 match id {
166 LibraryId::Local { path } => {
167 hash_bytes(state, b"local:");
168 hash_bytes(state, path.as_os_str().as_encoded_bytes());
169 }
170 LibraryId::Remote(url) => {
171 hash_bytes(state, b"remote:");
172 hash_bytes(state, url.as_bytes());
173 }
174 LibraryId::Virtual(name) => {
175 hash_bytes(state, b"virtual:");
176 hash_bytes(state, name.as_bytes());
177 }
178 }
179}
180
181pub(crate) fn prefix_for_library_key(key: LibraryKey) -> String {
182 format!("@m{:016x}", key.as_u64())
183}
184
185pub(crate) fn prefix_for_library(id: &LibraryId) -> String {
186 prefix_for_library_key(library_key_for_library(id))
187}
188
189pub(crate) fn qualify(prefix: &str, name: &Symbol) -> Symbol {
190 intern(&format!("{prefix}.{}", name.as_ref()))
191}
192
193pub fn virtual_export_name(library: &str, export: &str) -> String {
194 let id = LibraryId::Virtual(library.to_string());
195 let key = library_key_for_library(&id);
196 CanonicalSymbol::new(key, SymbolKind::Value, intern(export))
197 .symbol()
198 .to_string()
199}