clr_assembler/program/
builder.rs1use crate::program::*;
2
3#[derive(Debug)]
5pub struct ClrBuilder {
6 program: ClrProgram,
7 current_type: Option<usize>,
8 current_method: Option<usize>,
9}
10
11impl ClrBuilder {
12 pub fn new(name: String) -> Self {
14 Self {
15 program: ClrProgram {
16 name,
17 version: ClrVersion { major: 1, minor: 0, build: 0, revision: 0 },
18 access_flags: ClrAccessFlags::default(),
19 external_assemblies: Vec::new(),
20 module: None,
21 types: Vec::new(),
22 global_methods: Vec::new(),
23 global_fields: Vec::new(),
24 attributes: Vec::new(),
25 constant_pool: ClrConstantPool::new(),
26 source_file: None,
27 },
28 current_type: None,
29 current_method: None,
30 }
31 }
32
33 pub fn add_external_assembly(&mut self, name: String) {
35 self.program.external_assemblies.push(ClrExternalAssembly {
36 name,
37 version: ClrVersion { major: 4, minor: 0, build: 0, revision: 0 },
38 public_key_token: None,
39 culture: None,
40 hash_value: None,
41 });
42 }
43
44 pub fn begin_class(&mut self, name: String, namespace: Option<String>) {
46 let clr_type = ClrType::new(name, namespace);
47 self.program.types.push(clr_type);
48 self.current_type = Some(self.program.types.len() - 1);
49 self.current_method = None;
50 }
51
52 pub fn begin_method(&mut self, name: String, return_type: ClrTypeReference) {
54 let mut method = ClrMethod::new(name, return_type);
55 method.access_flags.is_public = true;
57 method.impl_flags.is_managed = true;
58 if method.name == "main" {
59 method.is_entry_point = true;
60 }
61 if let Some(type_idx) = self.current_type {
62 self.program.types[type_idx].methods.push(method);
63 self.current_method = Some(self.program.types[type_idx].methods.len() - 1);
64 }
65 else {
66 self.program.global_methods.push(method);
67 self.current_method = Some(self.program.global_methods.len() - 1);
68 }
69 }
70
71 pub fn emit(&mut self, opcode: ClrOpcode, operand: Option<ClrInstructionOperand>) {
73 let inst = ClrInstruction {
74 opcode,
75 operand,
76 offset: 0, };
78
79 if let Some(type_idx) = self.current_type {
80 if let Some(method_idx) = self.current_method {
81 self.program.types[type_idx].methods[method_idx].instructions.push(inst);
82 }
83 }
84 else if let Some(method_idx) = self.current_method {
85 self.program.global_methods[method_idx].instructions.push(inst);
86 }
87 }
88
89 pub fn finish(self) -> ClrProgram {
91 self.program
92 }
93}