interpreter/
lib.rs

1#![feature(fn_traits)]
2#![feature(trait_alias)]
3#![feature(concat_idents)]
4#![feature(macro_metavar_expr)]
5#![feature(get_mut_unchecked)]
6#![feature(impl_trait_in_bindings)]
7#![feature(unboxed_closures)]
8
9use std::{collections::HashMap, process, sync::Arc, time::Instant};
10
11pub use paste::paste;
12
13#[macro_use]
14pub mod macros;
15
16pub mod runtime;
17pub use runtime::RuntimeValue;
18
19#[cfg(feature = "parser")]
20pub mod parser;
21
22#[cfg(feature = "phf")]
23pub use phf;
24
25mod parallel_ipreter;
26
27pub use tokio;
28
29#[macro_use]
30pub mod package;
31pub mod types;
32pub mod val;
33
34pub(crate) use package::*;
35use tokio::runtime::{Builder, Runtime};
36use types::ExtendsInternal;
37pub use types::{Extends, Heap, LanguagePackages, MethodRes, PrototypeDocs};
38pub use val::*;
39
40pub use lealang_chalk_rs::Chalk;
41
42pub static VERSION_INT: u16 = 10;
43
44pub trait Package: Sync {
45  fn name(&self) -> &'static [u8];
46
47  fn doc(&self) -> HashMap<&'static str, &'static [&'static str; 3]> {
48    HashMap::new()
49  }
50
51  fn prototype_docs(&self) -> PrototypeDocs {
52    PrototypeDocs::default()
53  }
54
55  fn prototype(&self) -> Extends {
56    Extends::default()
57  }
58
59  fn methods(&self) -> MethodRes {
60    &[]
61  }
62}
63
64pub struct RespPackage {
65  pub methods: MethodRes,
66  pub extends: Option<Extends>,
67}
68
69pub struct Application<'a> {
70  code: Arc<Structure>,
71  pub(crate) pkg: LanguagePackages<'a>,
72  // Resolve path from mod name
73  pkg_resolver: Box<dyn FnMut(&str, bool) -> Vec<RespPackage>>,
74  // Log in case of full access request
75  log_info: Box<dyn FnMut(&str) -> ()>,
76}
77
78unsafe impl Send for Application<'_> {}
79unsafe impl Sync for Application<'_> {}
80
81pub type Args = &'static [&'static str];
82
83pub type ModuleArgs = &'static [&'static str];
84
85pub type StaticLeadModule = Arc<HashMap<&'static str, (ModuleArgs, &'static [Args])>>;
86
87#[derive(Debug)]
88pub enum LeadCode {
89  // Lead Modules will be lazily used
90  LeadModule(StaticLeadModule),
91  // Lead Code should be instantly made ready
92  Code(&'static [Args]),
93}
94
95pub type Structure = HashMap<
96  // File
97  &'static str,
98  // Code
99  LeadCode,
100>;
101
102impl<'a> Application<'a> {
103  pub fn new<
104    T: FnOnce() -> Structure,
105    F: FnMut(&str, bool) -> Vec<RespPackage> + 'static,
106    R: FnMut(&str) -> () + 'static,
107  >(
108    dll_resolver: F,
109    requested_perm: R,
110    structure: T,
111  ) -> Self {
112    let code = Arc::new(structure());
113
114    Self {
115      code,
116      pkg: LanguagePackages::new(),
117      pkg_resolver: Box::new(dll_resolver),
118      log_info: Box::new(requested_perm),
119    }
120  }
121
122  pub fn add_pkg<T: Package + 'static>(&mut self, package: T) -> &mut Self {
123    self.pkg.import(package);
124    self
125  }
126
127  pub fn add_pkg_static(&mut self, package: &'static dyn Package) -> &mut Self {
128    self.pkg.import_static(package);
129    self
130  }
131
132  pub fn add_pkg_box(&mut self, package: Box<dyn Package>) -> &mut Self {
133    self.pkg.import_dyn(package);
134    self
135  }
136
137  pub fn add_pkg_raw(&mut self, name: &'static [u8], methods: MethodRes) -> &mut Self {
138    let pkg = ImplPackage { name, methods };
139
140    self.pkg.import(pkg);
141
142    self
143  }
144
145  pub fn list_cmds(&mut self) -> &mut Self {
146    let mut chalk = Chalk::new();
147    chalk.red().bold();
148    chalk.println(&"The Lead Programming Language");
149
150    chalk.reset_weight().yellow().println(&"Interpreter");
151
152    self.pkg.list(&mut chalk);
153    self
154  }
155
156  /// ⚠️ This function still is panicking
157  pub fn run_non(mut self, runtime: Runtime) {
158    parallel_ipreter::schedule(runtime, &mut self)
159  }
160
161  pub fn run(self, time: bool) -> ! {
162    if time {
163      println!("⚒️  Building execution Runtime...");
164    }
165
166    // Start the Timer NOW!!!
167    let inst = Instant::now();
168
169    let runtime = Builder::new_multi_thread()
170      .enable_all()
171      .build()
172      .expect("Unable to build async runtime");
173
174    let dur = inst.elapsed();
175
176    if time {
177      println!("✅ Runtime Ready in {:?}", dur);
178      println!("⚒️  Executing...");
179    }
180
181    // Start the Timer NOW!!!
182    let inst = Instant::now();
183
184    self.run_non(runtime);
185
186    let dur = inst.elapsed();
187
188    if time {
189      println!("✅ Runtime Time Elasped: {:?}", dur);
190    }
191
192    process::exit(0)
193  }
194}