protospec_build/semantics/convert/program/
mod.rs1use super::*;
2
3mod resolve;
4
5mod ffi;
6
7mod import;
8
9mod field;
10
11mod const_;
12
13impl Program {
14 pub fn from_ast<'a, T: ImportResolver + 'static>(
15 ast: &ast::Program,
16 resolver: &'a T,
17 ) -> AsgResult<Program> {
18 let mut cached_imports: IndexMap<String, Program> = IndexMap::new();
19
20 Program::from_ast_imports(ast, resolver, &mut cached_imports)?;
21 Program::from_ast_imported(ast, resolver, &cached_imports)
22 }
23
24 fn from_ast_imported<T: ImportResolver + 'static>(
25 ast: &ast::Program,
26 resolver: &T,
27 import_cache: &IndexMap<String, Program>,
28 ) -> AsgResult<Program> {
29 let program = Arc::new(RefCell::new(Program {
30 types: IndexMap::new(),
31 consts: IndexMap::new(),
32 transforms: IndexMap::new(),
33 functions: IndexMap::new(),
34 }));
35
36 {
37 let mut return_fields = vec![];
38 let scope = Arc::new(RefCell::new(Scope {
39 parent_scope: None,
40 program: program.clone(),
41 declared_fields: IndexMap::new(),
42 declared_inputs: IndexMap::new(),
43 }));
44
45 for declaration in ast.declarations.iter() {
47 match declaration {
48 ast::Declaration::Ffi(ffi) => {
49 Scope::convert_ffi_declaration(ffi, resolver, &*program)?;
50 }
51 _ => (),
52 }
53 }
54
55 for declaration in ast.declarations.iter() {
57 match declaration {
58 ast::Declaration::Import(import) => {
59 Scope::convert_import_declaration(import, resolver, &*program, import_cache)?;
60 }
61 _ => (),
62 }
63 }
64
65 for declaration in ast.declarations.iter() {
67 match declaration {
68 ast::Declaration::Type(type_) if matches!(type_.value.type_.raw_type, ast::RawType::Enum(_) | ast::RawType::Bitfield(_)) => {
69 let field = Scope::convert_type_declaration(type_, &*program)?;
70 let scope = Scope::convert_ast_field_arguments(&scope, &field, Some(&type_.arguments[..]))?;
71 Scope::convert_ast_field(&scope, &type_.value, &field)?;
72 }
73 ast::Declaration::Const(const_) => {
74 Scope::convert_const_declaration(const_, &*program, &scope)?;
75 }
76 _ => (),
77 }
78 }
79
80 for declaration in ast.declarations.iter() {
82 match declaration {
83 ast::Declaration::Type(type_) if !matches!(type_.value.type_.raw_type, ast::RawType::Enum(_) | ast::RawType::Bitfield(_)) => {
84 let field = Scope::convert_type_declaration(type_, &*program)?;
85 return_fields.push((type_, field));
86 }
87 _ => (),
88 }
89 }
90
91 let mut sub_scopes = vec![];
93 for (type_, field) in &return_fields {
94 sub_scopes.push(Scope::convert_ast_field_arguments(&scope, &field, Some(&type_.arguments[..]))?);
95 }
96
97 for ((type_, field), sub_scope) in return_fields.into_iter().zip(sub_scopes.iter()) {
99 Scope::convert_ast_field(sub_scope, &type_.value, &field)?;
100 }
101 }
102
103 let program = Arc::try_unwrap(program)
104 .ok()
105 .expect("leaked program arc")
106 .into_inner();
107
108 program.scan_cycles();
109 Ok(program)
110 }
111}