jsonpiler/
lib.rs

1/*!A JSON-based programming language compiler.
2Compiles and executes a JSON-based program using the Jsonpiler.
3This program performs the following steps:
41. Parses the first CLI argument as the input JSON file path.
52. Reads the file content into a string.
63. Parses the string into a `Json` structure.
74. Compiles the structure into assembly code.
85. Assembles it into an `.obj` file.
96. Links it into an `.exe`.
107. Executes the resulting binary.
118. Returns its exit code.
12# Panics
13This function will panic if:
14- The platform is not Windows.
15- CLI arguments are invalid.
16- File reading, parsing, compilation, assembling, linking, or execution fails.
17- The working directory or executable filename is invalid.
18# Requirements
19- `as` and `ld` must be available in the system PATH.
20- On failure, exits with code 1 using `error_exit`.
21# Example
22```sh
23jsonpiler test.json
24```
25# Platform
26Windows only.
27*/
28mod assembler;
29mod bind;
30mod builtin;
31mod compile_context;
32mod func_info;
33mod json;
34mod label;
35mod macros;
36mod parser;
37mod portable_executable;
38mod scope_info;
39mod utility;
40use compile_context::CompileContext;
41use core::error::Error;
42use parser::Parser;
43use scope_info::ScopeInfo;
44use std::{collections::HashMap, vec::IntoIter};
45#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
46#[expect(dead_code)]
47enum Disp {
48  Byte(i8),
49  Dword(i32),
50  Zero,
51}
52#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
53#[expect(dead_code, clippy::arbitrary_source_item_ordering)]
54enum Reg {
55  Rax = 0,
56  Rcx = 1,
57  Rdx = 2,
58  Rbx = 3,
59  Rsp = 4,
60  Rbp = 5,
61  Rsi = 6,
62  Rdi = 7,
63  R8 = 8,
64  R9 = 9,
65  R10 = 10,
66  R11 = 11,
67  R12 = 12,
68  R13 = 13,
69  R14 = 14,
70  R15 = 15,
71}
72#[derive(Clone, Copy, PartialEq, Eq)]
73#[expect(clippy::allow_attributes)]
74enum Memory {
75  #[allow(dead_code)]
76  Base(Reg, Disp),
77  Reg(Reg),
78  RipRel(i32),
79  #[allow(dead_code)]
80  Sib(Sib),
81}
82#[derive(Clone, Copy, PartialEq, Eq)]
83#[expect(dead_code)]
84enum Scale {
85  S1 = 0,
86  S2 = 1,
87  S4 = 2,
88  S8 = 3,
89}
90#[derive(Clone, Copy, PartialEq, Eq)]
91struct Sib {
92  base: Reg,
93  disp: Disp,
94  index: Reg,
95  scale: Scale,
96}
97#[repr(u8)]
98#[derive(Eq, PartialEq, Ord, PartialOrd, Hash)]
99enum Sect {
100  Bss,
101  Data,
102  Idata,
103  Text,
104}
105struct Assembler {
106  addr_sect: HashMap<usize, Sect>,
107  dlls: Dlls,
108  rva: HashMap<Sect, u32>,
109  sym_addr: HashMap<usize, u32>,
110}
111type Dlls = Vec<(&'static str, Vec<(u16, &'static str)>)>;
112#[expect(dead_code)]
113#[derive(Clone, Debug)]
114enum Inst {
115  AddRId(Reg, u32),
116  AddRR(Reg, Reg),
117  AndRbRb(Reg, Reg),
118  Bss(usize, u32),
119  Byte(usize, u8),
120  Call(usize),
121  CallApi((usize, usize)),
122  Clear(Reg),
123  CmpRIb(Reg, i8),
124  Cqo,
125  IDivR(Reg),
126  IMulRR(Reg, Reg),
127  Jmp(usize),
128  JzJe(usize),
129  Label(usize),
130  LeaRM(Reg, VarKind),
131  MovMId(VarKind, u32),
132  MovMbIb(VarKind, u8),
133  MovMbRb(VarKind, Reg),
134  MovQQ(OpQ, OpQ),
135  MovRbIb(Reg, u8),
136  MovRbMb(Reg, VarKind),
137  MovRdId(Reg, u32),
138  NegR(Reg),
139  NotRb(Reg),
140  OrRbRb(Reg, Reg),
141  Pop(Reg),
142  Push(Reg),
143  Quad(usize, u64),
144  Ret,
145  Shl1R(Reg),
146  StringZ(usize, String),
147  SubRId(Reg, u32),
148  SubRR(Reg, Reg),
149  TestRR(Reg, Reg),
150  TestRbRb(Reg, Reg),
151  TestRdRd(Reg, Reg),
152  XorRR(Reg, Reg),
153  XorRbRb(Reg, Reg),
154}
155#[derive(Debug, Clone, Copy, PartialEq, Eq)]
156enum OpQ {
157  Args(usize),
158  Iq(u64),
159  Mq(VarKind),
160  Rq(Reg),
161}
162/*
163#[derive(Clone, Copy, PartialEq, Eq)]
164enum OpD {
165  Id(u32),
166  Md(VarKind),
167  Rd(Reg),
168}
169#[derive(Clone, Copy, PartialEq, Eq)]
170enum OpW {
171  Iw(u16),
172  Mw(VarKind),
173  Rw(Reg),
174}
175#[derive(Clone, Copy, PartialEq, Eq)]
176enum OpB {
177  Ib(u8),
178  Mb(VarKind),
179  Rb(Reg),
180}
181*/
182#[derive(Copy, Clone)]
183enum Arity {
184  Any,
185  AtLeast(usize),
186  #[expect(dead_code)]
187  AtMost(usize),
188  Exactly(usize),
189  #[expect(dead_code)]
190  NoArgs,
191  #[expect(dead_code)]
192  Range(usize, usize),
193}
194#[derive(Clone)]
195struct AsmFunc {
196  id: usize,
197  params: Vec<Json>,
198  ret: Box<Json>,
199}
200#[derive(Clone)]
201enum Bind<T> {
202  Lit(T),
203  Var(Label),
204}
205struct Builtin {
206  arg_len: Arity,
207  func: JFunc,
208  scoped: bool,
209  skip_eval: bool,
210}
211type ErrOR<T> = Result<T, Box<dyn Error>>;
212struct FuncInfo {
213  args: IntoIter<WithPos<Json>>,
214  free_list: Vec<(u32, u32)>,
215  len: usize,
216  name: String,
217  pos: Position,
218}
219type JFunc = fn(&mut Jsonpiler, &mut FuncInfo, &mut ScopeInfo) -> ErrOR<Json>;
220#[derive(Clone, Default)]
221enum Json {
222  Array(Bind<Vec<WithPos<Json>>>),
223  Bool(Bind<bool>),
224  Float(Bind<f64>),
225  Function(AsmFunc),
226  Int(Bind<i64>),
227  #[default]
228  Null,
229  Object(Bind<Vec<(WithPos<String>, WithPos<Json>)>>),
230  String(Bind<String>),
231}
232#[doc(hidden)]
233pub struct Jsonpiler {
234  builtin: HashMap<String, Builtin>,
235  ctx: CompileContext,
236  globals: HashMap<String, Json>,
237  import_table: Dlls,
238  insts: Vec<Inst>,
239  parser: Parser,
240  sym_table: HashMap<&'static str, usize>,
241}
242#[derive(Clone, Copy)]
243struct Label {
244  kind: VarKind,
245  size: u32,
246}
247#[derive(Copy, Clone, Default)]
248struct Position {
249  line: usize,
250  offset: usize,
251  size: usize,
252}
253#[derive(Clone, Copy, PartialEq, Eq, Debug)]
254enum VarKind {
255  Global { id: usize },
256  Local { offset: u32 },
257  Tmp { offset: u32 },
258}
259#[derive(Clone, Default)]
260struct WithPos<T> {
261  pos: Position,
262  value: T,
263}