1use 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 #[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 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 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 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 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 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}