MAJOR refactoring and scopes
This commit is contained in:
parent
1bc28d02ff
commit
3753f6d8f5
55
src/ast.rs
55
src/ast.rs
|
@ -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!(
|
||||
|
|
250
src/parse.rs
250
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<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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue