1#![deny(missing_docs)]
25#![deny(rustdoc::invalid_rust_codeblocks)]
26
27use std::iter::zip;
28
29use lalrpop_util::{lalrpop_mod, ParseError};
30
31use prelude::*;
32use utils::ast::Expr;
33use utils::orion::{setup_functions, setup_variables, Metadata, Variables};
34
35use crate::utils::ast::{CompCode, OpCode, ReassignCode, Type};
36use crate::utils::orion::{CustomFunctions, Function, Variable};
37
38pub use color_eyre::install as setup_error_hooks;
39pub use utils::jit::{decode, encode};
40
41mod error;
42mod prelude;
43mod types;
44mod utils;
45
46pub use utils::idle::IdleRunner;
47
48lalrpop_mod!(
49 #[allow(missing_docs)]
50 #[allow(clippy::type_complexity)]
51 lrparser
52);
53
54lalrpop_mod!(
55 #[allow(missing_docs)]
56 #[allow(clippy::type_complexity)]
57 lrbraces
58);
59
60pub fn run_contents<S: ToString>(contents: S, use_braces: bool) -> Result<()> {
76 let contents = contents.to_string();
77
78 if contents.is_empty() {
79 return Ok(());
80 }
81
82 let mut metadata = Metadata {
83 functions: setup_functions(),
84 ..Default::default()
85 };
86
87 let mut variables = setup_variables();
88
89 let mut custom_functions = CustomFunctions::new();
90
91 let lib = f!("{}\n", include_str!("./lib/std.or"));
92
93 let result = lrparser::StatementsParser::new()
94 .parse(lib.leak())
95 .with_context(|| "Error in standard file.")?;
96
97 for expr in result {
98 run(expr, &metadata, &mut variables, &mut custom_functions).with_context(|| {
99 "Error in \
100 standard file."
101 })?;
102 }
103
104 let result = if use_braces {
105 lrbraces::StatementsParser::new().parse(contents.clone().leak())
106 } else {
107 lrparser::StatementsParser::new().parse(contents.clone().leak())
108 };
109
110 let result = if result.is_err() {
111 Err(match result.err().unwrap() {
112 ParseError::InvalidToken { location } => {
113 let loc = utils::location::location(location, contents);
114 ParseError::InvalidToken { location: loc }
115 }
116
117 ParseError::UnrecognizedEof { location, expected } => {
118 let loc = utils::location::location(location, contents);
119 ParseError::UnrecognizedEof {
120 location: loc,
121 expected,
122 }
123 }
124
125 ParseError::UnrecognizedToken { token, expected } => {
126 let (loc1, token, loc2) = token;
127 let loc1 = utils::location::location(loc1, &contents);
128 let loc2 = utils::location::location(loc2, contents);
129
130 ParseError::UnrecognizedToken {
131 token: (loc1, token, loc2),
132 expected,
133 }
134 }
135
136 ParseError::ExtraToken { token } => {
137 let (loc1, token, loc2) = token;
138 let loc1 = utils::location::location(loc1, &contents);
139 let loc2 = utils::location::location(loc2, contents);
140
141 ParseError::ExtraToken {
142 token: (loc1, token, loc2),
143 }
144 }
145
146 ParseError::User { error } => ParseError::User { error }, })
148 } else {
149 result.map_err(|_| ParseError::User {
150 error: "impossible",
151 })
152 };
153
154 let ast: Vec<Option<Expr>> = result.unwrap_or_else(|e| {
155 #[cfg(debug_assertions)]
156 {
157 panic!("\x1b[31m{e}\x1b[0m");
158 }
159 #[cfg(not(debug_assertions))]
160 {
161 eprintln!("\x1b[31m{e}\x1b[0m");
162 std::process::exit(1)
163 }
164 });
165
166 for (count, expr) in ast.iter().enumerate() {
167 metadata.line = count + 1;
168
169 run(
170 expr.to_owned(),
171 &metadata,
172 &mut variables,
173 &mut custom_functions,
174 )?;
175 }
176
177 Ok(())
178}
179
180pub fn run_ast(ast: Vec<Option<Expr>>) -> Result<()> {
182 let mut metadata = Metadata {
183 functions: setup_functions(),
184 ..Default::default()
185 };
186
187 let mut variables = setup_variables();
188
189 let mut custom_functions = CustomFunctions::new();
190
191 let lib = f!("{}\n", include_str!("./lib/std.or"));
192
193 let result = lrparser::StatementsParser::new()
194 .parse(lib.leak())
195 .with_context(|| "Error in standard file.")?;
196
197 for expr in result {
198 run(expr, &metadata, &mut variables, &mut custom_functions).with_context(|| {
199 "Error in \
200 standard file."
201 })?;
202 }
203
204 for (count, expr) in ast.iter().enumerate() {
205 metadata.line = count + 1;
206
207 run(
208 expr.to_owned(),
209 &metadata,
210 &mut variables,
211 &mut custom_functions,
212 )?;
213 }
214
215 Ok(())
216}
217
218fn run(
219 ast: Option<Expr>,
220 meta: &Metadata,
221 variables: &mut Variables,
222 custom_functions: &mut CustomFunctions,
223) -> Result<Option<Expr>> {
224 let functions = &meta.functions;
225 let line = meta.line;
226
227 if ast.is_none() {
228 return Ok(None);
229 }
230
231 match ast.unwrap() {
232 Expr::FuncCall(func, args) => {
233 if custom_functions.contains_key(&func) {
234 let customs = custom_functions.clone();
235 let (f_args, body) = customs.get(&func).unwrap();
236
237 if args.len() != f_args.len() {
238 bail!(Errors::LineError {
239 line,
240 msg: f!(
241 "Invalid number of arguments! Expected: {}; Found: {}",
242 f_args.len(),
243 args.len()
244 )
245 })
246 }
247
248 let mut overrides = vec![];
249 let vars = variables.clone();
250
251 for (arg, f_arg) in zip(args, f_args) {
252 let arg = arg.eval(meta, variables, custom_functions)?;
253
254 if variables.contains_key(f_arg) {
255 overrides.push(vars.get_key_value(f_arg).unwrap());
256 }
257
258 variables.insert(f_arg.to_owned(), variable_expr_eq(arg, meta.scope + 1));
259 }
260
261 let res = body.to_owned().eval(meta, variables, custom_functions)?;
262
263 for (key, over) in overrides {
264 variables.insert(key.to_owned(), over.to_owned());
265 }
266
267 return Ok(res);
268 }
269
270 let func: &Function =
271 functions
272 .get(func.as_str())
273 .with_context(|| Errors::LineError {
274 line,
275 msg: f!("Could not find function `{func}`"),
276 })?;
277
278 Ok(match func {
279 Function::Void(f) => {
280 f(args, meta, variables, custom_functions)
281 .with_context(|| f!("Error on line {}", meta.line))?;
282 return Ok(None);
283 }
284 Function::String(f) => Some(Expr::String(
285 f(args, meta, variables, custom_functions)
286 .with_context(|| f!("Error on line {}", meta.line))?
287 .to_string(),
288 )),
289 })
290 }
291
292 Expr::Let(name, value) => {
293 let value = value.eval(meta, variables, custom_functions)?;
294
295 if variables.contains_key(&name) {
296 bail!(Errors::LineError {
297 line,
298 msg: f!("Variable already exists. \
299 Maybe you meant to overwrite it? `{name} = value`"),
300 })
301 }
302
303 variables.insert(name, variable_expr_eq(value, meta.scope));
304
305 Ok(None)
306 }
307 Expr::TypeLet(ty, name, value) => {
308 let value = value.eval(meta, variables, custom_functions)?;
309
310 if let Some(ref value) = value {
311 check_type(value, &ty, line)?;
312 } else {
313 bail!(Errors::LineError {
314 line,
315 msg: "Type does not match declaration.".to_string(),
316 })
317 }
318
319 if variables.contains_key(&name) {
320 bail!(Errors::LineError {
321 line,
322 msg: f!("Variable already exists. \
323 Maybe you meant to overwrite it? `{name} = value`"),
324 })
325 }
326
327 variables.insert(name, variable_expr_eq(value, meta.scope));
328
329 Ok(None)
330 }
331 Expr::Ident(ident) => {
332 let var = variables.get(&ident).with_context(|| Errors::LineError {
333 line,
334 msg: f!("Could not find variable `{ident}`"),
335 })?;
336
337 let var = match var {
338 Variable::String(s, _) => Some(Expr::String(s.to_string())),
339 Variable::Int8(n, _) => Some(Expr::Int8(*n)),
340 Variable::Int16(n, _) => Some(Expr::Int16(*n)),
341 Variable::Int32(n, _) => Some(Expr::Int32(*n)),
342 Variable::Int64(n, _) => Some(Expr::Int64(*n)),
343 Variable::Uint8(n, _) => Some(Expr::Uint8(*n)),
344 Variable::Uint16(n, _) => Some(Expr::Uint16(*n)),
345 Variable::Uint32(n, _) => Some(Expr::Uint32(*n)),
346 Variable::Uint64(n, _) => Some(Expr::Uint64(*n)),
347 Variable::None(_) => None,
348 Variable::Array(array, _) => Some(Expr::Array(array.to_vec())),
349 Variable::Char(c, _) => Some(Expr::Char(*c)),
350 Variable::Float(f, _) => Some(Expr::Float(*f)),
351 };
352
353 Ok(var)
354 }
355 Expr::Op(a, opcode, b) => {
356 let a = a.eval(meta, variables, custom_functions)?;
357 let b = b.eval(meta, variables, custom_functions)?;
358
359 match opcode {
360 OpCode::Add => W(a) + W(b),
361 OpCode::Subtract => W(a) - W(b),
362 OpCode::Multiply => W(a) * W(b),
363 OpCode::Divide => W(a) / W(b),
364 }
365 }
366 Expr::Compare(a, opcode, b) => {
367 let a = W(a.eval(meta, variables, custom_functions)?);
368 let b = W(b.eval(meta, variables, custom_functions)?);
369
370 Ok(Some(match opcode {
371 CompCode::Greater => Expr::Bool(a > b),
372 CompCode::Lesser => Expr::Bool(a < b),
373 CompCode::Equals => Expr::Bool(a == b),
374 CompCode::NotEquals => Expr::Bool(a != b),
375 CompCode::GreaterEquals => Expr::Bool(a >= b),
376 CompCode::LesserEquals => Expr::Bool(a <= b),
377 }))
378 }
379 Expr::Scope(lines) => {
380 let mut value = None;
381 let meta = Metadata {
382 scope: meta.scope + 1,
383 ..meta.to_owned()
384 };
385
386 for line in lines {
387 value = run(line, &meta, variables, custom_functions)?;
388 }
389
390 garbage(variables, &(meta.scope - 1));
391
392 Ok(value)
393 }
394 Expr::If(condition, scope) => {
395 let condition = run(Some(*condition), meta, variables, custom_functions)?;
396
397 let value = if match condition {
398 Some(Expr::Bool(b)) => b,
399 _ => bail!("Invalid type for conditioning."),
400 } {
401 run(Some(*scope), meta, variables, custom_functions)?
402 } else {
403 None
404 };
405
406 Ok(value)
407 }
408 Expr::IfElse(condition, if_code, else_code) => {
409 let condition = run(Some(*condition), meta, variables, custom_functions)?;
410
411 let value = if match condition {
412 Some(Expr::Bool(b)) => b,
413 _ => bail!("Invalid type for conditioning."),
414 } {
415 run(Some(*if_code), meta, variables, custom_functions)?
416 } else {
417 run(Some(*else_code), meta, variables, custom_functions)?
418 };
419
420 Ok(value)
421 }
422 Expr::Property(_, _) => todo!(),
423 Expr::Method(expr, method, args) => {
424 let expr = expr.eval(meta, variables, custom_functions)?;
425 let methodical = match expr {
426 Some(expr) => expr,
427 None => bail!(Errors::LineError {
428 line,
429 msg: "No methods belong to type `None`.".to_string()
430 }),
431 }
432 .to_methodical(meta, variables, custom_functions)
433 .with_context(|| Errors::GeneralError(f!("Error on line {line}")))?;
434
435 let res = methodical
436 .0
437 .call(&method, args)
438 .with_context(|| Errors::LineError {
439 line,
440 msg: f!("Failed to run method `{method}`"),
441 })?;
442
443 Ok(res)
444 }
445 Expr::For(ident, iterable, code) => {
446 match iterable.eval(meta, variables, custom_functions)? {
447 Some(Expr::String(_)) => {
448 bail!(Errors::LineError {
449 line,
450 msg: "String is not an iterable. Maybe you meant to iterate on its characters? \
451 `s.chars()`".to_string()
452 })
453 }
454 Some(Expr::Array(array)) => {
455 for expr in array {
456 let variable = variable_expr_eq(
457 expr.eval(meta, variables, custom_functions)?,
458 meta.scope,
459 );
460
461 variables.insert(ident.to_string(), variable);
462
463 code.clone().eval(meta, variables, custom_functions)?;
464 }
465
466 variables.remove(&ident);
467 }
468 _ => bail!("for: Type is not an iterable."),
469 }
470
471 Ok(None)
472 }
473 Expr::ForComplex(initializer, condition, eoi, code) => {
474 initializer.eval(meta, variables, custom_functions)?;
475
476 loop {
477 let condition_ = condition.clone().eval(meta, variables, custom_functions)?;
478
479 match condition_ {
480 Some(Expr::Bool(b)) => {
481 if !b {
482 break;
483 }
484 }
485 _ => bail!(Errors::LineError {
486 line,
487 msg: "Expected boolean".to_string()
488 }),
489 }
490
491 code.clone().eval(meta, variables, custom_functions)?;
492
493 eoi.clone().eval(meta, variables, custom_functions)?;
494 }
495
496 Ok(None)
497 }
498 Expr::Reassign(var, operation, expr) => {
499 let val = expr.clone().eval(meta, variables, custom_functions)?;
500
501 match variables.get_mut(&var) {
502 Some(v) => {
503 let (var_expr, scope) = expr_variable_eq(v);
504 *v = match operation {
505 ReassignCode::Re => variable_expr_eq(val, scope),
506 ReassignCode::Plus => {
507 let res = (W(var_expr) + W(val)).with_context(|| {
508 Errors::GeneralError(f!("Error on line {line}"))
509 })?;
510
511 variable_expr_eq(res, scope)
512 }
513 ReassignCode::Minus => {
514 let res = (W(var_expr) - W(val)).with_context(|| {
515 Errors::GeneralError(f!("Error on line {line}"))
516 })?;
517
518 variable_expr_eq(res, scope)
519 }
520 ReassignCode::Multiply => {
521 let res = (W(var_expr) * W(val)).with_context(|| {
522 Errors::GeneralError(f!("Error on line {line}"))
523 })?;
524
525 variable_expr_eq(res, scope)
526 }
527 ReassignCode::Divide => {
528 let res = (W(var_expr) / W(val)).with_context(|| {
529 Errors::GeneralError(f!("Error on line {line}"))
530 })?;
531
532 variable_expr_eq(res, scope)
533 }
534 };
535 }
536 None => bail!(f!("Variable {var} not found")),
537 }
538
539 Ok(None)
540 }
541 Expr::Slice(e, slice) => {
542 let slice = slice.eval(meta, variables, custom_functions)?;
543 let slice: usize = match slice {
544 Some(slice) => match slice {
545 Expr::Int8(n) => n.try_into()?,
546 Expr::Int16(n) => n.try_into()?,
547 Expr::Int32(n) => n.try_into()?,
548 Expr::Int64(n) => n.try_into()?,
549 Expr::Uint8(n) => n.into(),
550 Expr::Uint16(n) => n.into(),
551 Expr::Uint32(n) => n.try_into()?,
552 Expr::Uint64(n) => n.try_into()?,
553 _ => bail!(Errors::LineError {
554 line,
555 msg: "Cannot use this type as slicer.".to_string()
556 }),
557 },
558 None => bail!(Errors::LineError {
559 line,
560 msg: "Cannot use None as slicer.".to_string()
561 }),
562 };
563
564 Ok(match e.eval(meta, variables, custom_functions)? {
565 Some(expr) => match expr {
566 Expr::String(s) => Some(Expr::Char(
567 s.get(slice..slice + 1)
568 .with_context(|| Errors::LineError {
569 line,
570 msg: f!("Could not slice string at index {slice}"),
571 })?
572 .chars()
573 .next()
574 .with_context(|| Errors::LineError {
575 line,
576 msg: f!("Could not slice string at index {slice}"),
577 })?,
578 )),
579 Expr::Array(array) => {
580 let item = array.get(slice).with_context(|| Errors::LineError {
581 line,
582 msg: f!("Could not slice array at index {slice}"),
583 })?;
584
585 item.to_owned().eval(meta, variables, custom_functions)?
586 }
587 _ => bail!(Errors::LineError {
588 line,
589 msg: "Cannot slice this object.".to_string()
590 }),
591 },
592 None => bail!(Errors::LineError {
593 line,
594 msg: "Cannot slice a None object.".to_string()
595 }),
596 })
597 }
598 Expr::Func(name, args, body) => {
599 if name.starts_with('$') {
600 bail!(Errors::LineError {
601 line,
602 msg: f!("Cannot create inner functions! `{name}`")
603 })
604 }
605
606 custom_functions.insert(name.to_string(), (args, body));
607
608 Ok(None)
609 }
610 e => Ok(Some(e)),
611 }
612}
613
614fn garbage(variables: &mut Variables, scope_: &usize) {
615 variables.retain(|_, v| match v {
616 Variable::String(_, scope) => scope_ >= scope,
617 Variable::Int8(_, scope) => scope_ >= scope,
618 Variable::Int16(_, scope) => scope_ >= scope,
619 Variable::Int32(_, scope) => scope_ >= scope,
620 Variable::Int64(_, scope) => scope_ >= scope,
621 Variable::Uint8(_, scope) => scope_ >= scope,
622 Variable::Uint16(_, scope) => scope_ >= scope,
623 Variable::Uint32(_, scope) => scope_ >= scope,
624 Variable::Uint64(_, scope) => scope_ >= scope,
625 Variable::Float(_, scope) => scope_ >= scope,
626 Variable::None(scope) => scope_ >= scope,
627 Variable::Array(_, scope) => scope_ >= scope,
628 Variable::Char(_, scope) => scope_ >= scope,
629 });
630}
631
632fn variable_expr_eq(expr: Option<Expr>, scope: usize) -> Variable {
633 let expr = if let Some(expr) = expr {
634 expr
635 } else {
636 return Variable::None(scope);
637 };
638
639 match expr {
640 Expr::Int8(n) => Variable::Int8(n, scope),
641 Expr::Int16(n) => Variable::Int16(n, scope),
642 Expr::Int32(n) => Variable::Int32(n, scope),
643 Expr::Int64(n) => Variable::Int64(n, scope),
644 Expr::Uint8(n) => Variable::Uint8(n, scope),
645 Expr::Uint16(n) => Variable::Uint16(n, scope),
646 Expr::Uint32(n) => Variable::Uint32(n, scope),
647 Expr::Uint64(n) => Variable::Uint64(n, scope),
648 Expr::String(s) => Variable::String(s, scope),
649 Expr::Array(array) => Variable::Array(array, scope),
650 Expr::Char(c) => Variable::Char(c, scope),
651 Expr::Float(f) => Variable::Float(f, scope),
652 _ => unimplemented!(),
653 }
654}
655
656fn expr_variable_eq(var: &Variable) -> (Option<Expr>, usize) {
657 match var {
658 Variable::Int8(n, scope) => (Some(Expr::Int8(*n)), *scope),
659 Variable::Int16(n, scope) => (Some(Expr::Int16(*n)), *scope),
660 Variable::Int32(n, scope) => (Some(Expr::Int32(*n)), *scope),
661 Variable::Int64(n, scope) => (Some(Expr::Int64(*n)), *scope),
662 Variable::Uint8(n, scope) => (Some(Expr::Uint8(*n)), *scope),
663 Variable::Uint16(n, scope) => (Some(Expr::Uint16(*n)), *scope),
664 Variable::Uint32(n, scope) => (Some(Expr::Uint32(*n)), *scope),
665 Variable::Uint64(n, scope) => (Some(Expr::Uint64(*n)), *scope),
666 Variable::String(s, scope) => (Some(Expr::String(s.to_string())), *scope),
667 Variable::Array(array, scope) => (Some(Expr::Array(array.to_vec())), *scope),
668 Variable::Char(c, scope) => (Some(Expr::Char(*c)), *scope),
669 Variable::Float(f, scope) => (Some(Expr::Float(*f)), *scope),
670 _ => unimplemented!(),
671 }
672}
673
674fn check_type(expr: &Expr, ty: &Type, line: usize) -> Result<()> {
675 match (expr, ty) {
676 (Expr::Int8(_), Type::Int8) | (Expr::Int8(_), Type::DynInt) => {}
677 (Expr::Int16(_), Type::Int16) | (Expr::Int16(_), Type::DynInt) => {}
678 (Expr::Int32(_), Type::Int32) | (Expr::Int32(_), Type::DynInt) => {}
679 (Expr::Int64(_), Type::Int64) | (Expr::Int64(_), Type::DynInt) => {}
680 (Expr::Uint8(_), Type::Uint8) | (Expr::Uint8(_), Type::DynInt) => {}
681 (Expr::Uint16(_), Type::Uint16) | (Expr::Uint16(_), Type::DynInt) => {}
682 (Expr::Uint32(_), Type::Uint32) | (Expr::Uint32(_), Type::DynInt) => {}
683 (Expr::Uint64(_), Type::Uint64) | (Expr::Uint64(_), Type::DynInt) => {}
684 (Expr::String(_), Type::String) => {}
685 (Expr::Float(_), Type::Float) => {}
686 (Expr::Bool(_), Type::Bool) => {}
687 (Expr::Char(_), Type::Char) => {}
688 (Expr::Array(array), Type::Array(ty)) => {
689 if let Some(ty) = &**ty {
690 for expr in array {
691 check_type(expr, ty, line)?;
692 }
693 }
694 }
695 (_, _) => bail!(Errors::LineError {
696 line,
697 msg: "Type does not match declaration".to_string()
698 }),
699 }
700
701 Ok(())
702}