1use std::collections::HashMap;
2
3use gc::Gc;
4
5use context::Context;
6use symbol::Symbol;
7use util::{as_sym_list, is_shl};
8use value::Value;
9
10#[derive(Clone, Debug, Eq, Finalize, Hash, PartialEq, Trace)]
13pub enum ModuleHeaderError {
14 BadImportForm,
16
17 BadModuleForm,
19
20 NoModuleForm,
22}
23
24pub fn parse_module_header<C: 'static + Context>(
26 mut values: Vec<Gc<Value<C>>>,
27) -> Result<(Symbol, Vec<Symbol>, HashMap<Symbol, Vec<Symbol>>, Vec<Gc<Value<C>>>), ModuleHeaderError> {
28 fn parse_header_form<C: 'static + Context>(
29 import: bool,
30 value: Gc<Value<C>>,
31 ) -> Result<(Symbol, Vec<Symbol>), ModuleHeaderError> {
32 if let Some(mut sym_list) = as_sym_list(value) {
33 if sym_list.len() >= 2 {
34 let head = sym_list.remove(0);
35 if import && head != Symbol::from("import") {
36 Err(ModuleHeaderError::BadImportForm)
37 } else if !import && head != Symbol::from("module") {
38 Err(ModuleHeaderError::BadModuleForm)
39 } else {
40 let name = sym_list.remove(0);
41 Ok((name, sym_list))
42 }
43 } else {
44 Err(if import {
45 ModuleHeaderError::BadImportForm
46 } else {
47 ModuleHeaderError::BadModuleForm
48 })
49 }
50 } else {
51 Err(if import {
52 ModuleHeaderError::BadImportForm
53 } else {
54 ModuleHeaderError::BadModuleForm
55 })
56 }
57 }
58
59 if values.len() == 0 {
60 return Err(ModuleHeaderError::NoModuleForm);
61 }
62
63 let import_sym = Symbol::from("import");
64 let (name, exports) = parse_header_form(false, values.remove(0))?;
65 let end = values
66 .iter()
67 .cloned()
68 .position(|x| !is_shl(import_sym, x))
69 .unwrap_or_else(|| values.len());
70
71 let imports = values
72 .drain(..end)
73 .map(|v| parse_header_form(true, v))
74 .collect::<Result<_, _>>()?;
75 Ok((name, exports, imports, values))
76}