pipeline_script/core/
engine.rs1use crate::ast::r#type::Type;
2use crate::compiler::Compiler;
3use crate::context::Context;
4use crate::core::builtin::println;
5use crate::lexer::Lexer;
6use crate::llvm::builder::lljit::LLJITBuilder;
7use crate::llvm::context::LLVMContext;
8use crate::llvm::value::LLVMValue;
9use crate::parser::Parser;
10use crate::postprocessor::{r#type::TypePostprocessor, run_visitor, DynVisitor, Stage, Visitor};
11use crate::preprocessor::{ImportPreprocessor, Preprocessor};
12use std::collections::HashMap;
13use std::ffi::c_void;
14use std::fs;
15use std::path::{Path, PathBuf};
16
17pub struct Engine {
18 prelude_scripts: Vec<String>,
19 preprocessors: Vec<Box<dyn Preprocessor>>,
20 function_map: HashMap<String, *mut c_void>,
21 visitors: Vec<Box<dyn DynVisitor>>,
22 builtin_symbol_types: HashMap<String, Type>,
23 builtin_symbol: HashMap<String, LLVMValue>,
24 pub test_llvm: bool,
26 pub test_llvm_files: Vec<PathBuf>,
27}
28impl Default for Engine {
29 fn default() -> Self {
30 Self {
31 prelude_scripts: vec![],
32 preprocessors: vec![Box::new(ImportPreprocessor)],
33 visitors: vec![],
34 function_map: HashMap::new(),
35 builtin_symbol_types: HashMap::new(),
36 test_llvm: false,
37 test_llvm_files: vec![],
38 builtin_symbol: HashMap::new(),
39 }
40 }
41}
42
43impl Engine {
44 pub fn run_llvm_file(&self, path: impl AsRef<Path>) {
45 let r = fs::read_to_string(path.as_ref()).unwrap();
46 let ctx = LLVMContext::with_mc_jit();
47 let module = ctx.parse_ir(&r).unwrap();
48 let executor = module.create_executor().unwrap();
49 let println_function = module.get_function_ref("println");
50 executor.add_global_mapping(println_function, println as *mut c_void);
51 executor.run_function("$Module.main", &mut []);
52 }
53 pub fn run_file(&mut self, path: impl AsRef<Path>) {
54 let r = fs::read_to_string(path.as_ref()).unwrap();
55 self.run_script(r);
56 }
57 pub fn set_test_llvm(&mut self, test: bool) {
58 self.test_llvm = test;
59 }
60 pub fn add_test_llvm_file(&mut self, path: impl AsRef<Path>) {
61 self.test_llvm_files.push(path.as_ref().to_path_buf());
62 }
63 pub fn register_external_function(&mut self, name: impl Into<String>, f: *mut c_void) {
64 self.function_map.insert(name.into(), f);
65 }
66 pub fn register_builtin_symbol_type(&mut self, name: impl Into<String>, ty: Type) {
67 self.builtin_symbol_types.insert(name.into(), ty);
68 }
69 pub fn register_builtin_symbol(&mut self, name: impl Into<String>, value: LLVMValue) {
70 self.builtin_symbol.insert(name.into(), value);
71 }
72 pub fn register_visitor(&mut self, visitor: impl Visitor + 'static) {
73 self.visitors.push(Box::new(visitor));
74 }
75 pub fn register_preprocessor(&mut self, preprocessor: impl Preprocessor + 'static) {
76 self.preprocessors.push(Box::new(preprocessor));
77 }
78 pub fn register_precluded_scripts(&mut self, scripts: &[&str]) {
79 for script in scripts {
80 self.prelude_scripts.push(script.to_string());
81 }
82 }
83 pub fn run_script(&mut self, script: impl AsRef<str>) {
84 let mut s = script.as_ref().to_string();
85 for i in self.prelude_scripts.iter() {
86 s = format!("{}\n{}", i, s)
87 }
88 for preprocessor in &mut self.preprocessors {
89 s = preprocessor.process(&s)
90 }
91 let lexer = Lexer::from_script("main", s);
93 let ctx = Context::background();
95 let ctx = Context::with_module_slot_map(&ctx, Default::default());
96 let mut parser = Parser::new(lexer, &ctx);
97 let module_key = parser.parse(&ctx).unwrap();
98 ctx.apply_mut_module(module_key, |module| {
99 for i in self
100 .visitors
101 .iter()
102 .filter(|i| i.stage() == Stage::BeforeTypeInfer)
103 {
104 run_visitor(module, &**i)
105 }
106 });
107 let mut type_preprocessor = TypePostprocessor::new();
108 for (name, ty) in self.builtin_symbol_types.iter() {
109 type_preprocessor.register_builtin_symbol_type(name, ty.clone());
110 }
111 let module = type_preprocessor.process(module_key, &ctx);
112 let mut compiler = Compiler::new(module.clone());
113 for (name, value) in self.builtin_symbol.iter() {
114 compiler.register_builtin_symbol(name, value.clone());
115 }
116 ctx.register_module(module);
117 ctx.apply_mut_module(module_key, |module| {
118 for i in self
119 .visitors
120 .iter()
121 .filter(|i| i.stage() == Stage::AfterTypeInfer)
122 {
123 run_visitor(module, &**i)
124 }
125 });
126
127 let llvm_module = compiler.compile(&ctx);
129 let llvm_module = llvm_module.read().unwrap();
130 let jit = LLJITBuilder::new().create_lljit();
133 let safe_module = llvm_module.create_thread_safe_module();
134 match jit.add_main_dylib_llvm_ir_module(safe_module) {
135 Ok(_) => {}
136 Err(e) => {
137 println!("{}", e);
138 }
139 }
140 for (name, f) in &self.function_map {
141 jit.define_main_dylib_symbol(name, *f as u64);
142 }
143 let main = jit.lookup("$Module.main").unwrap();
144 let func: extern "C" fn() = unsafe { std::mem::transmute(main) };
145 func();
146 }
147}