diff --git a/src/ast.rs b/src/ast.rs index bdeb2f6..cebeb59 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -7,6 +7,7 @@ use std::collections::HashMap; pub struct Function { pub name: String, pub statements: Vec, + pub n_args: u64, assembly: Option, } @@ -15,6 +16,7 @@ pub enum Statement { FunctionCall(String, Vec), VariableDeclaration(String, ValueNode), VariableAssignment(String, ValueNode), + Scope(Vec), } #[derive(Debug, Clone)] @@ -46,10 +48,11 @@ pub trait Node { } impl Function { - pub fn new(name: String, statements: Vec) -> Function { + pub fn new(name: String, n_args: u64, statements: Vec) -> Function { Function { name, statements, + n_args, assembly: None, } } @@ -74,8 +77,9 @@ fn get_default_functions() -> HashMap { functions.insert( "out".to_string(), Function { - name: "exit".to_string(), + name: "out".to_string(), statements: vec![], + n_args: 1, assembly: Some( " out: @@ -115,6 +119,7 @@ F-OUT JMP 0xFF" Function { name: "exit".to_string(), statements: vec![], + n_args: 0, assembly: Some( " exit: @@ -165,13 +170,50 @@ F-OUT JMP 0xFF impl Node for Statement { fn to_assembly(&self, state: &mut AssemblerState) -> String { match self { + Statement::Scope(statements) => { + let init_assembly = " +ROM-OUT FLAGS-IN 0x00 +SE-OUT A-IN 0xFF +ROM-OUT B-IN 0x01 +ALU-OUT SE-IN 0xFF +" + .to_string(); + + state.variables.push("start scope".to_string()); + + let statement_assembly = statements + .iter() + .map(|x| x.to_assembly(state)) + .collect::>() + .join("\n"); + + let mut stop_assembly = "".to_string(); + + while state.variables.contains(&"start scope".to_string()) { + stop_assembly += &format!( + " +ROM-OUT FLAGS-IN 0x80 +SE-OUT A-IN 0xFF +ROM-OUT B-IN 0x01 +ALU-OUT SE-IN 0xFF +ROM-OUT FLAGS-IN 0x00" + ); + state.variables.pop(); + } + + format!( + "{init_assembly} +{statement_assembly} +{stop_assembly}" + ) + } Statement::FunctionCall(name, arguments) => { if !state.functions.contains_key(name) { todo!() } - state.variables.push(name.to_owned()); + state.variables.push(name.to_owned()); let argument_assembly: String = arguments .into_iter() .map(|x| x.to_assembly(state)) @@ -184,6 +226,10 @@ impl Node for Statement { .map(char::from) .collect(); + for _ in 0..state.functions.get(name).unwrap().n_args { + state.variables.pop(); + } + state.variables.pop(); format!( @@ -261,6 +307,8 @@ impl Node for ValueNode { ValueNode::Operator(o) => o.to_assembly(state), ValueNode::Variable(name) => { if !state.variables.contains(name) { + dbg!(&name); + dbg!(&state.variables); todo!(); } @@ -268,7 +316,6 @@ impl Node for ValueNode { - state.variables.iter().position(|x| x == name).unwrap() - 1; - dbg!(&state.variables); state.variables.push(name.to_owned()); format!( diff --git a/src/parse.rs b/src/parse.rs index 1b2cfbd..1486f65 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -4,20 +4,6 @@ use crate::ast::*; use crate::tokeniser::Keyword; use crate::tokeniser::Token; -#[derive(Clone, Debug)] -enum ParseState { - Function(Function), - Statement(Function), - None(Vec), -} - -impl Function { - fn push_statement(&mut self, statement: Statement) -> Function { - self.statements.push(statement); - self.to_owned() - } -} - fn parse_math(tokens: &Vec) -> ValueNode { let mut prioritizing_order: HashMap> = HashMap::new(); prioritizing_order.insert(0, HashSet::from([Token::Plus, Token::Minus])); @@ -80,145 +66,135 @@ fn parse_math(tokens: &Vec) -> ValueNode { }; } -fn parse_statement( - parse_state: &mut ParseState, - i: &mut usize, - tokens: &Vec, - functions: &Vec, -) -> ParseState { - let mut current_function = match parse_state { - ParseState::Statement(f) => f.to_owned(), - _ => todo!(), - }; +fn parse_statements(tokens: &Vec, starting_i: usize) -> (Vec, usize) { + let mut i = starting_i; + let mut statements = Vec::new(); + while i < tokens.len() { + statements.push(match &tokens[i] { + Token::OpenSquiglyBracket => { + let (statements, added_to_i) = parse_statements(tokens, i + 1); + i = added_to_i + 1; + Statement::Scope(statements) + } + Token::Keyword(Keyword::Let) => { + i += 1; + let name = match tokens[i].clone() { + Token::Identifier(identifier) => identifier, + _ => todo!(), + }; - if tokens[i.to_owned()] == Token::CloseSquiglyBracket { - let mut functions = functions.to_owned(); - functions.push(current_function); + i += 1; + match tokens[i].clone() { + Token::Equals => {} + _ => todo!(), + }; - return ParseState::None(functions); + i += 1; + + let mut declaration_tokens: Vec = Vec::new(); + while tokens[i] != Token::Semi { + declaration_tokens.push(tokens[i].clone()); + i += 1; + } + Statement::VariableDeclaration(name, parse_math(&declaration_tokens)) + } + Token::Keyword(Keyword::Assign) => { + i += 1; + let name = match tokens[i].clone() { + Token::Identifier(identifier) => identifier, + _ => todo!(), + }; + + i += 1; + match tokens[i].clone() { + Token::Equals => {} + _ => todo!(), + }; + + i += 1; + + let mut declaration_tokens: Vec = Vec::new(); + while tokens[i] != Token::Semi { + declaration_tokens.push(tokens[i].clone()); + i += 1; + } + Statement::VariableAssignment(name, parse_math(&declaration_tokens)) + } + Token::Identifier(identifier) => { + i += 1; + + let mut declaration_tokens: Vec> = Vec::new(); + + i += 1; + while tokens[i] != Token::CloseParanthesis { + let mut argument_tokens: Vec = Vec::new(); + while tokens[i] != Token::Comma { + argument_tokens.push(tokens[i].clone()); + i += 1; + } + declaration_tokens.push(argument_tokens); + i += 1; + } + + i += 1; + + let mut arguments: Vec = Vec::new(); + + for token_vec in &declaration_tokens { + if token_vec == &Vec::new() { + continue; + } + arguments.push(parse_math(token_vec)); + } + + Statement::FunctionCall(identifier.to_owned(), arguments) + } + Token::CloseSquiglyBracket => { + return (statements, i); + } + Token::Semi => { + i += 1; + continue; + } + _other => { + dbg!(_other); + todo!() + } + }); } - - let statement = match &tokens[i.to_owned()] { - Token::Keyword(Keyword::Let) => { - *i += 1; - let name = match tokens[*i].clone() { - Token::Identifier(identifier) => identifier, - _ => todo!(), - }; - - *i += 1; - match tokens[*i].clone() { - Token::Equals => {} - _ => todo!(), - }; - - *i += 1; - - let mut declaration_tokens: Vec = Vec::new(); - while tokens[*i] != Token::Semi { - declaration_tokens.push(tokens[*i].clone()); - *i += 1; - } - Statement::VariableDeclaration(name, parse_math(&declaration_tokens)) - } - Token::Keyword(Keyword::Assign) => { - *i += 1; - let name = match tokens[*i].clone() { - Token::Identifier(identifier) => identifier, - _ => todo!(), - }; - - *i += 1; - match tokens[*i].clone() { - Token::Equals => {} - _ => todo!(), - }; - - *i += 1; - - let mut declaration_tokens: Vec = Vec::new(); - while tokens[*i] != Token::Semi { - declaration_tokens.push(tokens[*i].clone()); - *i += 1; - } - Statement::VariableAssignment(name, parse_math(&declaration_tokens)) - } - Token::Identifier(identifier) => { - *i += 1; - - let mut declaration_tokens: Vec> = Vec::new(); - - *i += 1; - while tokens[*i] != Token::CloseParanthesis { - let mut argument_tokens: Vec = Vec::new(); - while tokens[*i] != Token::Comma { - argument_tokens.push(tokens[*i].clone()); - *i += 1; - } - declaration_tokens.push(argument_tokens); - *i += 1; - } - - *i += 1; - - let mut arguments: Vec = Vec::new(); - - for token_vec in &declaration_tokens { - if token_vec == &Vec::new() { - continue; - } - arguments.push(parse_math(token_vec)); - } - - Statement::FunctionCall(identifier.to_owned(), arguments) - } - _other => { - todo!() - } - }; - - current_function.push_statement(statement); - - return ParseState::Statement(current_function); + (statements, i) } pub fn ast(tokens: Vec) -> Vec { - let mut parse_state = ParseState::None(Vec::new()); let mut functions: Vec = Vec::new(); let mut i = 0; while i < tokens.len() { - parse_state = match &parse_state { - ParseState::None(funcs) => { - functions = funcs.to_owned(); - // Expect function and shit - match &tokens[i] { - Token::Keyword(keyword) => match keyword { - Keyword::Function => { - ParseState::Function(Function::new("".to_string(), Vec::new())) - } - _ => todo!(), - }, + match &tokens[i] { + Token::Keyword(Keyword::Function) => { + let (statements, added_to_i) = parse_statements(&tokens, i + 4); + let statements = vec![Statement::Scope(statements)]; + let function_name = match &tokens[i + 1] { + Token::Identifier(identifier) => identifier.to_owned(), _ => todo!(), - } + }; + let n_args = match &tokens[i + 2] { + Token::Number(num) => num.parse::().unwrap(), + _ => todo!(), + }; + i += added_to_i; + functions.push(Function::new(function_name, n_args, statements)); } - ParseState::Function(func) => match &tokens[i] { - Token::Identifier(identifier) => { - ParseState::Function(Function::new(identifier.to_owned(), Vec::new())) - } - Token::OpenSquiglyBracket => ParseState::Statement(func.to_owned()), - _ => todo!(), - }, - ParseState::Statement(_function) => { - parse_statement(&mut parse_state, &mut i, &tokens, &functions) + _other => { + dbg!(&functions); + dbg!(i); + dbg!(_other); + todo!(); } }; i += 1; } - match parse_state { - ParseState::None(v) => v, - _ => todo!(), - } + functions } diff --git a/src/tokeniser.rs b/src/tokeniser.rs index c031b65..202bef6 100644 --- a/src/tokeniser.rs +++ b/src/tokeniser.rs @@ -20,6 +20,7 @@ pub enum Keyword { Function, Let, Assign, + If, } enum TokenFinishedUnfinished { @@ -39,6 +40,7 @@ fn generate_keyword_map() -> HashMap { keywords.insert("fn".to_string(), K::Function); keywords.insert("let".to_string(), K::Let); keywords.insert("assign".to_string(), K::Assign); + keywords.insert("if".to_string(), K::If); keywords }