jsonpiler/
compiler.rs

1//! Implementation of the compiler inside the `Jsonpiler`.
2use super::{
3  Bind::{Lit, Var},
4  Builtin, ErrOR, FuncInfo, GlobalKind, JFunc, Json, JsonWithPos, Jsonpiler, Name, Position,
5  ScopeInfo,
6  VarKind::Global,
7  add, err,
8  utility::{get_int_str, imp_call, mn, scope_begin, scope_end},
9};
10use core::mem;
11use std::{
12  collections::{HashMap, HashSet},
13  fs::File,
14  io::{self, Write as _},
15};
16impl Jsonpiler {
17  /// Builds the assembly code from the parsed JSON.
18  /// This function is the main entry point for the compilation.
19  /// It takes the parsed JSON, sets up the initial function table,
20  /// evaluates the JSON, and writes the resulting assembly code to a file.
21  /// # Arguments
22  /// * `source` - The JSON string.
23  /// * `json_file` - The name of the original JSON file.
24  /// * `out_file` - The name of the file to write the assembly code to.
25  /// # Returns
26  /// * `Ok(())`
27  /// * `Err(Box<dyn Error>)` - If an error occurred during the compilation.
28  /// # Errors
29  /// * `Box<dyn Error>` - If an error occurred during the compilation.
30  #[inline]
31  pub fn build(&mut self, source: String, out_file: &str) -> ErrOR<()> {
32    let json = self.parse(source)?;
33    self.include_flag = HashSet::new();
34    self.text = vec![];
35    self.bss = vec![];
36    self.data = vec![];
37    self.global_seed = 0;
38    self.builtin = HashMap::new();
39    self.vars = vec![HashMap::new(), HashMap::new()];
40    self.all_register();
41    let mut info = ScopeInfo::default();
42    let result = self.eval(json.value, &mut info)?;
43    let mut writer = io::BufWriter::new(File::create(out_file)?);
44    writer.write_all(mn(".intel_syntax", &["noprefix"]).as_bytes())?;
45    writer.write_all(include_bytes!("asm/once/data.s"))?;
46    for data in &mut self.data {
47      writer.write_all(data.as_bytes())?;
48    }
49    writer.write_all(include_bytes!("asm/once/bss.s"))?;
50    for bss in &mut self.bss {
51      writer.write_all(bss.as_bytes())?;
52    }
53    writer.write_all(include_bytes!("asm/once/main.s"))?;
54    write!(
55      writer,
56      include_str!("asm/common/prologue.s"),
57      size = format!("0x{:x}", info.calc_alloc(8)?)
58    )?;
59    writer.write_all(include_bytes!("asm/once/startup.s"))?;
60    for body in &mut info.body {
61      writer.write_all(body.as_bytes())?;
62    }
63    if let Json::Int(int) = result {
64      writer.write_all(mn("mov", &["rcx", &get_int_str(&int, &mut info)?]).as_bytes())
65    } else {
66      writer.write_all(mn("xor", &["ecx", "ecx"]).as_bytes())
67    }?;
68    writer.write_all(imp_call("ExitProcess").as_bytes())?;
69    writer.write_all(mn(".seh_endproc", &[]).as_bytes())?;
70    for text in &mut self.text {
71      writer.write_all(text.as_bytes())?;
72    }
73    writer.write_all(include_bytes!("asm/once/handler.s"))?;
74    writer.flush()?;
75    Ok(())
76  }
77  /// Evaluate JSON representation.
78  pub(crate) fn eval(&mut self, mut json: Json, info: &mut ScopeInfo) -> ErrOR<Json> {
79    if let Json::Array(Lit(list)) = &mut json {
80      Ok(Json::Array(Lit(self.eval_args(mem::take(list), info)?)))
81    } else if let Json::Object(Lit(object)) = &mut json {
82      let mut result = Json::Null;
83      for (key, val) in object.iter_mut() {
84        if let Some(builtin) = self.builtin.get_mut(key) {
85          let scoped = builtin.scoped;
86          let func = builtin.func;
87          let mut tmp = ScopeInfo::default();
88          if scoped {
89            self.vars.push(HashMap::new());
90            scope_begin(&mut tmp, info)?;
91          }
92          let args = if let Json::Array(Lit(arr)) = &mut val.value {
93            let raw_args = mem::take(arr);
94            if self.builtin.get(key).is_some_and(|built| built.skip_eval) {
95              raw_args
96            } else {
97              self.eval_args(raw_args, info)?
98            }
99          } else {
100            self.eval_args(vec![mem::take(val)], info)?
101          };
102          result = func(
103            self,
104            FuncInfo { name: mem::take(key), pos: mem::take(&mut val.pos), args },
105            info,
106          )?;
107          if let Some((addr, size)) = result.tmp() {
108            info.free(addr, size)?;
109          }
110          if scoped {
111            scope_end(&mut tmp, info)?;
112            self.vars.pop();
113          }
114        } else if let Ok(Json::Function(func)) = self.get_var(key, &val.pos) {
115          info.body.push(mn("call", &[&format!(".L{:x}", func.name)]));
116          result = if let Json::Int(_) = *func.ret {
117            let name = info.get_tmp(8)?;
118            info.body.push(mn("mov", &[&format!("qword{name}"), "rax"]));
119            Json::Int(Var(name))
120          } else {
121            Json::Null
122          }
123        } else {
124          return err!(self, val.pos, "The `{key}` function is undefined.");
125        }
126      }
127      Ok(result)
128    } else {
129      Ok(json)
130    }
131  }
132  /// Evaluate arguments.
133  fn eval_args(
134    &mut self, mut args: Vec<JsonWithPos>, info: &mut ScopeInfo,
135  ) -> ErrOR<Vec<JsonWithPos>> {
136    for arg in &mut args {
137      let with_pos = mem::take(arg);
138      arg.pos = with_pos.pos;
139      arg.value = self.eval(with_pos.value, info)?;
140    }
141    Ok(args)
142  }
143  /// Generates a unique name for internal use.
144  pub(crate) fn get_global(&mut self, name: &GlobalKind, value: &str) -> ErrOR<Name> {
145    let seed = self.global_seed;
146    match name {
147      GlobalKind::Bss => self.bss.push(format!("  .lcomm .L{seed:x}, {value}\n")),
148      GlobalKind::Str => {
149        if let Some(str_seed) = self.str_cache.get(value) {
150          return Ok(Name { var: Global, seed: *str_seed });
151        }
152        self.str_cache.insert(value.to_owned(), seed);
153        self.data.push(format!("  .L{seed:x}: .string \"{value}\"\n"));
154      }
155      GlobalKind::Int | GlobalKind::Float => {
156        self.data.push(format!("  .align 8\n  .L{seed:x}: .quad {value}\n"));
157      }
158      GlobalKind::Func => (),
159    }
160    self.global_seed = add(self.global_seed, 1)?;
161    Ok(Name { var: Global, seed })
162  }
163  /// Gets variable.
164  pub(crate) fn get_var(&self, var_name: &str, pos: &Position) -> ErrOR<Json> {
165    for scope in self.vars.iter().rev() {
166      if let Some(val) = scope.get(var_name) {
167        return Ok(val.clone());
168      }
169    }
170    err!(self, pos, "Undefined variables: `{var_name}`")
171  }
172  /// Registers a function in the function table.
173  pub(crate) fn register(&mut self, name: &str, flag: (bool, bool), func: JFunc) {
174    self.builtin.insert(name.into(), Builtin { skip_eval: flag.0, scoped: flag.1, func });
175  }
176}