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
use super::{Command, Status, State};
use Status::{Success, Failure};

macro_rules! command {
  ($it:ident($c:expr) => $code:expr) => (command!($it($c, _state, _status, _args) => $code););
  ($it:ident($c:expr, $r:ident: status) => $code:expr) => (command!($it($c, _state, $r, _args) => $code););
  ($it:ident($c:expr, $s:ident, $r:ident, $a:ident) => $code:expr) => (pub struct $it;
  impl Command for $it {
    fn get_name(&self) -> &'static str {
      $c
    }
    fn run(&self, $s: &mut State, $r: Status, $a: &[String]) -> Status {
      $code
    }
  });
}


command!(Nop("nop", status: status) => {
  status
});

command!(Return("return", status: status) => {
  -status
});

command!(Println("println", _state, _status, args) => {
  use std::io;
  use std::io::Write;
  match writeln!(io::stdout(), "{}", args.join(" ")) {
    Ok(_) => Success,
    Err(_) => Failure
  }
});

command!(Load("load", state, _status, _args) => {
  // TODO add better API
  state.get_store_load(|sl| sl.pop().unwrap_or(Failure))
});

command!(Store("store", state, status, _args) => {
  // TODO add better API
  state.get_store_load(|sl| sl.push(status));
  status
});

command!(Loop("loop", state, status, _args) => {
  let mut newstatus = status;
  while state.get_op(|op| op.trigger()[*newstatus]) {
    let pos = state.get_pos();
    newstatus = match state.run(pos+1) {
      x @ Status::ReturnSuccess | x @ Status::ReturnFailure => return x,
      x @ Success | x @ Failure => x,
    };
  };
  newstatus
});

command!(Exec("exec", _state, _status, args) => {
  use std::process::Command;
  let cmd = args.join(" ");
  if cfg!(windows) {
    Command::new("cmd.exe").arg("/c").arg(cmd).status()
  } else {
    Command::new("/bin/sh").arg("-c").arg(cmd).status()
  }.map(|x| Status::from(x.success())).unwrap_or(Failure)
});