1use super::expr::Expr;
2use super::expr::Span;
3use super::registers::get_tgt_ids;
4use super::type_system::DataType;
5use crate::compiler::Namespace;
6use crate::data::Data;
7use crate::data::NULL;
8use crate::instr::Instr;
9use rustc_hash::FxHashMap;
10use rustc_hash::FxHashSet;
11use smol_strc::SmolStr;
12use std::rc::Rc;
13
14pub use crate::rt::{
18 DynamicLibFn, EnumType, EnumVariant, ErrorCatch, HostFnSig, InstrSrc, Pools, Source, Struct,
19};
20
21#[derive(Debug)]
22pub struct Function {
23 pub name: SmolStr,
24 pub args: Box<[(SmolStr, Option<DataType>)]>,
25 pub code: Rc<[Expr]>,
26 pub impls: Vec<FunctionImpl>,
27 pub is_recursive: Option<bool>,
28 pub returns_null: bool,
29 pub src_file: u16,
30 pub return_type_cache: Vec<(Box<[DataType]>, DataType)>,
32 pub direct_calls: Box<[SmolStr]>,
33 pub name_span: Span,
34 pub return_type: Option<(DataType, Span)>,
40}
41
42#[derive(Debug)]
43pub struct FunctionImpl {
44 pub loc: u16,
45 pub args_loc: Box<[u16]>,
46 pub arg_types: Box<[DataType]>,
47}
48
49#[derive(Debug)]
50pub struct FnSignature {
51 pub name: SmolStr,
52 pub args: Box<[DataType]>,
53 pub return_type: DataType,
54 pub id: u16,
55 pub variadic: bool,
59}
60
61#[derive(Debug)]
62pub struct Dynamiclib {
63 pub name: SmolStr,
64 pub fns: Box<[FnSignature]>,
65 pub is_host: bool,
71}
72
73#[derive(Clone, Copy)]
74pub struct Ctx {
75 pub block_id: u16,
76 pub is_compiling_recursive: bool,
78 pub single_run: bool,
80 pub file_idx: u16,
82 pub offset: u16,
84}
85
86impl Ctx {
87 #[inline(always)]
88 #[must_use]
89 pub const fn no_single_run(self) -> Self {
90 Self {
91 single_run: false,
92 ..self
93 }
94 }
95 #[inline(always)]
96 #[must_use]
97 pub const fn advance_offset(self, output_len: u16) -> Self {
98 Self {
99 offset: self.offset + output_len,
100 ..self
101 }
102 }
103 #[inline(always)]
104 #[must_use]
105 pub const fn set_offset(self, offset: u16) -> Self {
106 Self { offset, ..self }
107 }
108}
109
110pub struct State<'a> {
111 pub registers: &'a mut Vec<Data>,
112 pub fns: &'a mut Vec<Function>,
113 pub structs: &'a mut Vec<Struct>,
114 pub enums: &'a mut Vec<EnumType>,
115 pub pools: &'a mut Pools,
116 pub instr_src: &'a mut Vec<InstrSrc>,
117 pub fn_registers: &'a mut Vec<Vec<u16>>,
118 pub dyn_libs: &'a mut Vec<Dynamiclib>,
119 pub allocated_arg_count: &'a mut usize,
120 pub allocated_call_depth: &'a mut usize,
121 pub const_registers: &'a mut FxHashMap<Data, u16>,
122 pub free_registers: &'a mut Vec<u16>,
123 pub sources: &'a mut Vec<Source>,
124 pub reserved_registers: FxHashSet<u16>,
125 pub namespace: &'a mut Namespace,
126}
127
128impl State<'_> {
129 pub fn free_reg(&mut self, id: u16, v: &[Variable]) {
136 if !v.iter().any(|var| var.register_id == id)
137 && !self.const_registers.values().any(|®| reg == id)
138 && !self.reserved_registers.contains(&id)
139 && !self.free_registers.contains(&id)
140 {
141 self.free_registers.push(id);
142 }
143 }
144 pub fn alloc_reg(&mut self) -> u16 {
146 if let Some(reg) = self.free_registers.pop() {
147 reg
148 } else {
149 self.registers.push(NULL);
150 (self.registers.len() - 1) as u16
151 }
152 }
153 #[inline(always)]
156 pub fn alloc_reg_tgt(&mut self, tgt_id: Option<u16>) -> u16 {
157 if let Some(id) = tgt_id {
158 id
159 } else {
160 self.alloc_reg()
161 }
162 }
163 pub fn free_scope_registers(
165 &mut self,
166 regs_before: u16,
167 scope_instrs: &[Instr],
168 v: &[Variable],
169 ) {
170 for id in get_tgt_ids(scope_instrs) {
171 if id >= regs_before {
172 self.free_reg(id, v);
173 }
174 }
175 }
176
177 pub fn free_loop_scope_registers(
179 &mut self,
180 regs_before: u16,
181 scope_instrs: &[Instr],
182 v: &[Variable],
183 ) {
184 self.free_scope_registers(regs_before, scope_instrs, v);
185 for instr in scope_instrs {
187 if let Instr::CloneArray(template_reg, _, _) = instr
188 && *template_reg >= regs_before
189 {
190 self.free_reg(*template_reg, v);
191 } else if let Instr::CloneStruct(template_reg, _) = instr
192 && *template_reg >= regs_before
193 {
194 self.free_reg(*template_reg, v);
195 } else if let Instr::CloneEnum(template_reg, _) = instr
196 && *template_reg >= regs_before
197 {
198 self.free_reg(*template_reg, v);
199 }
200 }
201 }
202 #[inline(always)]
205 pub fn add_to_src(&mut self, ctx: Ctx, output: &[Instr], span: Span) {
206 self.instr_src.push(InstrSrc {
207 instr: unsafe { *output.last().unwrap_unchecked() },
208 span,
209 file_id: ctx.file_idx,
210 });
211 }
212}
213
214#[derive(Debug)]
215pub struct Variable {
216 pub name: SmolStr,
217 pub register_id: u16,
218 pub var_type: DataType,
219}