1pub mod functions;
9mod impl_compiler;
10mod impl_object;
11mod impl_parser;
12mod impl_value;
13use core::error::Error;
14use std::collections::{HashMap, HashSet};
15#[derive(Debug, Clone)]
17pub(crate) struct BuiltinFunc {
18 pub evaluated: bool,
20 pub func: JFunc,
22}
23type ErrOR<T> = Result<T, Box<dyn Error>>;
24#[derive(Debug, Clone, Default)]
26
27pub(crate) struct ErrorInfo {
28 line: usize,
30 pos: usize,
32}
33type JFunc = fn(&mut Jsonpiler, &Json, &[Json], &mut String) -> JFuncResult;
35type JFuncResult = ErrOR<JValue>;
37#[derive(Debug, Clone, Default)]
39pub(crate) struct JObject {
40 entries: Vec<(String, Json)>,
42 idx: HashMap<String, usize>,
44}
45type JResult = ErrOR<Json>;
47#[derive(Debug, Clone, Default)]
49pub(crate) enum JValue {
50 Function {
52 name: String,
54 params: Vec<Json>,
56 ret: Box<JValue>,
58 },
59 LArray(Vec<Json>),
61 LBool(bool),
63 LFloat(f64),
65 LInt(i64),
67 LObject(JObject),
69 LString(String),
71 #[default]
73 Null,
74 #[expect(dead_code, reason = "todo")]
76 VArray(String),
77 #[expect(dead_code, reason = "todo")]
79 VBool(String, usize),
80 #[expect(dead_code, reason = "todo")]
82 VFloat(String),
83 VInt(String),
85 #[expect(dead_code, reason = "todo")]
87 VObject(String),
88 VString(String),
90}
91#[derive(Debug, Clone, Default)]
93pub(crate) struct Json {
94 info: ErrorInfo,
96 value: JValue,
98}
99#[derive(Debug, Clone, Default)]
101pub struct Jsonpiler {
102 _globals: HashMap<String, JValue>,
104 f_table: HashMap<String, BuiltinFunc>,
106 include_flag: HashSet<String>,
108 info: ErrorInfo,
110 sect: Section,
112 seed: usize,
114 source: String,
116 vars: HashMap<String, JValue>,
118}
119impl Jsonpiler {
120 #[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#[derive(Debug, Clone, Default)]
167pub(crate) struct Section {
168 bss: String,
170 data: String,
172 text: String,
174}