Compare commits
	
		
			No commits in common. "33162fda6e581ba67d2f4baca9426b9919bda64b" and "9c9a4cab1c2cb3e5bf84de2570f8110f7cd74a25" have entirely different histories.
		
	
	
		
			33162fda6e
			...
			9c9a4cab1c
		
	
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							|  | @ -1,2 +1 @@ | ||||||
| /target | /target | ||||||
| Cargo.lock |  | ||||||
|  |  | ||||||
							
								
								
									
										92
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,92 @@ | ||||||
|  | # This file is automatically @generated by Cargo. | ||||||
|  | # It is not intended for manual editing. | ||||||
|  | version = 3 | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "libc" | ||||||
|  | version = "0.2.147" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "plonkus" | ||||||
|  | version = "0.1.0" | ||||||
|  | dependencies = [ | ||||||
|  |  "socket2", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "socket2" | ||||||
|  | version = "0.5.3" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877" | ||||||
|  | dependencies = [ | ||||||
|  |  "libc", | ||||||
|  |  "windows-sys", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "windows-sys" | ||||||
|  | version = "0.48.0" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" | ||||||
|  | dependencies = [ | ||||||
|  |  "windows-targets", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "windows-targets" | ||||||
|  | version = "0.48.5" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" | ||||||
|  | dependencies = [ | ||||||
|  |  "windows_aarch64_gnullvm", | ||||||
|  |  "windows_aarch64_msvc", | ||||||
|  |  "windows_i686_gnu", | ||||||
|  |  "windows_i686_msvc", | ||||||
|  |  "windows_x86_64_gnu", | ||||||
|  |  "windows_x86_64_gnullvm", | ||||||
|  |  "windows_x86_64_msvc", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "windows_aarch64_gnullvm" | ||||||
|  | version = "0.48.5" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "windows_aarch64_msvc" | ||||||
|  | version = "0.48.5" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "windows_i686_gnu" | ||||||
|  | version = "0.48.5" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "windows_i686_msvc" | ||||||
|  | version = "0.48.5" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "windows_x86_64_gnu" | ||||||
|  | version = "0.48.5" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "windows_x86_64_gnullvm" | ||||||
|  | version = "0.48.5" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "windows_x86_64_msvc" | ||||||
|  | version = "0.48.5" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" | ||||||
|  | @ -6,4 +6,4 @@ edition = "2021" | ||||||
| # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||||||
| 
 | 
 | ||||||
| [dependencies] | [dependencies] | ||||||
| rand = "0.8.5" | socket2 = "0.5.3" | ||||||
|  |  | ||||||
							
								
								
									
										11
									
								
								src/assembly.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/assembly.rs
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,11 @@ | ||||||
|  | use crate::tokeniser::Token; | ||||||
|  | 
 | ||||||
|  | pub fn assemblize(tokens: Vec<Token>) -> String { | ||||||
|  |     let mut output = String::new(); | ||||||
|  | 
 | ||||||
|  |     for token in tokens { | ||||||
|  |         output += "hii" | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     output | ||||||
|  | } | ||||||
							
								
								
									
										357
									
								
								src/ast.rs
									
									
									
									
									
								
							
							
						
						
									
										357
									
								
								src/ast.rs
									
									
									
									
									
								
							|  | @ -1,357 +0,0 @@ | ||||||
| extern crate rand; |  | ||||||
| 
 |  | ||||||
| use rand::{distributions::Alphanumeric, Rng}; |  | ||||||
| use std::collections::HashMap; |  | ||||||
| 
 |  | ||||||
| #[derive(Debug, Clone)] |  | ||||||
| pub struct Function { |  | ||||||
|     pub name: String, |  | ||||||
|     pub statements: Vec<Statement>, |  | ||||||
|     assembly: Option<String>, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #[derive(Debug, Clone)] |  | ||||||
| pub enum Statement { |  | ||||||
|     FunctionCall(String, Vec<ValueNode>), |  | ||||||
|     VariableDeclaration(String, ValueNode), |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #[derive(Debug, Clone)] |  | ||||||
| pub enum ValueNode { |  | ||||||
|     Literal(Literal), |  | ||||||
|     Operator(Operator), |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #[derive(Debug, Clone)] |  | ||||||
| pub enum Literal { |  | ||||||
|     Int(i64), |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #[derive(Debug, Clone)] |  | ||||||
| pub enum Operator { |  | ||||||
|     Add(Box<ValueNode>, Box<ValueNode>), |  | ||||||
|     Sub(Box<ValueNode>, Box<ValueNode>), |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #[derive(Debug, Clone)] |  | ||||||
| pub struct AssemblerState { |  | ||||||
|     pub functions: HashMap<String, Function>, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| pub trait Node { |  | ||||||
|     fn to_assembly(&self, state: &mut AssemblerState) -> String; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl Function { |  | ||||||
|     pub fn new(name: String, statements: Vec<Statement>) -> Function { |  | ||||||
|         Function { |  | ||||||
|             name, |  | ||||||
|             statements, |  | ||||||
|             assembly: None, |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     pub fn add(&self, state: &mut AssemblerState) -> Function { |  | ||||||
|         state.functions.insert(self.name.clone(), self.to_owned()); |  | ||||||
|         self.to_owned() |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl AssemblerState { |  | ||||||
|     pub fn new() -> AssemblerState { |  | ||||||
|         AssemblerState { |  | ||||||
|             functions: get_default_functions(), |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fn get_default_functions() -> HashMap<String, Function> { |  | ||||||
|     let mut functions = HashMap::new(); |  | ||||||
|     functions.insert( |  | ||||||
|         "out".to_string(), |  | ||||||
|         Function { |  | ||||||
|             name: "exit".to_string(), |  | ||||||
|             statements: vec![], |  | ||||||
|             assembly: Some( |  | ||||||
|                 " |  | ||||||
| out: |  | ||||||
| ; |  | ||||||
| ; Pop the argument of the stack |  | ||||||
| ; |  | ||||||
| 
 |  | ||||||
| SE-OUT  RAM-ADDR-U-IN 0xFF ; Set ram address to stack end |  | ||||||
| RAM-OUT OUTPUT-IN     0xFF ; Output top address onto output register |  | ||||||
| 
 |  | ||||||
| ROM-OUT FLAGS-IN      0x80 ; Subtract mode |  | ||||||
| SE-OUT  A-IN          0xFF ; Fetch SE |  | ||||||
| ROM-OUT B-IN          0x01 ; Subtract one |  | ||||||
| ALU-OUT SE-IN         0xFF ; Store in SE |  | ||||||
| ROM-OUT FLAGS-IN      0x00 ; Add mode |  | ||||||
| 
 |  | ||||||
| ; |  | ||||||
| ; Pop the return address of the stack |  | ||||||
| ; |  | ||||||
| 
 |  | ||||||
| SE-OUT  RAM-ADDR-U-IN 0xFF ; Set ram address to stack end |  | ||||||
| RAM-OUT ROM-ADDR-U-IN 0xFF ; Store top address in ROM jump address |  | ||||||
| 
 |  | ||||||
| ROM-OUT FLAGS-IN      0x80 ; Subtract mode |  | ||||||
| SE-OUT  A-IN          0xFF ; Fetch SE |  | ||||||
| ROM-OUT B-IN          0x01 ; Subtract one |  | ||||||
| ALU-OUT SE-IN         0xFF ; Store in SE |  | ||||||
| ROM-OUT FLAGS-IN      0x00 ; Add mode |  | ||||||
| 
 |  | ||||||
| F-OUT   JMP           0xFF" |  | ||||||
|                     .to_string(), |  | ||||||
|             ), |  | ||||||
|         }, |  | ||||||
|     ); |  | ||||||
|     functions.insert( |  | ||||||
|         "exit".to_string(), |  | ||||||
|         Function { |  | ||||||
|             name: "exit".to_string(), |  | ||||||
|             statements: vec![], |  | ||||||
|             assembly: Some( |  | ||||||
|                 " |  | ||||||
| exit: |  | ||||||
| F-OUT JMP 0xFF" |  | ||||||
|                     .to_string(), |  | ||||||
|             ), |  | ||||||
|         }, |  | ||||||
|     ); |  | ||||||
|     functions |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl Node for Function { |  | ||||||
|     fn to_assembly(&self, state: &mut AssemblerState) -> String { |  | ||||||
|         match &self.assembly { |  | ||||||
|             Some(v) => v.to_string(), |  | ||||||
|             None => format!( |  | ||||||
|                 "{}:\n{}
 |  | ||||||
| ; |  | ||||||
| ; Pop the return address of the stack |  | ||||||
| ; |  | ||||||
| 
 |  | ||||||
| SE-OUT  RAM-ADDR-U-IN 0xFF ; Set ram address to stack end |  | ||||||
| RAM-OUT ROM-ADDR-U-IN 0xFF ; Store top address in ROM jump address |  | ||||||
| 
 |  | ||||||
| ROM-OUT FLAGS-IN      0x80 ; Subtract mode |  | ||||||
| SE-OUT  A-IN          0xFF ; Fetch SE |  | ||||||
| ROM-OUT B-IN          0x01 ; Subtract one |  | ||||||
| ALU-OUT SE-IN         0xFF ; Store in SE |  | ||||||
| ROM-OUT FLAGS-IN      0x00 ; Add mode |  | ||||||
| 
 |  | ||||||
| F-OUT   JMP           0xFF |  | ||||||
| ",
 |  | ||||||
|                 self.name, |  | ||||||
|                 { |  | ||||||
|                     self.statements |  | ||||||
|                         .iter() |  | ||||||
|                         .map(|x| x.to_assembly(state)) |  | ||||||
|                         .collect::<Vec<String>>() |  | ||||||
|                         .join("\n") |  | ||||||
|                 } |  | ||||||
|             ), |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl Node for Statement { |  | ||||||
|     fn to_assembly(&self, state: &mut AssemblerState) -> String { |  | ||||||
|         match self { |  | ||||||
|             Statement::FunctionCall(name, arguments) => { |  | ||||||
|                 if !state.functions.contains_key(name) { |  | ||||||
|                     todo!() |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 let argument_assembly: String = arguments |  | ||||||
|                     .into_iter() |  | ||||||
|                     .map(|x| x.to_assembly(state)) |  | ||||||
|                     .collect::<Vec<String>>() |  | ||||||
|                     .join("\n"); |  | ||||||
| 
 |  | ||||||
|                 let call_id: String = rand::thread_rng() |  | ||||||
|                     .sample_iter(&Alphanumeric) |  | ||||||
|                     .take(30) |  | ||||||
|                     .map(char::from) |  | ||||||
|                     .collect(); |  | ||||||
| 
 |  | ||||||
|                 format!( |  | ||||||
|                     " |  | ||||||
| ; |  | ||||||
| ; Stack |  | ||||||
| ; |  | ||||||
| 
 |  | ||||||
| ; Increment Stack Pointer |  | ||||||
| 
 |  | ||||||
| SE-OUT  A-IN  0xFF ; Fetch SE |  | ||||||
| ROM-OUT B-IN  0x01 ; Add 1 |  | ||||||
| ALU-OUT SE-IN 0xFF ; Store |  | ||||||
| 
 |  | ||||||
| ; Store in top stack pointer |  | ||||||
| 
 |  | ||||||
| ALU-OUT RAM-ADDR-U-IN 0xFF ; Store in RAM address |  | ||||||
| ROM-OUT RAM-IN        ${name}-{call_id}  ; Store address after jump in ram |  | ||||||
| 
 |  | ||||||
| ; |  | ||||||
| ; Arguments |  | ||||||
| ; 
 |  | ||||||
| 
 |  | ||||||
| {argument_assembly} |  | ||||||
| 
 |  | ||||||
| ; |  | ||||||
| ; Jump |  | ||||||
| ; |  | ||||||
| ROM-OUT ROM-ADDR-U-IN ${name}  ; Jump to function label |  | ||||||
| F-OUT   JMP           0xFF ; Jump to function |  | ||||||
| 
 |  | ||||||
| {name}-{call_id}: |  | ||||||
| " |  | ||||||
|                 ) |  | ||||||
|             } |  | ||||||
|             Statement::VariableDeclaration(_name, _value) => { |  | ||||||
|                 todo!() |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl Node for ValueNode { |  | ||||||
|     fn to_assembly(&self, state: &mut AssemblerState) -> String { |  | ||||||
|         match self { |  | ||||||
|             ValueNode::Literal(v) => v.to_assembly(state), |  | ||||||
|             ValueNode::Operator(o) => o.to_assembly(state), |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl Node for Literal { |  | ||||||
|     fn to_assembly(&self, _state: &mut AssemblerState) -> String { |  | ||||||
|         match self { |  | ||||||
|             Literal::Int(v) => { |  | ||||||
|                 format!( |  | ||||||
|                     " |  | ||||||
| ; |  | ||||||
| ; Stack |  | ||||||
| ; |  | ||||||
| 
 |  | ||||||
| ; Increment Stack Pointer |  | ||||||
| 
 |  | ||||||
| SE-OUT  A-IN  0xFF ; Fetch SE |  | ||||||
| ROM-OUT B-IN  0x01 ; Add 1 |  | ||||||
| ALU-OUT SE-IN 0xFF ; Store |  | ||||||
| 
 |  | ||||||
| ; Store in top stack pointer |  | ||||||
| 
 |  | ||||||
| ALU-OUT RAM-ADDR-U-IN 0xFF ; Store in RAM address |  | ||||||
| ROM-OUT RAM-IN        {v}; Store literal value in RAM" |  | ||||||
|                 ) |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl Node for Operator { |  | ||||||
|     fn to_assembly(&self, state: &mut AssemblerState) -> String { |  | ||||||
|         match self { |  | ||||||
|             Operator::Add(a, b) => { |  | ||||||
|                 format!( |  | ||||||
|                     " |  | ||||||
| {} |  | ||||||
| {} |  | ||||||
| 
 |  | ||||||
| SE-OUT  RAM-ADDR-U-IN 0xFF ; Set ram address to stack end |  | ||||||
| RAM-OUT C-IN          0xFF ; Output top address onto output register |  | ||||||
| 
 |  | ||||||
| ROM-OUT FLAGS-IN      0x80 ; Subtract mode |  | ||||||
| SE-OUT  A-IN          0xFF ; Fetch SE |  | ||||||
| ROM-OUT B-IN          0x01 ; Subtract one |  | ||||||
| ALU-OUT SE-IN         0xFF ; Store in SE |  | ||||||
| 
 |  | ||||||
| SE-OUT  RAM-ADDR-U-IN 0xFF ; Set ram address to stack end |  | ||||||
| RAM-OUT D-IN          0xFF ; Output top address onto output register |  | ||||||
| 
 |  | ||||||
| ROM-OUT FLAGS-IN      0x80 ; Subtract mode |  | ||||||
| SE-OUT  A-IN          0xFF ; Fetch SE |  | ||||||
| ROM-OUT B-IN          0x01 ; Subtract one |  | ||||||
| ALU-OUT SE-IN         0xFF ; Store in SE |  | ||||||
| ROM-OUT FLAGS-IN      0x00 ; Add mode |  | ||||||
| 
 |  | ||||||
| C-OUT   A-IN          0xFF ; Move temporary values into a register for alu computation 
 |  | ||||||
| D-OUT   B-IN          0xFF ; Move temporary values into a register for alu computation 
 |  | ||||||
| ALU-OUT C-IN          0xFF ; Move ALU output into temporary register |  | ||||||
| 
 |  | ||||||
| SE-OUT  A-IN  0xFF ; Fetch SE |  | ||||||
| ROM-OUT B-IN  0x01 ; Add 1 |  | ||||||
| ALU-OUT SE-IN 0xFF ; Store |  | ||||||
| 
 |  | ||||||
| ALU-OUT RAM-ADDR-U-IN 0xFF ; Store in RAM address |  | ||||||
| C-OUT   RAM-IN        0xFF ; Store address after jump in ram |  | ||||||
| ",
 |  | ||||||
|                     a.to_assembly(state), |  | ||||||
|                     b.to_assembly(state) |  | ||||||
|                 ) |  | ||||||
|             } |  | ||||||
|             Operator::Sub(a, b) => { |  | ||||||
|                 format!( |  | ||||||
|                     " |  | ||||||
| {} |  | ||||||
| {} |  | ||||||
| 
 |  | ||||||
| SE-OUT  RAM-ADDR-U-IN 0xFF ; Set ram address to stack end |  | ||||||
| RAM-OUT C-IN          0xFF ; Output top address onto output register |  | ||||||
| 
 |  | ||||||
| ROM-OUT FLAGS-IN      0x80 ; Subtract mode |  | ||||||
| SE-OUT  A-IN          0xFF ; Fetch SE |  | ||||||
| ROM-OUT B-IN          0x01 ; Subtract one |  | ||||||
| ALU-OUT SE-IN         0xFF ; Store in SE |  | ||||||
| 
 |  | ||||||
| SE-OUT  RAM-ADDR-U-IN 0xFF ; Set ram address to stack end |  | ||||||
| RAM-OUT D-IN          0xFF ; Output top address onto output register |  | ||||||
| 
 |  | ||||||
| ROM-OUT FLAGS-IN      0x80 ; Subtract mode |  | ||||||
| SE-OUT  A-IN          0xFF ; Fetch SE |  | ||||||
| ROM-OUT B-IN          0x01 ; Subtract one |  | ||||||
| ALU-OUT SE-IN         0xFF ; Store in SE |  | ||||||
| ROM-OUT FLAGS-IN      0x00 ; Add mode |  | ||||||
| 
 |  | ||||||
| ROM-OUT FLAGS-IN      0x80 ; Subtract mode |  | ||||||
| C-OUT   B-IN          0xFF ; Move temporary values into a register for alu computation 
 |  | ||||||
| D-OUT   A-IN          0xFF ; Move temporary values into a register for alu computation 
 |  | ||||||
| ALU-OUT C-IN          0xFF ; Move ALU output into temporary register |  | ||||||
| ROM-OUT FLAGS-IN      0x00 ; Add mode |  | ||||||
| 
 |  | ||||||
| SE-OUT  A-IN  0xFF ; Fetch SE |  | ||||||
| ROM-OUT B-IN  0x01 ; Add 1 |  | ||||||
| ALU-OUT SE-IN 0xFF ; Store |  | ||||||
| 
 |  | ||||||
| ALU-OUT RAM-ADDR-U-IN 0xFF ; Store in RAM address |  | ||||||
| C-OUT   RAM-IN        0xFF ; Store address after jump in ram |  | ||||||
| ",
 |  | ||||||
|                     a.to_assembly(state), |  | ||||||
|                     b.to_assembly(state) |  | ||||||
|                 ) |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| pub fn to_assembly(functions: Vec<Function>) -> String { |  | ||||||
|     let mut final_product: String = "".to_owned(); |  | ||||||
|     let mut std_function_assembly = "".to_owned(); |  | ||||||
|     let mut state = AssemblerState::new(); |  | ||||||
| 
 |  | ||||||
|     for std_function in state.clone().functions { |  | ||||||
|         std_function_assembly += &std_function.1.to_assembly(&mut state); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     for standard_function in &functions { |  | ||||||
|         standard_function.add(&mut state); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     for standard_function in &functions { |  | ||||||
|         final_product += &standard_function.to_assembly(&mut state); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     final_product + &std_function_assembly |  | ||||||
| } |  | ||||||
							
								
								
									
										17
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								src/main.rs
									
									
									
									
									
								
							|  | @ -1,17 +1,12 @@ | ||||||
| mod ast; | mod assembly; | ||||||
| mod parse; |  | ||||||
| mod tokeniser; | mod tokeniser; | ||||||
| 
 | 
 | ||||||
| fn main() { | fn main() { | ||||||
|     let filename = "test.plonkus"; |     let filename = std::env::args().nth(1).expect("No filename argument"); | ||||||
|  |     let contents = | ||||||
|  |         std::fs::read_to_string(&filename).expect(&format!("No file named {}", &filename)); | ||||||
| 
 | 
 | ||||||
|     let contents = std::fs::read_to_string(filename).expect(&format!("No file named {}", filename)); |     let tokens = dbg!(tokeniser::tokenise(contents)); | ||||||
| 
 | 
 | ||||||
|     let tokens = tokeniser::tokenise(contents); |     let assembled = dbg!(assembly::assemblize(tokens)); | ||||||
| 
 |  | ||||||
|     let functions = parse::ast(tokens); |  | ||||||
| 
 |  | ||||||
|     let assembly = ast::to_assembly(functions); |  | ||||||
| 
 |  | ||||||
|     println!("{}", assembly); |  | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										199
									
								
								src/parse.rs
									
									
									
									
									
								
							
							
						
						
									
										199
									
								
								src/parse.rs
									
									
									
									
									
								
							|  | @ -1,199 +0,0 @@ | ||||||
| use std::collections::{HashMap, HashSet}; |  | ||||||
| 
 |  | ||||||
| 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])); |  | ||||||
| 
 |  | ||||||
|     let mut ordered_binops: Vec<Token> = Vec::new(); |  | ||||||
|     let mut ordered_binops_indexes: Vec<usize> = Vec::new(); |  | ||||||
| 
 |  | ||||||
|     if tokens.len() == 1 { |  | ||||||
|         return match &tokens[0] { |  | ||||||
|             Token::Number(n) => ValueNode::Literal(Literal::Int(n.parse::<i64>().unwrap())), |  | ||||||
|             _ => todo!(), |  | ||||||
|         }; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     for j in prioritizing_order.keys() { |  | ||||||
|         let mut i = 0; |  | ||||||
|         let current_order_binops = prioritizing_order.get(j).unwrap(); |  | ||||||
| 
 |  | ||||||
|         while i < tokens.len() { |  | ||||||
|             for binop in current_order_binops { |  | ||||||
|                 if &tokens[i] == binop { |  | ||||||
|                     ordered_binops.push(binop.to_owned()); |  | ||||||
|                     ordered_binops_indexes.push(i); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             i += 1; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     let binop = ordered_binops.pop().unwrap(); |  | ||||||
|     let binop_index = ordered_binops_indexes.pop().unwrap(); |  | ||||||
| 
 |  | ||||||
|     let mut a: Vec<Token> = Vec::new(); |  | ||||||
|     let mut b: Vec<Token> = Vec::new(); |  | ||||||
| 
 |  | ||||||
|     let mut i = 0; |  | ||||||
|     while i < tokens.len() { |  | ||||||
|         if i < binop_index { |  | ||||||
|             a.push(tokens[i].clone()); |  | ||||||
|         } |  | ||||||
|         if i > binop_index { |  | ||||||
|             b.push(tokens[i].clone()); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         i += 1; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return match binop { |  | ||||||
|         Token::Plus => ValueNode::Operator(Operator::Add( |  | ||||||
|             Box::new(parse_math(&a)), |  | ||||||
|             Box::new(parse_math(&b)), |  | ||||||
|         )), |  | ||||||
|         Token::Minus => ValueNode::Operator(Operator::Sub( |  | ||||||
|             Box::new(parse_math(&a)), |  | ||||||
|             Box::new(parse_math(&b)), |  | ||||||
|         )), |  | ||||||
|         _ => todo!(), |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 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!(), |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     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) => { |  | ||||||
|             *i += 1; |  | ||||||
|             let name = match tokens[*i].clone() { |  | ||||||
|                 Token::Identifier(identifier) => identifier, |  | ||||||
|                 _ => todo!(), |  | ||||||
|             }; |  | ||||||
| 
 |  | ||||||
|             *i += 1; |  | ||||||
|             match tokens[*i].clone() { |  | ||||||
|                 Token::Equals => {} |  | ||||||
|                 _ => todo!(), |  | ||||||
|             }; |  | ||||||
| 
 |  | ||||||
|             let mut declaration_tokens: Vec<Token> = Vec::new(); |  | ||||||
|             while tokens[*i] != Token::Semi { |  | ||||||
|                 *i += 1; |  | ||||||
|                 declaration_tokens.push(tokens[*i].clone()); |  | ||||||
|             } |  | ||||||
|             Statement::VariableDeclaration(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); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 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!(), |  | ||||||
|                     }, |  | ||||||
|                     _ => todo!(), |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             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) |  | ||||||
|             } |  | ||||||
|         }; |  | ||||||
| 
 |  | ||||||
|         i += 1; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     match parse_state { |  | ||||||
|         ParseState::None(v) => v, |  | ||||||
|         _ => todo!(), |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  | @ -1,29 +1,19 @@ | ||||||
| #[derive(Debug, Clone, PartialEq, Eq, Hash)] | #[derive(Debug, Clone)] | ||||||
| pub enum Token { | pub enum Token { | ||||||
|     Semi, |     SEMI, | ||||||
|     Equals, |     NUMBER(String), | ||||||
|     Comma, |     IDENTIFIER(String), | ||||||
|     Plus, |     KEYWORD(Keyword), | ||||||
|     Minus, |  | ||||||
|     Number(String), |  | ||||||
|     Identifier(String), |  | ||||||
|     Keyword(Keyword), |  | ||||||
|     OpenParanthesis, |  | ||||||
|     CloseParanthesis, |  | ||||||
|     OpenSquiglyBracket, |  | ||||||
|     CloseSquiglyBracket, |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Debug, Clone, PartialEq, Eq, Hash)] | #[derive(Debug, Clone)] | ||||||
| pub enum Keyword { | pub enum Keyword { | ||||||
|     Return, |     RETURN, | ||||||
|     Function, |  | ||||||
|     Let, |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| enum TokenFinishedUnfinished { | enum TokenFinishedUnfinished { | ||||||
|     Unfinished(Option<Token>), |     UNFINISHED(Option<Token>), | ||||||
|     Finished(Token), |     FINISHED(Token), | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| use std::collections::HashMap; | use std::collections::HashMap; | ||||||
|  | @ -34,9 +24,7 @@ fn generate_keyword_map() -> HashMap<String, Keyword> { | ||||||
|     let mut keywords: HashMap<String, Keyword> = HashMap::new(); |     let mut keywords: HashMap<String, Keyword> = HashMap::new(); | ||||||
| 
 | 
 | ||||||
|     use Keyword as K; |     use Keyword as K; | ||||||
|     keywords.insert("return".to_string(), K::Return); |     keywords.insert("return".to_string(), K::RETURN); | ||||||
|     keywords.insert("fn".to_string(), K::Function); |  | ||||||
|     keywords.insert("let".to_string(), K::Let); |  | ||||||
| 
 | 
 | ||||||
|     keywords |     keywords | ||||||
| } | } | ||||||
|  | @ -48,75 +36,46 @@ fn tokenise_current_character( | ||||||
|     let keywords = generate_keyword_map(); |     let keywords = generate_keyword_map(); | ||||||
| 
 | 
 | ||||||
|     match current_token_type { |     match current_token_type { | ||||||
|         Some(Token::Number(ref v)) => { |         Some(Token::NUMBER(ref v)) => { | ||||||
|             let mut current_characters = v.clone(); |             let mut current_characters = v.clone(); | ||||||
| 
 | 
 | ||||||
|             if current_character.is_digit(10) { |             if current_character.is_digit(10) { | ||||||
|                 current_characters.push(current_character); |                 current_characters.push(current_character); | ||||||
|                 return Unfinished(Some(Token::Number(current_characters))); |                 return UNFINISHED(Some(Token::NUMBER(current_characters))); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             Finished(Token::Number(current_characters)) |             FINISHED(Token::NUMBER(current_characters)) | ||||||
|         } |         } | ||||||
|         Some(Token::Identifier(ref v)) => { |         Some(Token::IDENTIFIER(ref v)) => { | ||||||
|             let mut current_characters = v.clone(); |             let mut current_characters = v.clone(); | ||||||
| 
 | 
 | ||||||
|             if current_character.is_alphanumeric() { |             if current_character.is_alphanumeric() { | ||||||
|                 current_characters.push(current_character); |                 current_characters.push(current_character); | ||||||
|                 return Unfinished(Some(Token::Identifier(current_characters))); |                 return UNFINISHED(Some(Token::IDENTIFIER(current_characters))); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             match keywords.get(¤t_characters) { |             match keywords.get(¤t_characters) { | ||||||
|                 Some(keyword) => Finished(Token::Keyword(keyword.clone())), |                 Some(keyword) => FINISHED(Token::KEYWORD(keyword.clone())), | ||||||
|                 None => Finished(Token::Identifier(current_characters)), |                 None => FINISHED(Token::IDENTIFIER(current_characters)), | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |         Some(Token::SEMI) => FINISHED(Token::SEMI), // Needed because we're always going back a step after returning finished token
 | ||||||
|         None => { |         None => { | ||||||
|             if current_character.is_digit(10) { |             if current_character.is_digit(10) { | ||||||
|                 return Unfinished(Some(Token::Number(String::from(current_character)))); |                 return UNFINISHED(Some(Token::NUMBER(String::from(current_character)))); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if current_character.is_alphabetic() { |             if current_character.is_alphabetic() { | ||||||
|                 return Unfinished(Some(Token::Identifier(String::from(current_character)))); |                 return UNFINISHED(Some(Token::IDENTIFIER(String::from(current_character)))); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if current_character == ';' { |             if current_character == ';' { | ||||||
|                 return Unfinished(Some(Token::Semi)); |                 return UNFINISHED(Some(Token::SEMI)); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if current_character == '(' { |             UNFINISHED(None) | ||||||
|                 return Unfinished(Some(Token::OpenParanthesis)); |  | ||||||
|         } |         } | ||||||
|             if current_character == ')' { |         Some(v) => FINISHED(v), | ||||||
|                 return Unfinished(Some(Token::CloseParanthesis)); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             if current_character == '{' { |  | ||||||
|                 return Unfinished(Some(Token::OpenSquiglyBracket)); |  | ||||||
|             } |  | ||||||
|             if current_character == '}' { |  | ||||||
|                 return Unfinished(Some(Token::CloseSquiglyBracket)); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             if current_character == '=' { |  | ||||||
|                 return Unfinished(Some(Token::Equals)); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             if current_character == ',' { |  | ||||||
|                 return Unfinished(Some(Token::Comma)); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             if current_character == '+' { |  | ||||||
|                 return Unfinished(Some(Token::Plus)); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             if current_character == '-' { |  | ||||||
|                 return Unfinished(Some(Token::Minus)); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             Unfinished(None) |  | ||||||
|         } |  | ||||||
|         Some(v) => Finished(v), |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -131,10 +90,10 @@ pub fn tokenise(input: String) -> Vec<Token> { | ||||||
|         current_character = input.as_bytes()[i] as char; |         current_character = input.as_bytes()[i] as char; | ||||||
| 
 | 
 | ||||||
|         match tokenise_current_character(current_character, current_token_type.clone()) { |         match tokenise_current_character(current_character, current_token_type.clone()) { | ||||||
|             Unfinished(v) => { |             UNFINISHED(v) => { | ||||||
|                 current_token_type = v.clone(); |                 current_token_type = v.clone(); | ||||||
|             } |             } | ||||||
|             Finished(v) => { |             FINISHED(v) => { | ||||||
|                 tokens.push(v); |                 tokens.push(v); | ||||||
|                 current_token_type = None; |                 current_token_type = None; | ||||||
|                 i -= 1; |                 i -= 1; | ||||||
|  |  | ||||||
|  | @ -1,4 +1 @@ | ||||||
| fn main { | return 42; | ||||||
|   out(42 - 3 - 1,); |  | ||||||
|   exit(,); |  | ||||||
| } |  | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue