interpreter/
ipreter.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
use crate::{
  error, runtime::_root_syntax::insert_into_application, types::{call_runtime_val, mkbuf, set_runtime_val, MethodData, Options}, Application
};

pub fn interpret(file: &str, mut app: &mut Application) {
  let file_name = if file == ":entry" { app.entry } else { file };

  let file = app.code.get(file).unwrap();

  let file = file.replace("\r", "");
  file.split("\n").enumerate().for_each(|(line, piece)| {
    if piece.starts_with("!") && app.next_marker {
      if piece == "!end" {
        app.next_marker = false;
      } else {
        let piece = piece.replacen("!", "", 1);
        tok_parse(format!("{}:{}", &file_name, line + 1), &piece, &mut app);
      }
    } else if !piece.starts_with("#") {
      tok_parse(format!("{}:{}", &file_name, line + 1), piece, &mut app);
    }
  });
}

fn tok_parse(file: String, piece: &str, app: &mut Application) {
  let mut tokens: Vec<String> = piece.split(" ").map(|x| x.to_string()).collect();

  let mut caller = tokens[0].as_str();
  let mut val_type = "<-none->";

  let mut to_set = String::new();

  if tokens[0].ends_with(":") && (tokens[0].starts_with("*") || tokens[0].starts_with("$")) {
    if tokens[0].starts_with("*") {
      val_type = "*";
    } else {
      val_type = "$";
    }

    to_set = tokens.remove(0);
    to_set = to_set.split_at(to_set.len() - 1).0.into();

    caller = tokens[0].as_str();
  }

  let mut opt = Options::new();

  if caller.starts_with("*") {
    insert_into_application(app as *mut _ as _, &tokens);
  } else if caller.starts_with("@") {
    if val_type == "$" {
      let _ = app.heap.set(to_set, mkbuf(&caller, &file));
    }
  } else if caller.starts_with("$") {
    match call_runtime_val(caller, &tokens, &mut app.heap, &file, &mut opt) {
      None => if &caller != &"" {
        error(&format!("Unexpected `{}`", &caller), &file);
      },
      Some(v) => {
        opt.pre = v.to_string();
        if opt.marker {
          app.next_marker = true;
        }

        let runt = opt.rem_r_runtime();

        if val_type == "*" {
          let _ = app.heap.set_ptr(to_set, opt.r_ptr_target, opt.r_ptr);
        } else if val_type == "$" && opt.r_val.is_some() {
          let _ = app.heap.set(to_set, opt.r_val.unwrap());
        } else if val_type == "$" && runt.is_some() {
          let _ = set_runtime_val(to_set, v, runt.unwrap());
        }
      }
    }
  } else {
    match app.pkg.inner.get_mut(caller) {
      Some(MethodData::Static(p, v)) => {
        v(&tokens, &mut app.heap, &file, &mut opt);

        let pkg: *const str = *p as *const _;
        let pkg = unsafe { &*pkg };

        opt.pre = pkg.to_string();

        if opt.marker {
          app.next_marker = true;
        }

        let runt = opt.rem_r_runtime();

        if val_type == "*" {
          let _ = app.heap.set_ptr(to_set, opt.r_ptr_target, opt.r_ptr);
        } else if val_type == "$" && opt.r_val.is_some() {
          let _ = app.heap.set(to_set, opt.r_val.unwrap());
        } else if val_type == "$" && runt.is_some() {
          let _ = set_runtime_val(to_set, pkg, runt.unwrap());
        }
      }
      _ => {
        match app.modules.get_mut(caller) {
          _ => if &caller != &"" {
            error(&format!("Unexpected `{}`", &caller), &file);
          }
        }
      }
    }
  }
}