pipeline_script/compiler/
mod.rs1mod expr;
2mod stmt;
3mod r#type;
4
5use crate::context::Context;
6use crate::llvm::context::LLVMContext;
7use crate::llvm::global::Global;
8use crate::llvm::module::LLVMModule;
9use std::collections::HashMap;
10use std::rc::Rc;
11use std::sync::RwLock;
12
13use crate::ast::module::Module;
14use crate::context::key::ContextKey;
15use crate::context::value::ContextValue;
16use crate::llvm::types::LLVMType;
17use crate::llvm::value::fucntion::FunctionValue;
18use crate::llvm::value::LLVMValue;
19
20pub struct Compiler {
21 module: Module,
22 ctx: LLVMContext,
23 builtin_symbol: HashMap<String, LLVMValue>,
24 llvm_module: Rc<RwLock<LLVMModule>>,
25}
26
27impl Compiler {
28 pub fn new(module: Module) -> Self {
29 let llvm_ctx = LLVMContext::new();
30 let llvm_module = llvm_ctx.create_module(module.get_name());
31 Self {
32 ctx: llvm_ctx,
33 module,
34 llvm_module: Rc::new(RwLock::new(llvm_module)),
35 builtin_symbol: HashMap::new(),
36 }
37 }
38 pub fn register_builtin_symbol(&mut self, name: &str, ty: LLVMValue) {
39 self.builtin_symbol.insert(name.to_string(), ty);
40 }
41 pub fn register_llvm_function(&mut self, name: &str, ty: LLVMType, arg_names: Vec<String>) {
42 self.llvm_module
43 .write()
44 .unwrap()
45 .register_function(name, ty, arg_names);
46 }
47 pub fn compile(&mut self, ctx: &Context) -> Rc<RwLock<LLVMModule>> {
48 let ctx = Context::with_type_table(ctx, HashMap::new());
49 let ctx = Context::with_scope(&ctx);
51 let ctx = Context::with_value(
52 &ctx,
53 ContextKey::LLVMModule,
54 ContextValue::LLVMModule(self.llvm_module.clone()),
55 );
56 for (name, ty) in self.builtin_symbol.iter() {
58 ctx.set_symbol(name.clone(), ty.clone());
59 }
60 for (name, item) in self.module.get_structs() {
62 if !item.generics.is_empty() {
63 continue;
64 }
65 let fields = item.get_fields();
66 let mut field_index: HashMap<String, usize> = HashMap::new();
67 for (i, field) in fields.iter().enumerate() {
68 field_index.insert(field.name.clone(), i);
69 }
70 let t = item.get_type();
71 let mut t = self.get_type(&ctx, &t);
72 if t.is_function() {
73 t = Global::pointer_type(t);
74 }
75 self.llvm_module
76 .write()
77 .unwrap()
78 .register_struct(name, field_index, t);
79 }
80 for (name, item) in self.module.get_type_aliases().iter() {
82 let t = self.compile_type(item.get_type());
83 self.llvm_module
84 .write()
85 .unwrap()
86 .register_struct(name, HashMap::new(), t);
87 }
88 let builder = Global::create_builder();
89 let ctx = Context::with_builder(&ctx, builder);
90 let ctx = Context::with_default_expr(&ctx);
91 for (name, item) in self.module.get_functions().iter() {
93 if item.is_template {
94 continue;
95 }
96 let args = item.args();
97 let mut arg_types = vec![];
98 let mut is_var_arg = false;
99 let mut is_array_vararg = false;
100 for arg in args {
101 if arg.is_var_arg() {
102 is_var_arg = true;
103 continue;
104 }
105 if arg.is_array_vararg() {
106 is_array_vararg = true;
107 }
108 let ty = arg.r#type().unwrap();
109 let t = self.get_type(&ctx, &ty);
110 if t.is_function() {
112 arg_types.push((
113 arg.name().to_string(),
114 Global::struct_type(
115 "Closure".into(),
116 vec![
117 ("ptr".to_string(), Global::pointer_type(t)),
118 ("env".to_string(), Global::pointer_type(Global::unit_type())),
119 ],
120 ),
121 ));
122 continue;
123 }
124 arg_types.push((arg.name().to_string(), t));
125 }
126 let return_type0 = item.return_type();
127 let return_type = self.get_type(&ctx, return_type0);
128 let t = if is_var_arg || item.is_vararg() {
129 Global::function_type_with_var_arg(return_type.clone(), arg_types)
130 } else {
131 Global::function_type(return_type.clone(), arg_types)
132 };
133 let f = if item.is_extern {
134 self.llvm_module
135 .write()
136 .unwrap()
137 .register_extern_function(name, t)
138 } else {
139 let args = item.args();
140 let param_names: Vec<String> =
141 args.iter().map(|arg| arg.name()).collect::<Vec<_>>();
142 self.llvm_module
143 .write()
144 .unwrap()
145 .register_function(name, t, param_names)
146 };
147 let mut function_value = FunctionValue::new(
148 f.get_function_ref(),
149 name.clone(),
150 Box::new(return_type.get_undef()),
151 args.iter()
152 .map(|arg| {
153 let name = arg.name().clone();
154 let undef = self.compile_type(&arg.r#type().unwrap()).get_undef();
155
156 if arg.is_env() {
157 if let Some(default_expr) = arg.get_default() {
158 ctx.set_default_expr(name.clone(), Box::new(default_expr.clone()));
159 }
160 (name, undef)
161 } else if let Some(default_expr) = arg.get_default() {
162 let r = self.compile_expr(default_expr, &ctx);
163 (
164 name,
165 if undef.is_inject() {
166 LLVMValue::Inject(Box::new(r))
167 } else {
168 r
169 },
170 )
171 } else {
172 (name, undef)
173 }
174 })
175 .collect(),
176 );
177 if item.is_vararg() || is_var_arg {
178 function_value.set_vararg();
179 }
180 if is_array_vararg {
181 function_value.set_array_vararg();
182 }
183 ctx.set_symbol(name.clone(), function_value.into());
184 }
185
186 for (_, item) in self.module.get_functions().iter() {
188 if item.is_extern || item.is_template {
189 continue;
190 }
191 let ctx = self.prepare_function(&ctx, item);
192 for stmt in item.body() {
193 self.compile_stmt(stmt, &ctx);
194 }
195 let flag = ctx.get_flag("return").unwrap();
196 if !flag {
197 let builder = ctx.get_builder();
198 builder.build_return_void();
199 }
200 }
201
202 let main = self.llvm_module.write().unwrap().register_function(
204 "$Module.main",
205 Global::function_type(Global::unit_type(), vec![]),
206 vec![],
207 );
208 let block = self.module.get_global_block();
209
210 let entry = main.append_basic_block("entry");
211 let builder = ctx.get_builder();
212 builder.position_at_end(entry);
213 let function_value = FunctionValue::new(
214 main.get_function_ref(),
215 "$Module.main".into(),
216 Box::new(Global::unit_type().get_undef()),
217 vec![],
218 );
219 let ctx = Context::with_function(&ctx, function_value);
220 let ctx = Context::with_scope(&ctx);
221 let ctx = Context::with_flag(&ctx, "return", false);
222 for stmt in block.iter() {
223 self.compile_stmt(stmt, &ctx);
224 }
225 let flag = ctx.get_flag("return").unwrap();
226 if !flag {
227 builder.build_return_void();
228 }
229 self.llvm_module.clone()
230 }
231 pub fn prepare_function(
232 &self,
233 ctx: &Context,
234 function: &crate::ast::function::Function,
235 ) -> Context {
236 let function_value = ctx
237 .get_symbol(function.name())
238 .unwrap()
239 .as_function()
240 .unwrap();
241 let entry = function_value.append_basic_block("entry");
242 let builder = ctx.get_builder();
243 builder.position_at_end(entry);
244 let ctx = Context::with_function(ctx, function_value.clone());
245 let ctx = Context::with_type(&ctx, "current_function".into(), function.get_type());
246 let ctx = Context::with_scope(&ctx);
247 let ctx = Context::with_flag(&ctx, "return", false);
248 for arg in function.args() {
250 let arg_name = arg.name();
251 let mut arg_value = function_value.get_param(arg_name.clone()).unwrap();
252 if let LLVMValue::Function(f) = &mut arg_value {
253 f.set_closure()
254 }
255 ctx.set_symbol(arg_name, arg_value);
256 }
257 ctx
258 }
259}