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 struct Function {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub statements: Vec<Statement>,
|
pub statements: Vec<Statement>,
|
||||||
|
pub n_args: u64,
|
||||||
assembly: Option<String>,
|
assembly: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +16,7 @@ pub enum Statement {
|
||||||
FunctionCall(String, Vec<ValueNode>),
|
FunctionCall(String, Vec<ValueNode>),
|
||||||
VariableDeclaration(String, ValueNode),
|
VariableDeclaration(String, ValueNode),
|
||||||
VariableAssignment(String, ValueNode),
|
VariableAssignment(String, ValueNode),
|
||||||
|
Scope(Vec<Statement>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -46,10 +48,11 @@ pub trait Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Function {
|
impl Function {
|
||||||
pub fn new(name: String, statements: Vec<Statement>) -> Function {
|
pub fn new(name: String, n_args: u64, statements: Vec<Statement>) -> Function {
|
||||||
Function {
|
Function {
|
||||||
name,
|
name,
|
||||||
statements,
|
statements,
|
||||||
|
n_args,
|
||||||
assembly: None,
|
assembly: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,8 +77,9 @@ fn get_default_functions() -> HashMap<String, Function> {
|
||||||
functions.insert(
|
functions.insert(
|
||||||
"out".to_string(),
|
"out".to_string(),
|
||||||
Function {
|
Function {
|
||||||
name: "exit".to_string(),
|
name: "out".to_string(),
|
||||||
statements: vec![],
|
statements: vec![],
|
||||||
|
n_args: 1,
|
||||||
assembly: Some(
|
assembly: Some(
|
||||||
"
|
"
|
||||||
out:
|
out:
|
||||||
|
@ -115,6 +119,7 @@ F-OUT JMP 0xFF"
|
||||||
Function {
|
Function {
|
||||||
name: "exit".to_string(),
|
name: "exit".to_string(),
|
||||||
statements: vec![],
|
statements: vec![],
|
||||||
|
n_args: 0,
|
||||||
assembly: Some(
|
assembly: Some(
|
||||||
"
|
"
|
||||||
exit:
|
exit:
|
||||||
|
@ -165,13 +170,50 @@ F-OUT JMP 0xFF
|
||||||
impl Node for Statement {
|
impl Node for Statement {
|
||||||
fn to_assembly(&self, state: &mut AssemblerState) -> String {
|
fn to_assembly(&self, state: &mut AssemblerState) -> String {
|
||||||
match self {
|
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) => {
|
Statement::FunctionCall(name, arguments) => {
|
||||||
if !state.functions.contains_key(name) {
|
if !state.functions.contains_key(name) {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
state.variables.push(name.to_owned());
|
|
||||||
|
|
||||||
|
state.variables.push(name.to_owned());
|
||||||
let argument_assembly: String = arguments
|
let argument_assembly: String = arguments
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|x| x.to_assembly(state))
|
.map(|x| x.to_assembly(state))
|
||||||
|
@ -184,6 +226,10 @@ impl Node for Statement {
|
||||||
.map(char::from)
|
.map(char::from)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
for _ in 0..state.functions.get(name).unwrap().n_args {
|
||||||
|
state.variables.pop();
|
||||||
|
}
|
||||||
|
|
||||||
state.variables.pop();
|
state.variables.pop();
|
||||||
|
|
||||||
format!(
|
format!(
|
||||||
|
@ -261,6 +307,8 @@ impl Node for ValueNode {
|
||||||
ValueNode::Operator(o) => o.to_assembly(state),
|
ValueNode::Operator(o) => o.to_assembly(state),
|
||||||
ValueNode::Variable(name) => {
|
ValueNode::Variable(name) => {
|
||||||
if !state.variables.contains(name) {
|
if !state.variables.contains(name) {
|
||||||
|
dbg!(&name);
|
||||||
|
dbg!(&state.variables);
|
||||||
todo!();
|
todo!();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,7 +316,6 @@ impl Node for ValueNode {
|
||||||
- state.variables.iter().position(|x| x == name).unwrap()
|
- state.variables.iter().position(|x| x == name).unwrap()
|
||||||
- 1;
|
- 1;
|
||||||
|
|
||||||
dbg!(&state.variables);
|
|
||||||
state.variables.push(name.to_owned());
|
state.variables.push(name.to_owned());
|
||||||
|
|
||||||
format!(
|
format!(
|
||||||
|
|
146
src/parse.rs
146
src/parse.rs
|
@ -4,20 +4,6 @@ use crate::ast::*;
|
||||||
use crate::tokeniser::Keyword;
|
use crate::tokeniser::Keyword;
|
||||||
use crate::tokeniser::Token;
|
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 {
|
fn parse_math(tokens: &Vec<Token>) -> ValueNode {
|
||||||
let mut prioritizing_order: HashMap<i64, HashSet<Token>> = HashMap::new();
|
let mut prioritizing_order: HashMap<i64, HashSet<Token>> = HashMap::new();
|
||||||
prioritizing_order.insert(0, HashSet::from([Token::Plus, Token::Minus]));
|
prioritizing_order.insert(0, HashSet::from([Token::Plus, Token::Minus]));
|
||||||
|
@ -80,86 +66,77 @@ fn parse_math(tokens: &Vec<Token>) -> ValueNode {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_statement(
|
fn parse_statements(tokens: &Vec<Token>, starting_i: usize) -> (Vec<Statement>, usize) {
|
||||||
parse_state: &mut ParseState,
|
let mut i = starting_i;
|
||||||
i: &mut usize,
|
let mut statements = Vec::new();
|
||||||
tokens: &Vec<Token>,
|
while i < tokens.len() {
|
||||||
functions: &Vec<Function>,
|
statements.push(match &tokens[i] {
|
||||||
) -> ParseState {
|
Token::OpenSquiglyBracket => {
|
||||||
let mut current_function = match parse_state {
|
let (statements, added_to_i) = parse_statements(tokens, i + 1);
|
||||||
ParseState::Statement(f) => f.to_owned(),
|
i = added_to_i + 1;
|
||||||
_ => todo!(),
|
Statement::Scope(statements)
|
||||||
};
|
|
||||||
|
|
||||||
if tokens[i.to_owned()] == Token::CloseSquiglyBracket {
|
|
||||||
let mut functions = functions.to_owned();
|
|
||||||
functions.push(current_function);
|
|
||||||
|
|
||||||
return ParseState::None(functions);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let statement = match &tokens[i.to_owned()] {
|
|
||||||
Token::Keyword(Keyword::Let) => {
|
Token::Keyword(Keyword::Let) => {
|
||||||
*i += 1;
|
i += 1;
|
||||||
let name = match tokens[*i].clone() {
|
let name = match tokens[i].clone() {
|
||||||
Token::Identifier(identifier) => identifier,
|
Token::Identifier(identifier) => identifier,
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
*i += 1;
|
i += 1;
|
||||||
match tokens[*i].clone() {
|
match tokens[i].clone() {
|
||||||
Token::Equals => {}
|
Token::Equals => {}
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
*i += 1;
|
i += 1;
|
||||||
|
|
||||||
let mut declaration_tokens: Vec<Token> = Vec::new();
|
let mut declaration_tokens: Vec<Token> = Vec::new();
|
||||||
while tokens[*i] != Token::Semi {
|
while tokens[i] != Token::Semi {
|
||||||
declaration_tokens.push(tokens[*i].clone());
|
declaration_tokens.push(tokens[i].clone());
|
||||||
*i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
Statement::VariableDeclaration(name, parse_math(&declaration_tokens))
|
Statement::VariableDeclaration(name, parse_math(&declaration_tokens))
|
||||||
}
|
}
|
||||||
Token::Keyword(Keyword::Assign) => {
|
Token::Keyword(Keyword::Assign) => {
|
||||||
*i += 1;
|
i += 1;
|
||||||
let name = match tokens[*i].clone() {
|
let name = match tokens[i].clone() {
|
||||||
Token::Identifier(identifier) => identifier,
|
Token::Identifier(identifier) => identifier,
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
*i += 1;
|
i += 1;
|
||||||
match tokens[*i].clone() {
|
match tokens[i].clone() {
|
||||||
Token::Equals => {}
|
Token::Equals => {}
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
*i += 1;
|
i += 1;
|
||||||
|
|
||||||
let mut declaration_tokens: Vec<Token> = Vec::new();
|
let mut declaration_tokens: Vec<Token> = Vec::new();
|
||||||
while tokens[*i] != Token::Semi {
|
while tokens[i] != Token::Semi {
|
||||||
declaration_tokens.push(tokens[*i].clone());
|
declaration_tokens.push(tokens[i].clone());
|
||||||
*i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
Statement::VariableAssignment(name, parse_math(&declaration_tokens))
|
Statement::VariableAssignment(name, parse_math(&declaration_tokens))
|
||||||
}
|
}
|
||||||
Token::Identifier(identifier) => {
|
Token::Identifier(identifier) => {
|
||||||
*i += 1;
|
i += 1;
|
||||||
|
|
||||||
let mut declaration_tokens: Vec<Vec<Token>> = Vec::new();
|
let mut declaration_tokens: Vec<Vec<Token>> = Vec::new();
|
||||||
|
|
||||||
*i += 1;
|
i += 1;
|
||||||
while tokens[*i] != Token::CloseParanthesis {
|
while tokens[i] != Token::CloseParanthesis {
|
||||||
let mut argument_tokens: Vec<Token> = Vec::new();
|
let mut argument_tokens: Vec<Token> = Vec::new();
|
||||||
while tokens[*i] != Token::Comma {
|
while tokens[i] != Token::Comma {
|
||||||
argument_tokens.push(tokens[*i].clone());
|
argument_tokens.push(tokens[i].clone());
|
||||||
*i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
declaration_tokens.push(argument_tokens);
|
declaration_tokens.push(argument_tokens);
|
||||||
*i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
*i += 1;
|
i += 1;
|
||||||
|
|
||||||
let mut arguments: Vec<ValueNode> = Vec::new();
|
let mut arguments: Vec<ValueNode> = Vec::new();
|
||||||
|
|
||||||
|
@ -172,53 +149,52 @@ fn parse_statement(
|
||||||
|
|
||||||
Statement::FunctionCall(identifier.to_owned(), arguments)
|
Statement::FunctionCall(identifier.to_owned(), arguments)
|
||||||
}
|
}
|
||||||
|
Token::CloseSquiglyBracket => {
|
||||||
|
return (statements, i);
|
||||||
|
}
|
||||||
|
Token::Semi => {
|
||||||
|
i += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
_other => {
|
_other => {
|
||||||
|
dbg!(_other);
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
|
}
|
||||||
current_function.push_statement(statement);
|
(statements, i)
|
||||||
|
|
||||||
return ParseState::Statement(current_function);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ast(tokens: Vec<Token>) -> Vec<Function> {
|
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 functions: Vec<Function> = Vec::new();
|
||||||
|
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
while i < tokens.len() {
|
while i < tokens.len() {
|
||||||
parse_state = match &parse_state {
|
|
||||||
ParseState::None(funcs) => {
|
|
||||||
functions = funcs.to_owned();
|
|
||||||
// Expect function and shit
|
|
||||||
match &tokens[i] {
|
match &tokens[i] {
|
||||||
Token::Keyword(keyword) => match keyword {
|
Token::Keyword(Keyword::Function) => {
|
||||||
Keyword::Function => {
|
let (statements, added_to_i) = parse_statements(&tokens, i + 4);
|
||||||
ParseState::Function(Function::new("".to_string(), Vec::new()))
|
let statements = vec![Statement::Scope(statements)];
|
||||||
}
|
let function_name = match &tokens[i + 1] {
|
||||||
|
Token::Identifier(identifier) => identifier.to_owned(),
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
},
|
};
|
||||||
|
let n_args = match &tokens[i + 2] {
|
||||||
|
Token::Number(num) => num.parse::<u64>().unwrap(),
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
|
};
|
||||||
|
i += added_to_i;
|
||||||
|
functions.push(Function::new(function_name, n_args, statements));
|
||||||
}
|
}
|
||||||
}
|
_other => {
|
||||||
ParseState::Function(func) => match &tokens[i] {
|
dbg!(&functions);
|
||||||
Token::Identifier(identifier) => {
|
dbg!(i);
|
||||||
ParseState::Function(Function::new(identifier.to_owned(), Vec::new()))
|
dbg!(_other);
|
||||||
}
|
todo!();
|
||||||
Token::OpenSquiglyBracket => ParseState::Statement(func.to_owned()),
|
|
||||||
_ => todo!(),
|
|
||||||
},
|
|
||||||
ParseState::Statement(_function) => {
|
|
||||||
parse_statement(&mut parse_state, &mut i, &tokens, &functions)
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
match parse_state {
|
functions
|
||||||
ParseState::None(v) => v,
|
|
||||||
_ => todo!(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ pub enum Keyword {
|
||||||
Function,
|
Function,
|
||||||
Let,
|
Let,
|
||||||
Assign,
|
Assign,
|
||||||
|
If,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum TokenFinishedUnfinished {
|
enum TokenFinishedUnfinished {
|
||||||
|
@ -39,6 +40,7 @@ fn generate_keyword_map() -> HashMap<String, Keyword> {
|
||||||
keywords.insert("fn".to_string(), K::Function);
|
keywords.insert("fn".to_string(), K::Function);
|
||||||
keywords.insert("let".to_string(), K::Let);
|
keywords.insert("let".to_string(), K::Let);
|
||||||
keywords.insert("assign".to_string(), K::Assign);
|
keywords.insert("assign".to_string(), K::Assign);
|
||||||
|
keywords.insert("if".to_string(), K::If);
|
||||||
|
|
||||||
keywords
|
keywords
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue