oort-vm 1.0.0

The Oort Virtual Machine
Documentation
use std::io;
use std::io::{stdout, Write};
use logos::Logos;

use crate::error::error;
use crate::error::get_token;
use crate::ir::compile::{Compile, IRFunc};

use super::access;
use super::lexer;

#[derive(PartialEq, Debug)]
pub(crate) enum Expr {
    _Integer(i64),
    _Add(Box<Expr>, Box<Expr>),
    _Subtract(Box<Expr>, Box<Expr>),
    _Multiply(Box<Expr>, Box<Expr>),
    _Divide(Box<Expr>, Box<Expr>),
    Func(Compile, Box<Expr>),
    String(String),
    Args(Vec<Expr>),
}

pub(crate) fn parse(ir_line: String) -> Expr {
    let mut ast = vec![];
    let mut describe = String::new();

    fn default(_expr: Expr) -> io::Result<()> {
        stdout().flush()
    }

    let mut func = Compile {
        f: IRFunc::Void(default),
        requires: vec![],
        c_func: "".to_string(),
    };

    let mut args = vec![];

    let tokens = lexer::Token::lexer(&ir_line);

    for token in tokens {
        let token = get_token(token);

        match token {
            lexer::Token::Descriptor(des) => describe = des,

            lexer::Token::Ident(ident) => {
                if describe.is_empty() {
                    error("Expected descriptor before identifier");
                }

                match describe.as_str() {
                    "func" => {
                        if access::functions_contains(&ident) {
                            let f = access::get_from_functions(ident).unwrap();

                            func = f;
                        }
                    }
                    "arg/string" => {
                        args.push(Expr::String(ident));
                    }
                    des => error(format!("Unknown descriptor: {des}").as_str()),
                }
            }

            _ => error("Expected descriptor token `%` or Identifier"),
        }
        
    }
    ast.push(Expr::Func(func, Box::new(Expr::Args(args))));
    println!("{:#?}", ast);

    Expr::Args(ast)
}

#[cfg(test)]
mod parser_tests {
    use super::*;

    #[test]
    fn test_parser() {
        let ast = parse("%func print".to_string());

        let f = access::get_from_functions("print".to_string()).unwrap();
        let expected_func = Expr::Func(f, Box::new(Expr::Args(vec![])));

        assert_eq!(ast, Expr::Args(vec![expected_func]));
    }
}