~fd/cane-lang

88767780612ead47eb8c61da4b3d1779a45ecb37 — Ersei Saggi 10 months ago 4d96d41
stdin, forever loops
7 files changed, 197 insertions(+), 51 deletions(-)

M README.md
M cane-lang/src/cli.rs
M cane-lang/src/lib.rs
M cane-wasm/index.html
M cane-wasm/src/lib.rs
M demos/loop.cn
M shell.nix
M README.md => README.md +3 -2
@@ 275,11 275,12 @@ This has the interesting property making any program with invalid tokens valid b

### Loops

Loops are similar to control flow. It will execute the string `N` times.
Loops are similar to control flow. It will execute the string `N` (or infinity) times.

| Name | Args | Notes |
| ---- | ---- | ----- |
| `repeat` | `String, Number` | Executes the string `N` times. `N` must be a non-negative integer. |
| `forever` | `String` | Executes the string forever. |

Example:



@@ 288,7 289,7 @@ Example:

(
	[
		(`hi\n' print)
		(`hi' println)
	]
	100 repeat
)

M cane-lang/src/cli.rs => cane-lang/src/cli.rs +3 -2
@@ 1,4 1,4 @@
use cane::stdtypes::{Data,Types};
use cane::stdtypes::{Data, Types};

use cane::Interpreter;
use std::collections::HashMap;


@@ 16,6 16,7 @@ fn main() -> std::io::Result<Data> {
    let f = File::open(args.get(1).unwrap())?;
    let reader = BufReader::new(f);
    let mut stdout = std::io::stdout();
    let mut stdin = std::io::stdin().lock();
    let mut variables = HashMap::new();
    let mut args_data = Data::new(Types::LIST);
    for arg in args {


@@ 23,6 24,6 @@ fn main() -> std::io::Result<Data> {
        data.set_string(arg);
        args_data.get_list().push(data);
    }
    let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args_data);
    let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args_data);
    runner.execute()
}

M cane-lang/src/lib.rs => cane-lang/src/lib.rs +161 -43
@@ 72,6 72,7 @@ where
    call_stack: Vec<Call>,
    variables: &'a mut HashMap<String, Data>,
    stdout: &'a mut dyn io::Write,
    stdin: &'a mut dyn io::BufRead,
    args: Data,
}



@@ 83,6 84,7 @@ where
    pub fn new(
        reader: BufReader<R>,
        stdout: &'a mut dyn io::Write,
        stdin: &'a mut dyn io::BufRead,
        variables: &'a mut HashMap<String, Data>,
        args: Data,
    ) -> Interpreter<'a, R> {


@@ 91,6 93,7 @@ where
            call_stack: Vec::new(),
            variables,
            stdout,
            stdin,
            args,
        };
        intp.call_stack.push(Call::new(State::Wait));


@@ 283,6 286,7 @@ where
                                    let mut action_interp = Interpreter::new(
                                        reader,
                                        self.stdout,
                                        self.stdin,
                                        self.variables,
                                        self.args.clone(),
                                    );


@@ 311,6 315,46 @@ where
                                "flatten" => {
                                    self.call_stack.last_mut().unwrap().get_data().make_flat();
                                }
                                "forever" => {
                                    let data = self.call_stack.last_mut().unwrap().get_data();
                                    let executable = data.get_list().pop_back();
                                    if executable.is_none() {
                                        return Err(Error::new(
                                            ErrorKind::InvalidData,
                                            "Infinite loop data missing".to_string(),
                                        ));
                                    }
                                    let mut c = Cursor::new(Vec::new());
                                    c.write_all(executable.unwrap().get_string().as_bytes())
                                        .unwrap();
                                    let mut reader = BufReader::new(c);
                                    reader.rewind().unwrap();
                                    let mut repeat_interp = Interpreter::new(
                                        reader,
                                        self.stdout,
                                        self.stdin,
                                        self.variables,
                                        self.args.clone(),
                                    );
                                    loop {
                                        match repeat_interp.execute() {
                                            Ok(data) => {
                                                self.call_stack
                                                    .last_mut()
                                                    .unwrap()
                                                    .get_data()
                                                    .get_list()
                                                    .append(data);
                                            }
                                            Err(e) => return Err(e),
                                        }
                                        match repeat_interp.rewind() {
                                            Ok(..) => (),
                                            Err(e) => return Err(e),
                                        }
                                        repeat_interp.reset();
                                    }
                                }
                                "repeat" => {
                                    let data = self.call_stack.last_mut().unwrap().get_data();
                                    let mut count = data.get_list().pop_back();


@@ 348,6 392,7 @@ where
                                    let mut repeat_interp = Interpreter::new(
                                        reader,
                                        self.stdout,
                                        self.stdin,
                                        self.variables,
                                        self.args.clone(),
                                    );


@@ 515,6 560,13 @@ where
                                    )
                                    .unwrap();
                                }
                                "readln" => {
                                    let mut input = String::new();
                                    self.stdin.read_line(&mut input).unwrap();
                                    let mut data = Data::new(Types::STRING);
                                    data.set_string(input);
                                    self.call_stack.last_mut().unwrap().get_data().get_list().push(data);
                                }
                                "sub" => {
                                    let data = self.call_stack.last_mut().unwrap().get_data();
                                    let result_wrapped = data.get_list().pop_front();


@@ 766,6 818,7 @@ where
                                                let mut action_interp = Interpreter::new(
                                                    reader,
                                                    self.stdout,
                                                        self.stdin,
                                                    self.variables,
                                                    self.call_stack
                                                        .last_mut()


@@ 1022,6 1075,7 @@ mod tests {
    fn test_print_string() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut stdin = Cursor::new(Vec::new());
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);



@@ 1030,7 1084,7 @@ mod tests {
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

        let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args);
        let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args);
        runner.execute().unwrap();

        assert_eq!(stdout, b"hello, world!\n");


@@ 1040,6 1094,7 @@ mod tests {
    fn test_println_string() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut stdin = Cursor::new(Vec::new());
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);



@@ 1048,7 1103,7 @@ mod tests {
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

        let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args);
        let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args);
        runner.execute().unwrap();

        assert_eq!(stdout, b"hello, world!\n");


@@ 1058,6 1113,7 @@ mod tests {
    fn test_escape_string() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut stdin = Cursor::new(Vec::new());
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);



@@ 1066,7 1122,7 @@ mod tests {
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

        let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args);
        let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args);
        runner.execute().unwrap();

        assert_eq!(stdout, b"hello, world!\\'\n");


@@ 1076,6 1132,7 @@ mod tests {
    fn test_add_print_string() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut stdin = Cursor::new(Vec::new());
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);



@@ 1084,7 1141,7 @@ mod tests {
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

        let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args);
        let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args);
        runner.execute().unwrap();

        assert_eq!(stdout, b"hello, world!\n");


@@ 1094,6 1151,7 @@ mod tests {
    fn test_add_rational() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut stdin = Cursor::new(Vec::new());
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);



@@ 1102,7 1160,7 @@ mod tests {
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

        let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args);
        let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args);
        runner.execute().unwrap();

        assert_eq!(stdout, b"5/4");


@@ 1112,6 1170,7 @@ mod tests {
    fn test_no_unwrap() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut stdin = Cursor::new(Vec::new());
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);



@@ 1120,7 1179,7 @@ mod tests {
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

        let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args);
        let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args);
        runner.execute().unwrap();

        assert_eq!(stdout, b"5");


@@ 1130,6 1189,7 @@ mod tests {
    fn test_unwrap() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut stdin = Cursor::new(Vec::new());
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);



@@ 1138,7 1198,7 @@ mod tests {
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

        let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args);
        let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args);
        runner.execute().unwrap();

        assert_eq!(stdout, b"21");


@@ 1148,6 1208,7 @@ mod tests {
    fn test_variable() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut stdin = Cursor::new(Vec::new());
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);



@@ 1156,7 1217,7 @@ mod tests {
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

        let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args);
        let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args);
        runner.execute().unwrap();

        assert_eq!(stdout, b"4");


@@ 1166,6 1227,7 @@ mod tests {
    fn test_variable_overwrite() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut stdin = Cursor::new(Vec::new());
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);



@@ 1175,7 1237,7 @@ mod tests {
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

        let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args);
        let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args);
        runner.execute().unwrap();

        assert_eq!(stdout, b"41");


@@ 1185,6 1247,7 @@ mod tests {
    fn test_action() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut stdin = Cursor::new(Vec::new());
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);



@@ 1193,7 1256,7 @@ mod tests {
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

        let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args);
        let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args);
        runner.execute().unwrap();

        assert_eq!(stdout, b"4");


@@ 1203,6 1266,7 @@ mod tests {
    fn test_args() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut stdin = Cursor::new(Vec::new());
        let mut variables = HashMap::new();
        let mut args = Data::new(Types::LIST);
        let mut arg = Data::new(Types::STRING);


@@ 1214,7 1278,7 @@ mod tests {
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

        let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args);
        let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args);
        runner.execute().unwrap();

        assert_eq!(stdout, b"argument");


@@ 1224,6 1288,7 @@ mod tests {
    fn test_action_args() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut stdin = Cursor::new(Vec::new());
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);



@@ 1232,7 1297,7 @@ mod tests {
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

        let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args);
        let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args);
        runner.execute().unwrap();

        assert_eq!(stdout, b"10");


@@ 1242,6 1307,7 @@ mod tests {
    fn test_cast_str_to_num() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut stdin = Cursor::new(Vec::new());
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);



@@ 1250,7 1316,7 @@ mod tests {
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

        let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args);
        let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args);
        runner.execute().unwrap();

        assert_eq!(stdout, b"17/7");


@@ 1260,6 1326,7 @@ mod tests {
    fn test_cast_list_to_num() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut stdin = Cursor::new(Vec::new());
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);



@@ 1268,7 1335,7 @@ mod tests {
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

        let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args);
        let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args);
        runner.execute().unwrap();

        assert_eq!(stdout, b"4");


@@ 1278,6 1345,7 @@ mod tests {
    fn test_cast_str_to_list() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut stdin = Cursor::new(Vec::new());
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);



@@ 1286,7 1354,7 @@ mod tests {
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

        let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args);
        let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args);
        runner.execute().unwrap();

        assert_eq!(stdout, b"5");


@@ 1296,6 1364,7 @@ mod tests {
    fn test_cast_list_to_str() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut stdin = Cursor::new(Vec::new());
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);



@@ 1304,7 1373,7 @@ mod tests {
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

        let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args);
        let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args);
        runner.execute().unwrap();

        assert_eq!(stdout, b"abcd");


@@ 1314,6 1383,7 @@ mod tests {
    fn test_implicit_str() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut stdin = Cursor::new(Vec::new());
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);



@@ 1322,7 1392,7 @@ mod tests {
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

        let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args);
        let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args);
        runner.execute().unwrap();

        assert_eq!(stdout, b"asc");


@@ 1332,6 1402,7 @@ mod tests {
    fn test_more_implicit_str() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut stdin = Cursor::new(Vec::new());
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);



@@ 1340,7 1411,7 @@ mod tests {
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

        let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args);
        let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args);
        runner.execute().unwrap();

        assert_eq!(stdout, b"asc");


@@ 1350,6 1421,7 @@ mod tests {
    fn test_lazy_str() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut stdin = Cursor::new(Vec::new());
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);



@@ 1358,7 1430,7 @@ mod tests {
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

        let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args);
        let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args);
        runner.execute().unwrap();

        assert_eq!(stdout, b"10");


@@ 1368,6 1440,7 @@ mod tests {
    fn test_lazy_str_nested() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut stdin = Cursor::new(Vec::new());
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);



@@ 1376,7 1449,7 @@ mod tests {
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

        let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args);
        let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args);
        runner.execute().unwrap();

        assert_eq!(stdout, b"123456789");


@@ 1386,6 1459,7 @@ mod tests {
    fn test_is_eq() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut stdin = Cursor::new(Vec::new());
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);



@@ 1395,7 1469,7 @@ mod tests {
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

        let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args);
        let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args);
        runner.execute().unwrap();

        assert_eq!(stdout, b"equal");


@@ 1405,6 1479,7 @@ mod tests {
    fn test_is_neq() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut stdin = Cursor::new(Vec::new());
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);



@@ 1414,7 1489,7 @@ mod tests {
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

        let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args);
        let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args);
        runner.execute().unwrap();

        assert_eq!(stdout, b"nope");


@@ 1424,6 1499,7 @@ mod tests {
    fn test_is_asc() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut stdin = Cursor::new(Vec::new());
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);



@@ 1432,7 1508,7 @@ mod tests {
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

        let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args);
        let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args);
        runner.execute().unwrap();

        assert_eq!(stdout, b"ascending");


@@ 1442,6 1518,7 @@ mod tests {
    fn test_is_asc_neq() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut stdin = Cursor::new(Vec::new());
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);



@@ 1450,7 1527,7 @@ mod tests {
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

        let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args);
        let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args);
        runner.execute().unwrap();

        assert_eq!(stdout, b"nope");


@@ 1460,6 1537,7 @@ mod tests {
    fn test_is_asc_eq() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut stdin = Cursor::new(Vec::new());
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);



@@ 1468,7 1546,7 @@ mod tests {
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

        let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args);
        let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args);
        runner.execute().unwrap();

        assert_eq!(stdout, b"ascending eq");


@@ 1478,6 1556,7 @@ mod tests {
    fn test_is_n_asc_eq() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut stdin = Cursor::new(Vec::new());
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);



@@ 1486,7 1565,7 @@ mod tests {
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

        let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args);
        let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args);
        runner.execute().unwrap();

        assert_eq!(stdout, b"nope");


@@ 1496,6 1575,7 @@ mod tests {
    fn test_is_desc() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut stdin = Cursor::new(Vec::new());
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);



@@ 1504,7 1584,7 @@ mod tests {
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

        let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args);
        let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args);
        runner.execute().unwrap();

        assert_eq!(stdout, b"descending");


@@ 1514,6 1594,7 @@ mod tests {
    fn test_is_desc_neq() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut stdin = Cursor::new(Vec::new());
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);



@@ 1522,7 1603,7 @@ mod tests {
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

        let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args);
        let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args);
        runner.execute().unwrap();

        assert_eq!(stdout, b"nope");


@@ 1532,6 1613,7 @@ mod tests {
    fn test_is_desc_eq() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut stdin = Cursor::new(Vec::new());
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);



@@ 1541,7 1623,7 @@ mod tests {
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

        let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args);
        let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args);
        runner.execute().unwrap();

        assert_eq!(stdout, b"descending eq");


@@ 1551,6 1633,7 @@ mod tests {
    fn test_is_n_desc_eq() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut stdin = Cursor::new(Vec::new());
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);



@@ 1559,7 1642,7 @@ mod tests {
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

        let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args);
        let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args);
        runner.execute().unwrap();

        assert_eq!(stdout, b"nope");


@@ 1569,6 1652,7 @@ mod tests {
    fn test_repeat() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut stdin = Cursor::new(Vec::new());
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);



@@ 1577,7 1661,7 @@ mod tests {
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

        let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args);
        let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args);
        runner.execute().unwrap();

        assert_eq!(stdout, b"aaaaaaaaaa");


@@ 1587,6 1671,7 @@ mod tests {
    fn test_duplicate_data() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut stdin = Cursor::new(Vec::new());
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);



@@ 1595,7 1680,7 @@ mod tests {
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

        let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args);
        let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args);
        runner.execute().unwrap();

        assert_eq!(stdout, b"10");


@@ 1605,6 1690,7 @@ mod tests {
    fn test_drop() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut stdin = Cursor::new(Vec::new());
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);



@@ 1613,7 1699,7 @@ mod tests {
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

        let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args);
        let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args);
        runner.execute().unwrap();

        assert_eq!(stdout, b"63");


@@ 1623,6 1709,7 @@ mod tests {
    fn test_flatten() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut stdin = Cursor::new(Vec::new());
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);



@@ 1631,7 1718,7 @@ mod tests {
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

        let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args);
        let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args);
        runner.execute().unwrap();

        assert_eq!(stdout, b"yes");


@@ 1641,6 1728,7 @@ mod tests {
    fn test_join() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut stdin = Cursor::new(Vec::new());
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);



@@ 1649,7 1737,7 @@ mod tests {
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

        let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args);
        let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args);
        runner.execute().unwrap();

        assert_eq!(stdout, b"a-b-c");


@@ 1659,6 1747,7 @@ mod tests {
    fn test_split() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut stdin = Cursor::new(Vec::new());
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);



@@ 1667,7 1756,7 @@ mod tests {
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

        let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args);
        let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args);
        runner.execute().unwrap();

        assert_eq!(stdout, b"abc");


@@ 1677,6 1766,7 @@ mod tests {
    fn test_subtract() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut stdin = Cursor::new(Vec::new());
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);



@@ 1685,7 1775,7 @@ mod tests {
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

        let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args);
        let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args);
        runner.execute().unwrap();

        assert_eq!(stdout, b"-5");


@@ 1695,6 1785,7 @@ mod tests {
    fn test_multiplication() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut stdin = Cursor::new(Vec::new());
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);



@@ 1703,7 1794,7 @@ mod tests {
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

        let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args);
        let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args);
        runner.execute().unwrap();

        assert_eq!(stdout, b"120");


@@ 1713,6 1804,7 @@ mod tests {
    fn test_division() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut stdin = Cursor::new(Vec::new());
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);



@@ 1721,7 1813,7 @@ mod tests {
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

        let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args);
        let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args);
        runner.execute().unwrap();

        assert_eq!(stdout, b"5/24");


@@ 1731,6 1823,7 @@ mod tests {
    fn test_negation() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut stdin = Cursor::new(Vec::new());
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);



@@ 1739,7 1832,7 @@ mod tests {
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

        let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args);
        let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args);
        runner.execute().unwrap();

        assert_eq!(stdout, b"-3");


@@ 1749,6 1842,7 @@ mod tests {
    fn test_floor() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut stdin = Cursor::new(Vec::new());
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);



@@ 1757,7 1851,7 @@ mod tests {
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

        let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args);
        let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args);
        runner.execute().unwrap();

        assert_eq!(stdout, b"1 0");


@@ 1767,6 1861,7 @@ mod tests {
    fn test_ceil() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut stdin = Cursor::new(Vec::new());
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);



@@ 1775,7 1870,7 @@ mod tests {
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

        let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args);
        let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args);
        runner.execute().unwrap();

        assert_eq!(stdout, b"2 1");


@@ 1785,6 1880,7 @@ mod tests {
    fn test_abs() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut stdin = Cursor::new(Vec::new());
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);



@@ 1793,9 1889,31 @@ mod tests {
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

        let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args);
        let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args);
        runner.execute().unwrap();

        assert_eq!(stdout, b"5/4 99/100");
    }

    #[test]
    fn test_stdin() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut stdin = Cursor::new(Vec::new());
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);

        let test_input = b"(readln print)" as &[u8];
        let test_stdin = b"hello!\nbye\n" as &[u8];
        c.write_all(test_input).unwrap();
        stdin.write_all(test_stdin).unwrap();
        stdin.rewind().unwrap();
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

        let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args);
        runner.execute().unwrap();

        assert_eq!(stdout, b"hello!\n");
    }
}

M cane-wasm/index.html => cane-wasm/index.html +5 -0
@@ 69,6 69,11 @@ arg1 arg2 arg3 (space separated)</textarea
        return false
      })()

	  window.readIn = function readIn() {
		  writeOut("Web playground does not support stdin (yet!)")
		  return ""
	  }

      window.writeOut = function writeOut(text) {
        document.getElementById('output').innerText += text
      }

M cane-wasm/src/lib.rs => cane-wasm/src/lib.rs +20 -3
@@ 4,12 4,14 @@ use cane::stdtypes::{Data, Types};

use cane::Interpreter;
use std::collections::HashMap;
use std::io::Result;
use std::io::{BufReader, Seek};
use std::io::{Cursor, Write};
use std::io::{Cursor, Read, Write};

#[wasm_bindgen]
extern "C" {
    pub fn writeOut(s: &str);
    pub fn readIn() -> String;
}

struct JSOut {}


@@ 20,8 22,22 @@ impl JSOut {
    }
}

struct JSIn {}

impl JSIn {
    fn new() -> Self {
        Self {}
    }
}

impl Read for JSIn {
    fn read(&mut self, mut buf: &mut [u8]) -> Result<usize> {
        buf.write(readIn().as_bytes())
    }
}

impl Write for JSOut {
    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        writeOut(&std::str::from_utf8(buf).unwrap());
        Ok(buf.len())
    }


@@ 40,6 56,7 @@ pub fn interpreter(input: &str, args_str: &str) {
    reader.rewind().unwrap();

    let mut stdout = JSOut::new();
    let mut stdin = BufReader::new(JSIn::new());

    let mut variables = HashMap::new();
    let mut args_data = Data::new(Types::LIST);


@@ 50,7 67,7 @@ pub fn interpreter(input: &str, args_str: &str) {
        args_data.get_list().push(data);
    }

    let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args_data);
    let mut runner = Interpreter::new(reader, &mut stdout, &mut stdin, &mut variables, args_data);

    match runner.execute() {
        Ok(..) => (),

M demos/loop.cn => demos/loop.cn +4 -0
@@ 8,3 8,7 @@
	]
	100 repeat
)

; Will print "hello" forever ~

([(`hello' println)] forever)

M shell.nix => shell.nix +1 -1
@@ 1,5 1,5 @@
let
  pkgs = import (fetchTarball("channel:nixpkgs-unstable")) {};
in pkgs.mkShell {
  buildInputs = [ pkgs.rustfmt pkgs.rust-analyzer pkgs.wasm-pack pkgs.rustup pkgs.pkg-config pkgs.openssl pkgs.binaryen ];
  buildInputs = [ pkgs.rustfmt pkgs.rust-analyzer pkgs.wasm-pack pkgs.rustup pkgs.pkg-config pkgs.openssl pkgs.binaryen pkgs.nodePackages.prettier ];
}