1use crate::compiler::{CompilerError, dependency_graph};
6use crate::parser::common::{CompoundIdentifier, Include};
7use crate::parser::{self, bind_library};
8use crate::{linter, make_identifier};
9use std::collections::HashMap;
10use std::fmt;
11use std::ops::Deref;
12
13pub type SymbolTable = HashMap<CompoundIdentifier, Symbol>;
14
15#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Deserialize, serde::Serialize)]
16pub enum Symbol {
17 DeprecatedKey(u32),
18 Key(String, bind_library::ValueType),
19 NumberValue(u64),
20 StringValue(String),
21 BoolValue(bool),
22 EnumValue(String),
23}
24
25impl fmt::Display for Symbol {
26 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27 match self {
28 Symbol::DeprecatedKey(key) => write!(f, "DeprecatedKey({})", key),
29 Symbol::Key(key, _) => write!(f, "Key({})", key),
30 Symbol::NumberValue(value) => write!(f, "{}", value),
31 Symbol::StringValue(value) => write!(f, "\"{}\"", value),
32 Symbol::BoolValue(value) => write!(f, "{}", value),
33 Symbol::EnumValue(value) => write!(f, "Enum({})", value),
34 }
35 }
36}
37
38struct SymbolTableDeclaration {
41 pub declaration: bind_library::Declaration,
42
43 pub qualified_k: CompoundIdentifier,
46 pub qualified_v: CompoundIdentifier,
47
48 pub local_qualified_k: CompoundIdentifier,
51 pub local_qualified_v: CompoundIdentifier,
52}
53
54pub fn get_symbol_table_from_libraries<'a>(
55 using: &Vec<Include>,
56 libraries: &[String],
57 lint: bool,
58) -> Result<SymbolTable, CompilerError> {
59 let library_asts: Vec<bind_library::Ast> = libraries
60 .iter()
61 .map(|lib| {
62 let ast = bind_library::Ast::try_from(lib.as_str())
63 .map_err(CompilerError::BindParserError)?;
64 if lint {
65 linter::lint_library(&ast).map_err(CompilerError::LinterError)?;
66 }
67 Ok(ast)
68 })
69 .collect::<Result<_, CompilerError>>()?;
70
71 let dependencies = resolve_dependencies(using, library_asts.iter())?;
72 let aliases = get_aliases(using);
73 construct_symbol_table(dependencies.into_iter(), aliases)
74}
75
76fn get_aliases(using: &Vec<Include>) -> HashMap<CompoundIdentifier, String> {
77 return using
78 .iter()
79 .filter_map(|using| match &using.alias {
80 Some(alias) => Some((using.name.clone(), alias.clone())),
81 None => None,
82 })
83 .collect::<HashMap<_, _>>();
84}
85
86pub fn resolve_dependencies<'a>(
87 using: &Vec<Include>,
88 libraries: impl Iterator<Item = &'a bind_library::Ast> + Clone,
89) -> Result<Vec<&'a bind_library::Ast>, CompilerError> {
90 (|| {
91 let mut graph = dependency_graph::DependencyGraph::new();
92
93 for library in libraries.clone() {
94 graph.insert_node(library.name.clone(), library);
95 }
96
97 for Include { name, .. } in using {
98 graph.insert_edge_from_root(name)?;
99 }
100
101 for library in libraries.clone() {
102 graph.insert_edge_from_root(&library.name)?;
103 }
104
105 for from in libraries {
106 for to in &from.using {
107 graph.insert_edge(&from.name, &to.name)?;
108 }
109 }
110
111 graph.resolve()
112 })()
113 .map_err(CompilerError::DependencyError)
114}
115
116fn find_qualified_identifier(
119 declaration: &bind_library::Declaration,
120 using: &Vec<parser::common::Include>,
121 library_names: &std::collections::HashSet<CompoundIdentifier>,
122 local_qualified: &CompoundIdentifier,
123) -> Result<CompoundIdentifier, CompilerError> {
124 if let Some(namespace) = declaration.identifier.parent() {
125 if !declaration.extends {
127 return Err(CompilerError::MissingExtendsKeyword(declaration.identifier.clone()));
128 }
129
130 if namespace == make_identifier!["fuchsia"] {
133 return Ok(declaration.identifier.clone());
134 }
135
136 let include = using.iter().find(|include| {
138 namespace == include.name || Some(namespace.to_string()) == include.alias
139 });
140
141 if let Some(include) = include {
142 return Ok(include.name.nest(declaration.identifier.name.clone()));
143 }
144
145 if library_names.contains(&namespace) {
147 return Ok(namespace.nest(declaration.identifier.name.clone()));
148 }
149
150 return Err(CompilerError::UnresolvedQualification(declaration.identifier.clone()));
151 }
152
153 if declaration.extends {
155 return Err(CompilerError::InvalidExtendsKeyword(local_qualified.clone()));
156 }
157
158 Ok(local_qualified.clone())
160}
161
162fn insert_symbol_entries(
164 symbol_table: &mut SymbolTable,
165 declaration_data: SymbolTableDeclaration,
166) -> Result<(), CompilerError> {
167 let SymbolTableDeclaration {
168 declaration,
169 qualified_k,
170 qualified_v,
171 local_qualified_k,
172 local_qualified_v,
173 } = declaration_data;
174
175 match symbol_table.get(&qualified_k) {
178 Some(Symbol::Key(_, value_type)) => {
179 if !declaration.extends {
180 return Err(CompilerError::DuplicateIdentifier(qualified_k));
181 }
182 if declaration.value_type != *value_type {
183 return Err(CompilerError::TypeMismatch(qualified_k));
184 }
185 }
186 Some(Symbol::DeprecatedKey(_)) => (),
187 Some(_) => {
188 return Err(CompilerError::TypeMismatch(qualified_k));
189 }
190 None => {
191 if declaration.extends {
192 return Err(CompilerError::UndeclaredKey(qualified_k));
193 }
194 symbol_table
195 .insert(qualified_k, Symbol::Key(qualified_v.to_string(), declaration.value_type));
196 }
197 }
198
199 for value in &declaration.values {
203 let qualified_value_k = local_qualified_k.nest(value.identifier().to_string());
204 let qualified_value_v = local_qualified_v.nest(value.identifier().to_string());
205 if symbol_table.contains_key(&qualified_value_k) {
206 return Err(CompilerError::DuplicateIdentifier(qualified_value_k));
207 }
208
209 let value_symbol = match value {
210 bind_library::Value::Number(_, value) => Symbol::NumberValue(*value),
211 bind_library::Value::Str(_, value) => Symbol::StringValue(value.clone()),
212 bind_library::Value::Bool(_, value) => Symbol::BoolValue(*value),
213 bind_library::Value::Enum(_) => Symbol::EnumValue(qualified_value_v.to_string()),
214 };
215 symbol_table.insert(qualified_value_k, value_symbol);
216 }
217 Ok(())
218}
219
220pub fn construct_symbol_table(
226 libraries: impl Iterator<Item = impl Deref<Target = bind_library::Ast>>,
227 aliases: HashMap<CompoundIdentifier, String>,
228) -> Result<SymbolTable, CompilerError> {
229 let mut symbol_table: HashMap<CompoundIdentifier, Symbol> = get_deprecated_symbols();
230
231 let libs = libraries.collect::<Vec<_>>();
232 let library_names =
233 libs.iter().map(|lib| lib.name.clone()).collect::<std::collections::HashSet<_>>();
234
235 let mut extended_declarations: Vec<SymbolTableDeclaration> = vec![];
238
239 for lib in libs {
240 let bind_library::Ast { name, using, declarations } = &*lib;
241
242 let aliased_name = match aliases.get(name) {
243 Some(alias) => Some(make_identifier!(alias)),
244 None => None,
245 };
246
247 for declaration in declarations {
248 let local_qualified_id = name.nest(declaration.identifier.name.clone());
253
254 let qualified_id =
259 find_qualified_identifier(declaration, using, &library_names, &local_qualified_id)?;
260
261 if let Some(alias) = aliased_name.as_ref() {
262 let alias_local_qualified_id = alias.nest(declaration.identifier.name.clone());
263 let alias_qualified_id = find_qualified_identifier(
264 declaration,
265 using,
266 &library_names,
267 &alias_local_qualified_id,
268 )?;
269
270 let entry_data = SymbolTableDeclaration {
271 declaration: declaration.clone(),
272 qualified_k: alias_qualified_id,
273 qualified_v: qualified_id.clone(),
274 local_qualified_k: alias_local_qualified_id.clone(),
275 local_qualified_v: local_qualified_id.clone(),
276 };
277
278 if declaration.extends {
279 extended_declarations.push(entry_data);
280 } else {
281 insert_symbol_entries(&mut symbol_table, entry_data)?;
282 }
283 }
284
285 let entry_data = SymbolTableDeclaration {
286 declaration: declaration.clone(),
287 qualified_k: qualified_id.clone(),
288 qualified_v: qualified_id,
289 local_qualified_k: local_qualified_id.clone(),
290 local_qualified_v: local_qualified_id,
291 };
292
293 if declaration.extends {
294 extended_declarations.push(entry_data);
295 } else {
296 insert_symbol_entries(&mut symbol_table, entry_data)?;
297 }
298 }
299 }
300
301 for declaration in extended_declarations.into_iter() {
302 insert_symbol_entries(&mut symbol_table, declaration)?;
303 }
304
305 Ok(symbol_table)
306}
307
308#[allow(clippy::vec_init_then_push, reason = "mass allow for https://fxbug.dev/381896734")]
309fn deprecated_keys() -> Vec<(String, u32)> {
312 let mut keys = Vec::new();
313
314 keys.push(("BIND_PROTOCOL".to_string(), 0x0001));
315
316 keys.push(("BIND_AUTOBIND".to_string(), 0x0002));
317
318 keys.push(("BIND_COMPOSITE".to_string(), 0x0003));
319
320 keys.push(("BIND_FIDL_PROTOCOL".to_string(), 0x0004));
321
322 keys.push(("BIND_PLATFORM_DEV_VID".to_string(), 0x0300));
323 keys.push(("BIND_PCI_VID".to_string(), 0x0100));
324
325 keys.push(("BIND_PCI_DID".to_string(), 0x0101));
326 keys.push(("BIND_PCI_CLASS".to_string(), 0x0102));
327 keys.push(("BIND_PCI_SUBCLASS".to_string(), 0x0103));
328 keys.push(("BIND_PCI_INTERFACE".to_string(), 0x0104));
329 keys.push(("BIND_PCI_REVISION".to_string(), 0x0105));
330 keys.push(("BIND_PCI_TOPO".to_string(), 0x0107));
331
332 keys.push(("BIND_USB_VID".to_string(), 0x0200));
335 keys.push(("BIND_USB_PID".to_string(), 0x0201));
336 keys.push(("BIND_USB_CLASS".to_string(), 0x0202));
337 keys.push(("BIND_USB_SUBCLASS".to_string(), 0x0203));
338 keys.push(("BIND_USB_PROTOCOL".to_string(), 0x0204));
339 keys.push(("BIND_USB_INTERFACE_NUMBER".to_string(), 0x0205));
340
341 keys.push(("BIND_PLATFORM_DEV_VID".to_string(), 0x0300));
343 keys.push(("BIND_PLATFORM_DEV_PID".to_string(), 0x0301));
344 keys.push(("BIND_PLATFORM_DEV_DID".to_string(), 0x0302));
345 keys.push(("BIND_PLATFORM_DEV_INSTANCE_ID".to_string(), 0x0304));
346 keys.push(("BIND_PLATFORM_DEV_INTERRUPT_ID".to_string(), 0x0305));
347
348 keys.push(("BIND_ACPI_BUS_TYPE".to_string(), 0x0400));
350 keys.push(("BIND_ACPI_ID".to_string(), 0x0401));
351
352 keys.push(("BIND_IHDA_CODEC_VID".to_string(), 0x0500));
354 keys.push(("BIND_IHDA_CODEC_DID".to_string(), 0x0501));
355 keys.push(("BIND_IHDA_CODEC_MAJOR_REV".to_string(), 0x0502));
356 keys.push(("BIND_IHDA_CODEC_MINOR_REV".to_string(), 0x0503));
357 keys.push(("BIND_IHDA_CODEC_VENDOR_REV".to_string(), 0x0504));
358 keys.push(("BIND_IHDA_CODEC_VENDOR_STEP".to_string(), 0x0505));
359
360 keys.push(("BIND_SERIAL_CLASS".to_string(), 0x0600));
362 keys.push(("BIND_SERIAL_VID".to_string(), 0x0601));
363 keys.push(("BIND_SERIAL_PID".to_string(), 0x0602));
364
365 keys.push(("BIND_NAND_CLASS".to_string(), 0x0700));
367
368 keys.push(("BIND_SDIO_VID".to_string(), 0x0900));
370 keys.push(("BIND_SDIO_PID".to_string(), 0x0901));
371 keys.push(("BIND_SDIO_FUNCTION".to_string(), 0x0902));
372
373 keys.push(("BIND_I2C_CLASS".to_string(), 0x0A00));
375 keys.push(("BIND_I2C_BUS_ID".to_string(), 0x0A01));
376 keys.push(("BIND_I2C_ADDRESS".to_string(), 0x0A02));
377
378 keys.push(("BIND_GPIO_PIN".to_string(), 0x0A10));
380 keys.push(("BIND_GPIO_CONTROLLER".to_string(), 0x0A11));
381
382 keys.push(("BIND_POWER_DOMAIN".to_string(), 0x0A20));
384 keys.push(("BIND_POWER_DOMAIN_COMPOSITE".to_string(), 0x0A21));
385
386 keys.push(("BIND_CLOCK_ID".to_string(), 0x0A30));
388
389 keys.push(("BIND_SPI_BUS_ID".to_string(), 0x0A41));
391 keys.push(("BIND_SPI_CHIP_SELECT".to_string(), 0x0A42));
392
393 keys.push(("BIND_PWM_ID".to_string(), 0x0A50));
395
396 keys.push(("BIND_INIT_STEP".to_string(), 0x0A60));
398
399 keys.push(("BIND_CODEC_INSTANCE".to_string(), 0x0A70));
401
402 keys.push(("BIND_POWER_SENSOR_DOMAIN".to_string(), 0x0A90));
404
405 keys.push(("BIND_MAILBOX_ID".to_string(), 0x0AA0));
407
408 keys
409}
410
411fn get_deprecated_symbols() -> SymbolTable {
412 let mut symbol_table = HashMap::new();
413 for (key, value) in deprecated_keys() {
414 symbol_table.insert(make_identifier!("fuchsia", key), Symbol::DeprecatedKey(value));
415 }
416 symbol_table
417}
418
419pub fn get_deprecated_key_identifiers() -> HashMap<u32, String> {
420 let mut key_identifiers = HashMap::new();
421 for (key, value) in deprecated_keys() {
422 key_identifiers.insert(value, make_identifier!("fuchsia", key).to_string());
423 }
424 key_identifiers
425}
426
427pub fn get_deprecated_key_identifier(key: u32) -> Option<String> {
428 match key {
429 0x0000 => Some("fuchsia.BIND_FLAGS".to_string()),
430 0x0001 => Some("fuchsia.BIND_PROTOCOL".to_string()),
431 0x0002 => Some("fuchsia.BIND_AUTOBIND".to_string()),
432 0x0003 => Some("fuchsia.BIND_COMPOSITE".to_string()),
433 0x0004 => Some("fuchsia.BIND_FIDL_PROTOCOL".to_string()),
434
435 0x0100 => Some("fuchsia.BIND_PCI_VID".to_string()),
437 0x0101 => Some("fuchsia.BIND_PCI_DID".to_string()),
438 0x0102 => Some("fuchsia.BIND_PCI_CLASS".to_string()),
439 0x0103 => Some("fuchsia.BIND_PCI_SUBCLASS".to_string()),
440 0x0104 => Some("fuchsia.BIND_PCI_INTERFACE".to_string()),
441 0x0105 => Some("fuchsia.BIND_PCI_REVISION".to_string()),
442 0x0107 => Some("fuchsia.BIND_PCI_TOPO".to_string()),
443
444 0x0200 => Some("fuchsia.BIND_USB_VID".to_string()),
446 0x0201 => Some("fuchsia.BIND_USB_PID".to_string()),
447 0x0202 => Some("fuchsia.BIND_USB_CLASS".to_string()),
448 0x0203 => Some("fuchsia.BIND_USB_SUBCLASS".to_string()),
449 0x0204 => Some("fuchsia.BIND_USB_PROTOCOL".to_string()),
450 0x0205 => Some("fuchsia.BIND_USB_INTERFACE_NUMBER".to_string()),
451
452 0x0300 => Some("fuchsia.BIND_PLATFORM_DEV_VID".to_string()),
454 0x0301 => Some("fuchsia.BIND_PLATFORM_DEV_PID".to_string()),
455 0x0302 => Some("fuchsia.BIND_PLATFORM_DEV_DID".to_string()),
456 0x0304 => Some("fuchsia.BIND_PLATFORM_DEV_INSTANCE_ID".to_string()),
457 0x0305 => Some("fuchsia.BIND_PLATFORM_DEV_INTERRUPT_ID".to_string()),
458
459 0x0400 => Some("fuchsia.BIND_ACPI_BUS_TYPE".to_string()),
461 0x0401 => Some("fuchsia.BIND_ACPI_ID".to_string()),
462
463 0x0500 => Some("fuchsia.BIND_IHDA_CODEC_VID".to_string()),
465 0x0501 => Some("fuchsia.BIND_IHDA_CODEC_DID".to_string()),
466 0x0502 => Some("fuchsia.BIND_IHDA_CODEC_MAJOR_REV".to_string()),
467 0x0503 => Some("fuchsia.BIND_IHDA_CODEC_MINOR_REV".to_string()),
468 0x0504 => Some("fuchsia.BIND_IHDA_CODEC_VENDOR_REV".to_string()),
469 0x0505 => Some("fuchsia.BIND_IHDA_CODEC_VENDOR_STEP".to_string()),
470
471 0x0600 => Some("fuchsia.BIND_SERIAL_CLASS".to_string()),
473 0x0601 => Some("fuchsia.BIND_SERIAL_VID".to_string()),
474 0x0602 => Some("fuchsia.BIND_SERIAL_PID".to_string()),
475
476 0x0700 => Some("fuchsia.BIND_NAND_CLASS".to_string()),
478
479 0x0900 => Some("fuchsia.BIND_SDIO_VID".to_string()),
481 0x0901 => Some("fuchsia.BIND_SDIO_PID".to_string()),
482 0x0902 => Some("fuchsia.BIND_SDIO_FUNCTION".to_string()),
483
484 0x0A00 => Some("fuchsia.BIND_I2C_CLASS".to_string()),
486 0x0A01 => Some("fuchsia.BIND_I2C_BUS_ID".to_string()),
487 0x0A02 => Some("fuchsia.BIND_I2C_ADDRESS".to_string()),
488 0x0A03 => Some("fuchsia.BIND_I2C_VID".to_string()),
489 0x0A04 => Some("fuchsia.BIND_I2C_DID".to_string()),
490
491 0x0A10 => Some("fuchsia.BIND_GPIO_PIN".to_string()),
493 0x0A11 => Some("fuchsia.BIND_GPIO_CONTROLLER".to_string()),
494
495 0x0A20 => Some("fuchsia.BIND_POWER_DOMAIN".to_string()),
497 0x0A21 => Some("fuchsia.BIND_POWER_DOMAIN_COMPOSITE".to_string()),
498
499 0x0A30 => Some("fuchsia.BIND_CLOCK_ID".to_string()),
501
502 0x0A41 => Some("fuchsia.BIND_SPI_BUS_ID".to_string()),
504 0x0A42 => Some("fuchsia.BIND_SPI_CHIP_SELECT".to_string()),
505
506 0x0A50 => Some("fuchsia.BIND_PWM_ID".to_string()),
508
509 0x0A60 => Some("fuchsia.BIND_INIT_STEP".to_string()),
511
512 0x0A70 => Some("fuchsia.BIND_CODEC_INSTANCE".to_string()),
514
515 0x0A90 => Some("fuchsia.BIND_POWER_SENSOR_DOMAIN".to_string()),
517
518 0x0AA0 => Some("fuchsia.BIND_MAILBOX_ID".to_string()),
520
521 _ => None,
522 }
523}
524
525pub fn get_deprecated_key_value(key: &str) -> Option<u32> {
526 match key {
527 "fuchsia.BIND_FLAGS" => Some(0x0000),
528 "fuchsia.BIND_PROTOCOL" => Some(0x0001),
529 "fuchsia.BIND_AUTOBIND" => Some(0x0002),
530 "fuchsia.BIND_COMPOSITE" => Some(0x0003),
531 "fuchsia.BIND_FIDL_PROTOCOL" => Some(0x0004),
532
533 "fuchsia.BIND_PCI_VID" => Some(0x0100),
535 "fuchsia.BIND_PCI_DID" => Some(0x0101),
536 "fuchsia.BIND_PCI_CLASS" => Some(0x0102),
537 "fuchsia.BIND_PCI_SUBCLASS" => Some(0x0103),
538 "fuchsia.BIND_PCI_INTERFACE" => Some(0x0104),
539 "fuchsia.BIND_PCI_REVISION" => Some(0x0105),
540 "fuchsia.BIND_PCI_TOPO" => Some(0x0107),
541
542 "fuchsia.BIND_USB_VID" => Some(0x0200),
544 "fuchsia.BIND_USB_PID" => Some(0x0201),
545 "fuchsia.BIND_USB_CLASS" => Some(0x0202),
546 "fuchsia.BIND_USB_SUBCLASS" => Some(0x0203),
547 "fuchsia.BIND_USB_PROTOCOL" => Some(0x0204),
548 "fuchsia.BIND_USB_INTERFACE_NUMBER" => Some(0x0205),
549
550 "fuchsia.BIND_PLATFORM_DEV_VID" => Some(0x0300),
552 "fuchsia.BIND_PLATFORM_DEV_PID" => Some(0x0301),
553 "fuchsia.BIND_PLATFORM_DEV_DID" => Some(0x0302),
554 "fuchsia.BIND_PLATFORM_DEV_INSTANCE_ID" => Some(0x0304),
555 "fuchsia.BIND_PLATFORM_DEV_INTERRUPT_ID" => Some(0x0305),
556
557 "fuchsia.BIND_ACPI_BUS_TYPE" => Some(0x0400),
559 "fuchsia.BIND_ACPI_ID" => Some(0x0401),
560
561 "fuchsia.BIND_IHDA_CODEC_VID" => Some(0x0500),
563 "fuchsia.BIND_IHDA_CODEC_DID" => Some(0x0501),
564 "fuchsia.BIND_IHDA_CODEC_MAJOR_REV" => Some(0x0502),
565 "fuchsia.BIND_IHDA_CODEC_MINOR_REV" => Some(0x0503),
566 "fuchsia.BIND_IHDA_CODEC_VENDOR_REV" => Some(0x0504),
567 "fuchsia.BIND_IHDA_CODEC_VENDOR_STEP" => Some(0x0505),
568
569 "fuchsia.BIND_SERIAL_CLASS" => Some(0x0600),
571 "fuchsia.BIND_SERIAL_VID" => Some(0x0601),
572 "fuchsia.BIND_SERIAL_PID" => Some(0x0602),
573
574 "fuchsia.BIND_NAND_CLASS" => Some(0x0700),
576
577 "fuchsia.BIND_SDIO_VID" => Some(0x0900),
579 "fuchsia.BIND_SDIO_PID" => Some(0x0901),
580 "fuchsia.BIND_SDIO_FUNCTION" => Some(0x0902),
581
582 "fuchsia.BIND_I2C_CLASS" => Some(0x0A00),
584 "fuchsia.BIND_I2C_BUS_ID" => Some(0x0A01),
585 "fuchsia.BIND_I2C_ADDRESS" => Some(0x0A02),
586 "fuchsia.BIND_I2C_VID" => Some(0x0A03),
587 "fuchsia.BIND_I2C_DID" => Some(0x0A04),
588
589 "fuchsia.BIND_GPIO_PIN" => Some(0x0A10),
591 "fuchsia.BIND_GPIO_CONTROLLER" => Some(0x0A11),
592
593 "fuchsia.BIND_POWER_DOMAIN" => Some(0x0A20),
595 "fuchsia.BIND_POWER_DOMAIN_COMPOSITE" => Some(0x0A21),
596
597 "fuchsia.BIND_CLOCK_ID" => Some(0x0A30),
599
600 "fuchsia.BIND_SPI_BUS_ID" => Some(0x0A41),
602 "fuchsia.BIND_SPI_CHIP_SELECT" => Some(0x0A42),
603
604 "fuchsia.BIND_PWM_ID" => Some(0x0A50),
606
607 "fuchsia.BIND_INIT_STEP" => Some(0x0A60),
609
610 "fuchsia.BIND_CODEC_INSTANCE" => Some(0x0A70),
612
613 "fuchsia.BIND_POWER_SENSOR_DOMAIN" => Some(0x0A90),
615
616 "fuchsia.BIND_MAILBOX_ID" => Some(0x0AA0),
618
619 _ => None,
620 }
621}
622
623#[cfg(test)]
624mod test {
625 use super::*;
626 use crate::make_identifier;
627 use crate::parser::bind_library;
628 use crate::parser::common::Include;
629
630 mod symbol_table {
631 use super::*;
632
633 #[test]
634 fn simple_key_and_value() {
635 let libraries = vec![bind_library::Ast {
636 name: make_identifier!("test"),
637 using: vec![],
638 declarations: vec![bind_library::Declaration {
639 identifier: make_identifier!["symbol"],
640 value_type: bind_library::ValueType::Number,
641 extends: false,
642 values: vec![(bind_library::Value::Number("x".to_string(), 1))],
643 }],
644 }];
645
646 let st = construct_symbol_table(libraries.iter(), HashMap::new()).unwrap();
647 assert_eq!(
648 st.get(&make_identifier!("test", "symbol")),
649 Some(&Symbol::Key("test.symbol".to_string(), bind_library::ValueType::Number))
650 );
651 assert_eq!(
652 st.get(&make_identifier!("test", "symbol", "x")),
653 Some(&Symbol::NumberValue(1))
654 );
655 }
656
657 #[test]
658 fn all_value_types() {
659 let libraries = vec![bind_library::Ast {
660 name: make_identifier!("hummingbird"),
661 using: vec![],
662 declarations: vec![
663 bind_library::Declaration {
664 identifier: make_identifier!["sunbeam"],
665 value_type: bind_library::ValueType::Number,
666 extends: false,
667 values: vec![(bind_library::Value::Number("shining".to_string(), 1))],
668 },
669 bind_library::Declaration {
670 identifier: make_identifier!["mountaingem"],
671 value_type: bind_library::ValueType::Bool,
672 extends: false,
673 values: vec![
674 (bind_library::Value::Bool("white-bellied".to_string(), false)),
675 ],
676 },
677 bind_library::Declaration {
678 identifier: make_identifier!["brilliant"],
679 value_type: bind_library::ValueType::Enum,
680 extends: false,
681 values: vec![(bind_library::Value::Enum("black-throated".to_string()))],
682 },
683 bind_library::Declaration {
684 identifier: make_identifier!["woodnymph"],
685 value_type: bind_library::ValueType::Str,
686 extends: false,
687 values: vec![
688 (bind_library::Value::Str(
689 "fork-tailed".to_string(),
690 "sabrewing".to_string(),
691 )),
692 ],
693 },
694 ],
695 }];
696
697 let st = construct_symbol_table(libraries.iter(), HashMap::new()).unwrap();
698 assert_eq!(
699 st.get(&make_identifier!("hummingbird", "sunbeam", "shining")),
700 Some(&Symbol::NumberValue(1))
701 );
702 assert_eq!(
703 st.get(&make_identifier!("hummingbird", "mountaingem", "white-bellied")),
704 Some(&Symbol::BoolValue(false))
705 );
706 assert_eq!(
707 st.get(&make_identifier!("hummingbird", "brilliant", "black-throated")),
708 Some(&Symbol::EnumValue("hummingbird.brilliant.black-throated".to_string()))
709 );
710 assert_eq!(
711 st.get(&make_identifier!("hummingbird", "woodnymph", "fork-tailed")),
712 Some(&Symbol::StringValue("sabrewing".to_string()))
713 );
714 }
715
716 #[test]
717 fn extension() {
718 let libraries = vec![
719 bind_library::Ast {
720 name: make_identifier!("lib_a"),
721 using: vec![],
722 declarations: vec![bind_library::Declaration {
723 identifier: make_identifier!["symbol"],
724 value_type: bind_library::ValueType::Number,
725 extends: false,
726 values: vec![(bind_library::Value::Number("x".to_string(), 1))],
727 }],
728 },
729 bind_library::Ast {
730 name: make_identifier!("lib_b"),
731 using: vec![Include { name: make_identifier!("lib_a"), alias: None }],
732 declarations: vec![bind_library::Declaration {
733 identifier: make_identifier!["lib_a", "symbol"],
734 value_type: bind_library::ValueType::Number,
735 extends: true,
736 values: vec![(bind_library::Value::Number("y".to_string(), 2))],
737 }],
738 },
739 ];
740
741 let st = construct_symbol_table(libraries.iter(), HashMap::new()).unwrap();
742 assert_eq!(
743 st.get(&make_identifier!("lib_a", "symbol")),
744 Some(&Symbol::Key("lib_a.symbol".to_string(), bind_library::ValueType::Number))
745 );
746 assert_eq!(
747 st.get(&make_identifier!("lib_a", "symbol", "x")),
748 Some(&Symbol::NumberValue(1))
749 );
750 assert_eq!(
751 st.get(&make_identifier!("lib_b", "symbol", "y")),
752 Some(&Symbol::NumberValue(2))
753 );
754 }
755
756 #[test]
757 fn extension_with_dependency_defined_after_library() {
758 let libraries = vec![
759 bind_library::Ast {
760 name: make_identifier!("lib_b"),
761 using: vec![Include { name: make_identifier!("lib_a"), alias: None }],
762 declarations: vec![bind_library::Declaration {
763 identifier: make_identifier!["lib_a", "symbol"],
764 value_type: bind_library::ValueType::Number,
765 extends: true,
766 values: vec![(bind_library::Value::Number("y".to_string(), 2))],
767 }],
768 },
769 bind_library::Ast {
770 name: make_identifier!("lib_a"),
771 using: vec![],
772 declarations: vec![bind_library::Declaration {
773 identifier: make_identifier!["symbol"],
774 value_type: bind_library::ValueType::Number,
775 extends: false,
776 values: vec![(bind_library::Value::Number("x".to_string(), 1))],
777 }],
778 },
779 ];
780
781 let st = construct_symbol_table(libraries.iter(), HashMap::new()).unwrap();
782 assert_eq!(
783 st.get(&make_identifier!("lib_a", "symbol")),
784 Some(&Symbol::Key("lib_a.symbol".to_string(), bind_library::ValueType::Number))
785 );
786 assert_eq!(
787 st.get(&make_identifier!("lib_a", "symbol", "x")),
788 Some(&Symbol::NumberValue(1))
789 );
790 assert_eq!(
791 st.get(&make_identifier!("lib_b", "symbol", "y")),
792 Some(&Symbol::NumberValue(2))
793 );
794 }
795
796 #[test]
797 fn aliased_extension() {
798 let libraries = vec![
799 bind_library::Ast {
800 name: make_identifier!("lib_a"),
801 using: vec![],
802 declarations: vec![bind_library::Declaration {
803 identifier: make_identifier!["symbol"],
804 value_type: bind_library::ValueType::Number,
805 extends: false,
806 values: vec![(bind_library::Value::Number("x".to_string(), 1))],
807 }],
808 },
809 bind_library::Ast {
810 name: make_identifier!("lib_b"),
811 using: vec![Include {
812 name: make_identifier!("lib_a"),
813 alias: Some("alias".to_string()),
814 }],
815 declarations: vec![bind_library::Declaration {
816 identifier: make_identifier!["alias", "symbol"],
817 value_type: bind_library::ValueType::Number,
818 extends: true,
819 values: vec![(bind_library::Value::Number("y".to_string(), 2))],
820 }],
821 },
822 ];
823
824 let st = construct_symbol_table(libraries.iter(), HashMap::new()).unwrap();
825 assert_eq!(
826 st.get(&make_identifier!("lib_a", "symbol")),
827 Some(&Symbol::Key("lib_a.symbol".to_string(), bind_library::ValueType::Number))
828 );
829 assert_eq!(
830 st.get(&make_identifier!("lib_a", "symbol", "x")),
831 Some(&Symbol::NumberValue(1))
832 );
833 assert_eq!(
834 st.get(&make_identifier!("lib_b", "symbol", "y")),
835 Some(&Symbol::NumberValue(2))
836 );
837 }
838
839 #[test]
840 fn aliased_extension_with_library_alias() {
841 let libraries = vec![
842 bind_library::Ast {
843 name: make_identifier!("lib_a"),
844 using: vec![],
845 declarations: vec![bind_library::Declaration {
846 identifier: make_identifier!["symbol"],
847 value_type: bind_library::ValueType::Number,
848 extends: false,
849 values: vec![(bind_library::Value::Number("x".to_string(), 1))],
850 }],
851 },
852 bind_library::Ast {
853 name: make_identifier!("lib_b"),
854 using: vec![Include {
855 name: make_identifier!("lib_a"),
856 alias: Some("alias".to_string()),
857 }],
858 declarations: vec![
859 bind_library::Declaration {
860 identifier: make_identifier!["alias", "symbol"],
861 value_type: bind_library::ValueType::Number,
862 extends: true,
863 values: vec![(bind_library::Value::Number("y".to_string(), 2))],
864 },
865 bind_library::Declaration {
866 identifier: make_identifier!["enum_symbol"],
867 value_type: bind_library::ValueType::Enum,
868 extends: false,
869 values: vec![(bind_library::Value::Enum("the_val".to_string()))],
870 },
871 ],
872 },
873 ];
874
875 let st = construct_symbol_table(
877 libraries.iter(),
878 HashMap::from([(make_identifier!("lib_b"), "opaque".to_string())]),
879 )
880 .unwrap();
881
882 assert_eq!(
883 st.get(&make_identifier!("lib_a", "symbol")),
884 Some(&Symbol::Key("lib_a.symbol".to_string(), bind_library::ValueType::Number))
885 );
886 assert_eq!(
887 st.get(&make_identifier!("lib_a", "symbol", "x")),
888 Some(&Symbol::NumberValue(1))
889 );
890 assert_eq!(
891 st.get(&make_identifier!("opaque", "symbol", "y")),
892 Some(&Symbol::NumberValue(2))
893 );
894 assert_eq!(
895 st.get(&make_identifier!("lib_b", "symbol", "y")),
896 Some(&Symbol::NumberValue(2))
897 );
898 assert_eq!(
899 st.get(&make_identifier!("opaque", "enum_symbol")),
900 Some(&Symbol::Key("lib_b.enum_symbol".to_string(), bind_library::ValueType::Enum))
901 );
902 assert_eq!(
903 st.get(&make_identifier!("lib_b", "enum_symbol")),
904 Some(&Symbol::Key("lib_b.enum_symbol".to_string(), bind_library::ValueType::Enum))
905 );
906 assert_eq!(
907 st.get(&make_identifier!("opaque", "enum_symbol", "the_val")),
908 Some(&Symbol::EnumValue("lib_b.enum_symbol.the_val".to_string()))
909 );
910 assert_eq!(
911 st.get(&make_identifier!("lib_b", "enum_symbol", "the_val")),
912 Some(&Symbol::EnumValue("lib_b.enum_symbol.the_val".to_string()))
913 );
914 }
915
916 #[test]
917 fn deprecated_key_extension() {
918 let libraries = vec![bind_library::Ast {
919 name: make_identifier!("lib_a"),
920 using: vec![],
921 declarations: vec![bind_library::Declaration {
922 identifier: make_identifier!["fuchsia", "BIND_PCI_DID"],
923 value_type: bind_library::ValueType::Number,
924 extends: true,
925 values: vec![(bind_library::Value::Number("x".to_string(), 0x1234))],
926 }],
927 }];
928
929 let st = construct_symbol_table(libraries.iter(), HashMap::new()).unwrap();
930 assert_eq!(
931 st.get(&make_identifier!("lib_a", "BIND_PCI_DID", "x")),
932 Some(&Symbol::NumberValue(0x1234))
933 );
934 }
935
936 #[test]
937 fn duplicate_key() {
938 let libraries = vec![bind_library::Ast {
939 name: make_identifier!("test"),
940 using: vec![],
941 declarations: vec![
942 bind_library::Declaration {
943 identifier: make_identifier!["symbol"],
944 value_type: bind_library::ValueType::Number,
945 extends: false,
946 values: vec![],
947 },
948 bind_library::Declaration {
949 identifier: make_identifier!["symbol"],
950 value_type: bind_library::ValueType::Number,
951 extends: false,
952 values: vec![],
953 },
954 ],
955 }];
956
957 assert_eq!(
958 construct_symbol_table(libraries.iter(), HashMap::new()),
959 Err(CompilerError::DuplicateIdentifier(make_identifier!("test", "symbol")))
960 );
961 }
962
963 #[test]
964 fn duplicate_value() {
965 let libraries = vec![bind_library::Ast {
966 name: make_identifier!("test"),
967 using: vec![],
968 declarations: vec![bind_library::Declaration {
969 identifier: make_identifier!["symbol"],
970 value_type: bind_library::ValueType::Number,
971 extends: false,
972 values: vec![
973 bind_library::Value::Number("a".to_string(), 1),
974 bind_library::Value::Number("a".to_string(), 2),
975 ],
976 }],
977 }];
978
979 assert_eq!(
980 construct_symbol_table(libraries.iter(), HashMap::new()),
981 Err(CompilerError::DuplicateIdentifier(make_identifier!("test", "symbol", "a")))
982 );
983 }
984
985 #[test]
986 fn keys_are_qualified() {
987 let libraries = vec![
989 bind_library::Ast {
990 name: make_identifier!("lib_a"),
991 using: vec![],
992 declarations: vec![bind_library::Declaration {
993 identifier: make_identifier!["symbol"],
994 value_type: bind_library::ValueType::Number,
995 extends: false,
996 values: vec![],
997 }],
998 },
999 bind_library::Ast {
1000 name: make_identifier!("lib_b"),
1001 using: vec![],
1002 declarations: vec![bind_library::Declaration {
1003 identifier: make_identifier!["symbol"],
1004 value_type: bind_library::ValueType::Number,
1005 extends: false,
1006 values: vec![],
1007 }],
1008 },
1009 ];
1010
1011 let st = construct_symbol_table(libraries.iter(), HashMap::new()).unwrap();
1012 assert_eq!(
1013 st.get(&make_identifier!("lib_a", "symbol")),
1014 Some(&Symbol::Key("lib_a.symbol".to_string(), bind_library::ValueType::Number))
1015 );
1016 assert_eq!(
1017 st.get(&make_identifier!("lib_b", "symbol")),
1018 Some(&Symbol::Key("lib_b.symbol".to_string(), bind_library::ValueType::Number))
1019 );
1020 }
1021
1022 #[test]
1023 fn missing_extend_keyword() {
1024 let libraries = vec![
1026 bind_library::Ast {
1027 name: make_identifier!("lib_a"),
1028 using: vec![],
1029 declarations: vec![bind_library::Declaration {
1030 identifier: make_identifier!["symbol"],
1031 value_type: bind_library::ValueType::Number,
1032 extends: false,
1033 values: vec![],
1034 }],
1035 },
1036 bind_library::Ast {
1037 name: make_identifier!("lib_b"),
1038 using: vec![],
1039 declarations: vec![bind_library::Declaration {
1040 identifier: make_identifier!["lib_a", "symbol"],
1041 value_type: bind_library::ValueType::Number,
1042 extends: false,
1043 values: vec![],
1044 }],
1045 },
1046 ];
1047
1048 assert_eq!(
1049 construct_symbol_table(libraries.iter(), HashMap::new()),
1050 Err(CompilerError::MissingExtendsKeyword(make_identifier!("lib_a", "symbol")))
1051 );
1052 }
1053
1054 #[test]
1055 fn invalid_extend_keyword() {
1056 let libraries = vec![bind_library::Ast {
1059 name: make_identifier!("lib_a"),
1060 using: vec![],
1061 declarations: vec![bind_library::Declaration {
1062 identifier: make_identifier!["symbol"],
1063 value_type: bind_library::ValueType::Number,
1064 extends: true,
1065 values: vec![],
1066 }],
1067 }];
1068
1069 assert_eq!(
1070 construct_symbol_table(libraries.iter(), HashMap::new()),
1071 Err(CompilerError::InvalidExtendsKeyword(make_identifier!("lib_a", "symbol")))
1072 );
1073 }
1074
1075 #[test]
1076 fn unresolved_qualification() {
1077 let libraries = vec![bind_library::Ast {
1080 name: make_identifier!("lib_a"),
1081 using: vec![],
1082 declarations: vec![bind_library::Declaration {
1083 identifier: make_identifier!["lib_b", "symbol"],
1084 value_type: bind_library::ValueType::Number,
1085 extends: true,
1086 values: vec![],
1087 }],
1088 }];
1089
1090 assert_eq!(
1091 construct_symbol_table(libraries.iter(), HashMap::new()),
1092 Err(CompilerError::UnresolvedQualification(make_identifier!("lib_b", "symbol")))
1093 );
1094 }
1095
1096 #[test]
1097 fn undeclared_key() {
1098 let libraries = vec![
1099 bind_library::Ast {
1100 name: make_identifier!("lib_a"),
1101 using: vec![],
1102 declarations: vec![],
1103 },
1104 bind_library::Ast {
1105 name: make_identifier!("lib_b"),
1106 using: vec![Include { name: make_identifier!("lib_a"), alias: None }],
1107 declarations: vec![bind_library::Declaration {
1108 identifier: make_identifier!["lib_a", "symbol"],
1109 value_type: bind_library::ValueType::Number,
1110 extends: true,
1111 values: vec![],
1112 }],
1113 },
1114 ];
1115
1116 assert_eq!(
1117 construct_symbol_table(libraries.iter(), HashMap::new()),
1118 Err(CompilerError::UndeclaredKey(make_identifier!("lib_a", "symbol")))
1119 );
1120 }
1121
1122 #[test]
1123 fn type_mismatch() {
1124 let libraries = vec![
1125 bind_library::Ast {
1126 name: make_identifier!("lib_a"),
1127 using: vec![],
1128 declarations: vec![bind_library::Declaration {
1129 identifier: make_identifier!["symbol"],
1130 value_type: bind_library::ValueType::Str,
1131 extends: false,
1132 values: vec![],
1133 }],
1134 },
1135 bind_library::Ast {
1136 name: make_identifier!("lib_b"),
1137 using: vec![Include { name: make_identifier!("lib_a"), alias: None }],
1138 declarations: vec![bind_library::Declaration {
1139 identifier: make_identifier!["lib_a", "symbol"],
1140 value_type: bind_library::ValueType::Number,
1141 extends: true,
1142 values: vec![],
1143 }],
1144 },
1145 ];
1146
1147 assert_eq!(
1148 construct_symbol_table(libraries.iter(), HashMap::new()),
1149 Err(CompilerError::TypeMismatch(make_identifier!("lib_a", "symbol")))
1150 );
1151 }
1152 }
1153}