MAJOR refactoring and scopes

This commit is contained in:
vanten-s 2023-09-17 21:52:14 +02:00
parent 1bc28d02ff
commit 3753f6d8f5
Signed by: vanten-s
GPG key ID: DE3060396884D3F2
3 changed files with 166 additions and 141 deletions

View file

@ -7,6 +7,7 @@ use std::collections::HashMap;
pub struct Function {
pub name: String,
pub statements: Vec<Statement>,
pub n_args: u64,
assembly: Option<String>,
}
@ -15,6 +16,7 @@ pub enum Statement {
FunctionCall(String, Vec<ValueNode>),
VariableDeclaration(String, ValueNode),
VariableAssignment(String, ValueNode),
Scope(Vec<Statement>),
}
#[derive(Debug, Clone)]
@ -46,10 +48,11 @@ pub trait Node {
}
impl Function {
pub fn new(name: String, statements: Vec<Statement>) -> Function {
pub fn new(name: String, n_args: u64, statements: Vec<Statement>) -> Function {
Function {
name,
statements,
n_args,
assembly: None,
}
}
@ -74,8 +77,9 @@ fn get_default_functions() -> HashMap<String, Function> {
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::<Vec<String>>()
.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!(

View file

@ -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<Function>),
}
impl Function {
fn push_statement(&mut self, statement: Statement) -> Function {
self.statements.push(statement);
self.to_owned()
}
}
fn parse_math(tokens: &Vec<Token>) -> ValueNode {
let mut prioritizing_order: HashMap<i64, HashSet<Token>> = HashMap::new();
prioritizing_order.insert(0, HashSet::from([Token::Plus, Token::Minus]));
@ -80,145 +66,135 @@ fn parse_math(tokens: &Vec<Token>) -> ValueNode {
};
}
fn parse_statement(
parse_state: &mut ParseState,
i: &mut usize,
tokens: &Vec<Token>,
functions: &Vec<Function>,
) -> ParseState {
let mut current_function = match parse_state {
ParseState::Statement(f) => f.to_owned(),
_ => todo!(),
};
fn parse_statements(tokens: &Vec<Token>, starting_i: usize) -> (Vec<Statement>, 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<Token> = 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<Token> = 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<Token>> = Vec::new();
i += 1;
while tokens[i] != Token::CloseParanthesis {
let mut argument_tokens: Vec<Token> = 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<ValueNode> = 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<Token> = 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<Token> = 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<Token>> = Vec::new();
*i += 1;
while tokens[*i] != Token::CloseParanthesis {
let mut argument_tokens: Vec<Token> = 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<ValueNode> = 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<Token>) -> Vec<Function> {
let mut parse_state = ParseState::None(Vec::new());
let mut functions: Vec<Function> = 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::<u64>().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
}

View file

@ -20,6 +20,7 @@ pub enum Keyword {
Function,
Let,
Assign,
If,
}
enum TokenFinishedUnfinished {
@ -39,6 +40,7 @@ fn generate_keyword_map() -> HashMap<String, Keyword> {
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
}