jsonpiler/
lib.rs

1//! (main.rs)
2//! ```should_panic
3//! use jsonpiler::functions::run;
4//! fn main() -> ! {
5//!  run()
6//!}
7//! ```
8pub mod functions;
9mod impl_compiler;
10mod impl_object;
11mod impl_parser;
12mod impl_value;
13use core::error::Error;
14use std::collections::{HashMap, HashSet};
15/// Built-in function.
16#[derive(Debug, Clone)]
17pub(crate) struct BuiltinFunc {
18  /// Should arguments already be evaluated.
19  pub evaluated: bool,
20  /// Pointer of function.
21  pub func: JFunc,
22}
23type ErrOR<T> = Result<T, Box<dyn Error>>;
24/// line and pos in source code.
25#[derive(Debug, Clone, Default)]
26
27pub(crate) struct ErrorInfo {
28  /// Line number of the part being parsed.
29  line: usize,
30  /// Location of the part being parsed.
31  pos: usize,
32}
33/// Built-in function types.
34type JFunc = fn(&mut Jsonpiler, &Json, &[Json], &mut String) -> JFuncResult;
35/// Contain `JValue` or `Box<dyn Error>`.
36type JFuncResult = ErrOR<JValue>;
37/// Represents a JSON object with key-value pairs.
38#[derive(Debug, Clone, Default)]
39pub(crate) struct JObject {
40  /// Stores the key-value pairs in insertion order.
41  entries: Vec<(String, Json)>,
42  /// Maps keys to their index in the entries vector for quick lookup.
43  idx: HashMap<String, usize>,
44}
45/// Contain `Json` or `Box<dyn Error>`.
46type JResult = ErrOR<Json>;
47/// Type and value information.
48#[derive(Debug, Clone, Default)]
49pub(crate) enum JValue {
50  /// Function.
51  Function {
52    /// Name of function.
53    name: String,
54    /// Parameters of function.
55    params: Vec<Json>,
56    /// Return type of function.
57    ret: Box<JValue>,
58  },
59  /// Array.
60  LArray(Vec<Json>),
61  /// Bool.
62  LBool(bool),
63  /// Float.
64  LFloat(f64),
65  /// Integer.
66  LInt(i64),
67  /// Object.
68  LObject(JObject),
69  /// String.
70  LString(String),
71  /// Null.
72  #[default]
73  Null,
74  /// Array variable.
75  #[expect(dead_code, reason = "todo")]
76  VArray(String),
77  /// Bool variable.
78  #[expect(dead_code, reason = "todo")]
79  VBool(String, usize),
80  /// Float variable.
81  #[expect(dead_code, reason = "todo")]
82  VFloat(String),
83  /// Integer variable.
84  VInt(String),
85  /// Object variable.
86  #[expect(dead_code, reason = "todo")]
87  VObject(String),
88  /// String variable.
89  VString(String),
90}
91/// Json object.
92#[derive(Debug, Clone, Default)]
93pub(crate) struct Json {
94  /// Line number of objects in the source code.
95  info: ErrorInfo,
96  /// Type and value information.
97  value: JValue,
98}
99/// Parser and compiler.
100#[derive(Debug, Clone, Default)]
101pub struct Jsonpiler {
102  /// Global variables (now on Unused).
103  _globals: HashMap<String, JValue>,
104  /// Built-in function table.
105  f_table: HashMap<String, BuiltinFunc>,
106  /// Flag to avoid including the same file twice.
107  include_flag: HashSet<String>,
108  /// Information to be used during parsing.
109  info: ErrorInfo,
110  /// Section of the assembly.
111  sect: Section,
112  /// Seed to generate names.
113  seed: usize,
114  /// Source code.
115  source: String,
116  /// Variable table.
117  vars: HashMap<String, JValue>,
118}
119impl Jsonpiler {
120  /// Format error.
121  #[must_use]
122  pub(crate) fn fmt_err(&self, err: &str, info: &ErrorInfo) -> String {
123    const MSG1: &str = "\nError occurred on line: ";
124    const MSG2: &str = "\nError position:\n";
125    if self.source.is_empty() {
126      return format!("{err}{MSG1}{}{MSG2}Error: Empty input", info.line);
127    }
128    let len = self.source.len();
129    let idx = info.pos.min(len.saturating_sub(1));
130    let start = if idx == 0 {
131      0
132    } else {
133      let Some(left) = self.source.get(..idx) else {
134        return format!("{err}{MSG1}{}{MSG2}Error: Failed to get substring", info.line);
135      };
136      match left.rfind('\n') {
137        None => 0,
138        Some(start_pos) => {
139          let Some(res) = start_pos.checked_add(1) else {
140            return format!("{err}{MSG1}{}{MSG2}Error: Overflow", info.line);
141          };
142          res
143        }
144      }
145    };
146    let Some(right) = self.source.get(idx..) else {
147      return format!("{err}{MSG1}{}{MSG2}Error: Failed to get substring", info.line);
148    };
149    let end = match right.find('\n') {
150      None => len,
151      Some(end_pos) => {
152        let Some(res) = idx.checked_add(end_pos) else {
153          return format!("{err}{MSG1}{}{MSG2}Error: Overflow", info.line);
154        };
155        res
156      }
157    };
158    let ws = " ".repeat(idx.saturating_sub(start));
159    let Some(result) = self.source.get(start..end) else {
160      return format!("{err}{MSG1}{}{MSG2}Error: Failed to get substring", info.line);
161    };
162    format!("{err}{MSG1}{}{MSG2}{result}\n{ws}^", info.line)
163  }
164}
165/// Section of the assembly.
166#[derive(Debug, Clone, Default)]
167pub(crate) struct Section {
168  /// Buffer to store the contents of the bss section of the assembly.
169  bss: String,
170  /// Buffer to store the contents of the data section of the assembly.
171  data: String,
172  /// Buffer to store the contents of the text section of the assembly.
173  text: String,
174}