~fd/cane-lang

32db883e27d4e3ed49569964682dc65b7ac58ec8 — Ersei Saggi 8 months ago 8b2f877
Actions (functions)
3 files changed, 164 insertions(+), 41 deletions(-)

M src/interpreter.rs
M src/main.rs
M src/stdtypes.rs
M src/interpreter.rs => src/interpreter.rs +142 -27
@@ 1,7 1,7 @@
use crate::stdtypes::{Data, Number, Types};
use rug::Rational;
use std::collections::HashMap;
use std::io::{self, BufReader, Error, ErrorKind, Read, Seek, SeekFrom};
use std::io::{self, BufReader, Cursor, Error, ErrorKind, Read, Seek, SeekFrom, Write};
use std::u8;

#[derive(PartialEq, Eq, Debug)]


@@ 60,8 60,9 @@ where
{
    reader: BufReader<R>,
    call_stack: Vec<Call>,
    variables: HashMap<String, Data>,
    variables: &'a mut HashMap<String, Data>,
    stdout: &'a mut dyn io::Write,
    args: Data,
}

impl<'a, R> Interpreter<'_, R>


@@ 69,17 70,23 @@ where
    R: Read,
    R: Seek,
{
    pub fn new(reader: BufReader<R>, stdout: &'a mut dyn io::Write) -> Interpreter<'a, R> {
    pub fn new(
        reader: BufReader<R>,
        stdout: &'a mut dyn io::Write,
        variables: &'a mut HashMap<String, Data>,
        args: Data,
    ) -> Interpreter<'a, R> {
        let mut intp = Interpreter {
            reader,
            call_stack: Vec::new(),
            variables: HashMap::new(),
            variables,
            stdout,
            args,
        };
        intp.call_stack.push(Call::new(State::Wait));
        return intp;
    }
    pub fn execute(&mut self) -> Result<(), io::Error> {
    pub fn execute(&mut self) -> Result<Data, io::Error> {
        let mut buf: [u8; 1] = [0];
        loop {
            match self.reader.read_exact(&mut buf) {


@@ 120,7 127,7 @@ where
                            let data = self.call_stack.last_mut().unwrap().get_data().to_owned();
                            self.call_stack.pop();
                            match self.call_stack.last_mut().unwrap().get_state() {
                                Some(State::Data) => self
                                Some(State::Data) | Some(State::Wait) => self
                                    .call_stack
                                    .last_mut()
                                    .unwrap()


@@ 191,6 198,14 @@ where
                                "add" => {
                                    self.call_stack.last_mut().unwrap().get_data().add();
                                } // Add data
                                "args" => {
                                    self.call_stack
                                        .last_mut()
                                        .unwrap()
                                        .get_data()
                                        .get_list()
                                        .append(self.args.clone());
                                } // Add data
                                "print" => {
                                    write!(
                                        self.stdout,


@@ 283,22 298,46 @@ where
                                        .variables
                                        .get(self.call_stack.last_mut().unwrap().get_token())
                                    {
                                        Some(data) => {
                                            match data.get_kind() {
                                                Types::ACTION => {
                                                    unimplemented!()
                                                }
                                                _ => {
                                        Some(data) => match data.get_kind() {
                                            Types::ACTION => {
                                                let mut c = Cursor::new(Vec::new());

                                                c.write_all(data.to_string().as_bytes()).unwrap();
                                                let mut reader = BufReader::new(c);
                                                reader.rewind().unwrap();
                                                let mut action_interp = Interpreter::new(
                                                    reader,
                                                    self.stdout,
                                                    self.variables,
                                                    self.call_stack
                                                        .last_mut()
                                                        .unwrap()
                                                        .get_data()
                                                        .get_list()
                                                        .push(data.clone());
                                                reset = true;
                                                        .clone(),
                                                );
                                                match action_interp.execute() {
                                                    Ok(data) => {
                                                        self.call_stack
                                                            .last_mut()
                                                            .unwrap()
                                                            .get_data()
                                                            .get_list()
                                                            .push(data);
                                                        reset = true;
                                                    }
                                                    Err(e) => return Err(e),
                                                }
                                            }
                                        }
                                            _ => {
                                                self.call_stack
                                                    .last_mut()
                                                    .unwrap()
                                                    .get_data()
                                                    .get_list()
                                                    .push(data.clone());
                                                reset = true;
                                            }
                                        },
                                        None => (),
                                    }
                                }


@@ 315,7 354,7 @@ where
                                    self.call_stack.last_mut().unwrap().get_data().to_owned();
                                self.call_stack.pop();
                                match self.call_stack.last_mut().unwrap().get_state() {
                                    Some(State::Data) => self
                                    Some(State::Data) | Some(State::Wait) => self
                                        .call_stack
                                        .last_mut()
                                        .unwrap()


@@ 401,7 440,7 @@ where
        // End of file
        // Check if the program still needs to do anything
        match self.call_stack.last_mut().unwrap().get_state() {
            Some(State::Wait) => Ok(()),
            Some(State::Wait) => Ok(self.call_stack.last_mut().unwrap().get_data().clone()),
            _ => {
                return Err(Error::new(
                    ErrorKind::UnexpectedEof,


@@ 415,6 454,8 @@ where
#[cfg(test)]
mod tests {
    use crate::interpreter::Interpreter;
    use crate::stdtypes::{Data, Types};
    use std::collections::HashMap;
    use std::io::BufReader;
    use std::io::{Cursor, Seek, Write};



@@ 422,13 463,15 @@ mod tests {
    fn test_print_string() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);

        let test_input = b"(`hello, world!\n' print)" as &[u8];
        c.write_all(test_input).unwrap();
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

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

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


@@ 438,13 481,15 @@ mod tests {
    fn test_escape_string() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);

        let test_input = b"(`hello, world!\\\\\\'\\n' print)" as &[u8];
        c.write_all(test_input).unwrap();
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

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

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


@@ 454,13 499,15 @@ mod tests {
    fn test_add_print_string() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);

        let test_input = b"(`hello, ' `world!\n' add print)" as &[u8];
        c.write_all(test_input).unwrap();
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

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

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


@@ 470,13 517,15 @@ mod tests {
    fn test_add_rational() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);

        let test_input = b"(1/2 3/4 add print)" as &[u8];
        c.write_all(test_input).unwrap();
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

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

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


@@ 486,13 535,15 @@ mod tests {
    fn test_no_unwrap() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);

        let test_input = b"(1 2 (3 4 add 1) add print)" as &[u8];
        c.write_all(test_input).unwrap();
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

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

        assert_eq!(stdout, b"5");


@@ 502,13 553,15 @@ mod tests {
    fn test_unwrap() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);

        let test_input = b"(1 2 (3 4 add 1)? add print)" as &[u8];
        c.write_all(test_input).unwrap();
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

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

        assert_eq!(stdout, b"11");


@@ 518,13 571,15 @@ mod tests {
    fn test_variable() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);

        let test_input = b"((1 1 2 add) `var' defvar) (var print)" as &[u8];
        c.write_all(test_input).unwrap();
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

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

        assert_eq!(stdout, b"4");


@@ 534,15 589,75 @@ mod tests {
    fn test_variable_overwrite() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut variables = HashMap::new();
        let args = Data::new(Types::LIST);

        let test_input = b"((1 1 2 add) `var' defvar) (var print) (1 `var' defvar) (var print)" as &[u8];
        let test_input =
            b"((1 1 2 add) `var' defvar) (var print) (1 `var' defvar) (var print)" as &[u8];
        c.write_all(test_input).unwrap();
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

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

        assert_eq!(stdout, b"41");
    }

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

        let test_input = b"(`(1 1 2 add print)' `act' defact) (act)" as &[u8];
        c.write_all(test_input).unwrap();
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

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

        assert_eq!(stdout, b"4");
    }

    #[test]
    fn test_args() {
        let mut c = Cursor::new(Vec::new());
        let mut stdout = Vec::new();
        let mut variables = HashMap::new();
        let mut args = Data::new(Types::LIST);
        let mut arg = Data::new(Types::STRING);
        arg.set_string("argument".to_string());
        args.get_list().push(arg);

        let test_input = b"(args print)" as &[u8];
        c.write_all(test_input).unwrap();
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

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

        assert_eq!(stdout, b"argument");
    }

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

        let test_input = b"(`(args add print)' `act' defact) (1 2 3 4 act)" as &[u8];
        c.write_all(test_input).unwrap();
        let mut reader = BufReader::new(c);
        reader.rewind().unwrap();

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

        assert_eq!(stdout, b"10");
    }
}

M src/main.rs => src/main.rs +15 -14
@@ 1,10 1,13 @@
mod interpreter;
mod stdtypes;

use stdtypes::Data;

use crate::interpreter::Interpreter;
use std::collections::HashMap;
use std::{env, fs::File, io::BufReader, io::Error, io::ErrorKind};

fn main() -> std::io::Result<()> {
fn main() -> std::io::Result<Data> {
    let args: Vec<_> = env::args().collect();
    if args.len() < 2 {
        return Err(Error::new(


@@ 13,18 16,16 @@ fn main() -> std::io::Result<()> {
        ));
    }

    let mut iter = args.iter();
    iter.next();

    for name in iter {
        let f = File::open(name)?;
        let reader = BufReader::new(f);
        let mut stdout = std::io::stdout();
        let mut runner = Interpreter::new(reader, &mut stdout);
        match runner.execute() {
            Ok(..) => (),
            Err(e) => return Err(e),
        }
    let f = File::open(args.get(1).unwrap())?;
    let reader = BufReader::new(f);
    let mut stdout = std::io::stdout();
    let mut variables = HashMap::new();
    let mut args_data = Data::new(stdtypes::Types::LIST);
    for arg in args {
        let mut data = Data::new(stdtypes::Types::STRING);
        data.set_string(arg);
        args_data.get_list().push(data);
    }
    Ok(())
    let mut runner = Interpreter::new(reader, &mut stdout, &mut variables, args_data);
    runner.execute()
}

M src/stdtypes.rs => src/stdtypes.rs +7 -0
@@ 1,6 1,7 @@
use rug::Rational;
use std::collections::LinkedList;
use std::fmt;
use std::process::{ExitCode, Termination};

/// Represents a doubly-linked list
#[derive(Clone, Debug)]


@@ 119,6 120,12 @@ impl fmt::Display for Data {
    }
}

impl Termination for Data {
    fn report(self) -> ExitCode {
        return ExitCode::SUCCESS;
    }
}

impl List {
    pub fn push(&mut self, data: Data) {
        self.0.push_back(data);