Still incredibly buggy, but i need to commit something to git.

I'm going to fix the problem soon trust me :3
This commit is contained in:
Goren Barak 2023-12-09 15:35:48 -05:00
parent fba9dded42
commit 7d7bac18c6
13 changed files with 118 additions and 320 deletions

View file

@ -1,19 +1,33 @@
use std::rc::Rc;
use crate::parse::ast::*;
use skylang::temp;
use std::rc::Rc;
const REGISTERS: [&str; 9] = ["r10", "r11", "r12", "r13", "r14", "r15", "rax", "rdi", "rsi"];
const REGISTERS: [&str; 9] = ["r10", "r11", "r12", "r13", "r14", "rsp", "rbp", "rdp", "rdi"];
#[derive(Debug)]
pub struct FasmCodegen {
register_counter: usize,
operation_queue: Vec<String>
operation_queue: Vec<OperationQueue>,
use_queue: bool,
}
#[derive(Debug)]
enum OperationQueue {
RegisterCounter(usize),
Instruction(String),
}
impl Default for FasmCodegen {
fn default() -> Self {
Self::new()
}
}
impl FasmCodegen {
pub fn new() -> Self {
FasmCodegen {
register_counter: 0,
operation_queue: Vec::new()
operation_queue: Vec::new(),
use_queue: false
}
}
@ -57,28 +71,45 @@ impl FasmCodegen {
match expr {
// If the expression is a math expression.
Expr::MathExpr(e) => {
if let Expr::MathExpr(m) = e.right.as_ref() {
let codegen = fasm_codegen!(fun: &vec![Expr::MathExpr(m.clone())]);
self.operation_queue.push(codegen);
if let Expr::MathExpr(_m) = e.right.as_ref() {
self.register_counter += 1;
self.operation_queue.push(OperationQueue::RegisterCounter(self.register_counter));
self.use_queue = true;
} else {
self.use_queue = false;
}
let mut register_counter = Box::new(self.register_counter);
if self.use_queue {
println!("self.use_queue");
if let Some(OperationQueue::RegisterCounter(q)) = self.operation_queue.pop() {
register_counter = Box::new(q);
}
}
dbg!(*register_counter, self.register_counter, self.use_queue);
unwrap!(e.left);
self.register_counter += 1;
asm_start.push_str(format!("\tmov {}, rax\n", REGISTERS[self.register_counter]).as_str());
dbg!(*register_counter, self.register_counter, self.use_queue);
asm_start.push_str(format!("\tmov {}, rax\n", REGISTERS[*register_counter]).as_str());
unwrap!(e.right);
self.register_counter += 1;
asm_start.push_str(format!("\tmov {}, rax\n", REGISTERS[self.register_counter]).as_str());
dbg!(*register_counter, self.register_counter, self.use_queue);
asm_start.push_str(format!("\tmov {}, rax\n", REGISTERS[*register_counter]).as_str());
self.register_counter += 1;
match e.operator {
// If the operator is addition.
MathOperator::OP_ADD => {
asm_start.push_str(format!("\tadd {}, {}\n", REGISTERS[self.register_counter - 1], REGISTERS[self.register_counter]).as_str());
asm_start.push_str(format!("\tmov rax, {}\n", REGISTERS[self.register_counter - 1]).as_str());
asm_start.push_str(format!("\tadd {}, {}\n", REGISTERS[*register_counter - 1], REGISTERS[*register_counter]).as_str());
asm_start.push_str(format!("\tmov rax, {}\n", REGISTERS[*register_counter - 1]).as_str());
// r10 ← r10 + r11; rax ← r10;
// The sum will now be stored in the %rax register.
},
// If the operator is multiplication.
MathOperator::OP_MULT => {
asm_start.push_str(format!("\timul {}, {}\n", REGISTERS[self.register_counter - 1], REGISTERS[self.register_counter]).as_str());
asm_start.push_str(format!("\tmov rax, {}\n", REGISTERS[self.register_counter - 1]).as_str());
asm_start.push_str(format!("\timul {}, {}\n", REGISTERS[*register_counter - 1], REGISTERS[*register_counter]).as_str());
asm_start.push_str(format!("\tmov rax, {}\n", REGISTERS[*register_counter - 1]).as_str());
// r10 ← r10 * r11; rax ← r10;
// The product will now be stored in the %rax register.
},
@ -94,6 +125,7 @@ impl FasmCodegen {
MathOperator::OP_SUB => {
asm_start.push_str("\tsub r10, r11\n");
asm_start.push_str("\tmov rax, r10\n");
// r10 ← r10 - r11; rax ← r10;
// The difference will now be stored in the %rax register.
},
@ -116,49 +148,49 @@ impl FasmCodegen {
0 => {
// First parameter. Put in %rdi.
unwrap!(p);
asm_start.push_str(format!("\tmov rdi, rax\n").as_str());
asm_start.push_str("\tmov rdi, rax\n".to_string().as_str());
// rdi ← e.params[0];
},
1 => {
// Second parameter. Put in %rsi.
unwrap!(p);
asm_start.push_str(format!("\tmov rsi, rax\n").as_str());
asm_start.push_str("\tmov rsi, rax\n".to_string().as_str());
// rsi ← e.params[1];
},
2 => {
// Third parameter. Put in %rdx.
unwrap!(p);
asm_start.push_str(format!("\tmov rdx, rax\n").as_str());
asm_start.push_str("\tmov rdx, rax\n".to_string().as_str());
// rdx ← e.params[2];
},
3 => {
// Fourth parameter. Put in %rcx.
unwrap!(p);
asm_start.push_str(format!("\tmov rcx, rax\n").as_str());
asm_start.push_str("\tmov rcx, rax\n".to_string().as_str());
// rcx ← e.params[3];
},
4 => {
// Fifth parameter. Put in %r8.
unwrap!(p);
asm_start.push_str(format!("\tmov r8, rax").as_str());
asm_start.push_str("\tmov r8, rax".to_string().as_str());
// r8 ← e.params[4];
},
5 => {
// Sixth parameter. Put in %r9.
unwrap!(p);
asm_start.push_str(format!("\tmov r9, rax\n").as_str());
asm_start.push_str("\tmov r9, rax\n".to_string().as_str());
// r9 ← e.params[5];
},
_ => {
// Parameters after the sixth parameter are pushed to the stack.
unwrap!(p);
asm_start.push_str(format!("\tpush rax\n").as_str());
asm_start.push_str("\tpush rax\n".to_string().as_str());
// STACK_TOP ← e.params[(6+)];
}
}
@ -206,7 +238,7 @@ impl FasmCodegen {
asm_start.push_str("mov rdi, rax");
unwrap!(e.right);
asm_start.push_str("mov rsi, rax");
asm_start.push_str(format!("\tcmp rdi, rsi\n").as_str());
asm_start.push_str("\tcmp rdi, rsi\n".to_string().as_str());
// Check what the condition is.
match e.cond {
COND_OP::EQ => {
@ -232,7 +264,7 @@ impl FasmCodegen {
no => unsafe {
// Write some data I randomly typed to your memory because don't going around playing with something that I haven't implemented yet.
println!("{:?} is not. implemented.", no);
let mut ptr = 0x00 as *mut f64;
let ptr = std::ptr::null_mut::<f64>();
::std::ptr::write(ptr, 124010240120401240.12410240124120401240);
},
}

View file

View file

View file

@ -1 +0,0 @@
pub mod tok;

View file

@ -1,149 +0,0 @@
#![allow(unused)]
use super::tok::*;
fn check_single_char<'a>(word: &'a str) -> Option<Token<'a>> {
macro_rules! tok {
($tt:expr) => {
Some(Token::new($tt, word))
};
};
let tok = match word {
";" => tok!(Semicolon),
"=" => tok!(Equal),
"(" => tok!(LeftParen),
")" => tok!(RightParen),
"{" => tok!(LeftBrace),
"}" => tok!(RightBrace),
"," => tok!(Comma),
"." => tok!(Dot),
"-" => tok!(Minus),
"+" => tok!(Plus),
"/" => tok!(Slash),
"*" => tok!(Star),
"%" => tok!(Percent),
"!" => tok!(Bang),
":" => tok!(Colon),
"<" => tok!(Less),
">" => tok!(Greater),
_ => None
};
tok
}
fn check_keyword<'a>(word: &'a str) -> Option<Token<'a>> {
macro_rules! tok {
($tt:expr) => {
Some(Token::new($tt, word))
};
};
let tok = match word {
"fn" => tok!(Fn),
"let" => tok!(Let),
"if" => tok!(If),
"else" => tok!(Else),
"while" => tok!(While),
"elif" => tok!(Elif),
"return" => tok!(Return),
"for" => tok!(For),
"in" => tok!(In),
"break" => tok!(Break),
"continue" => tok!(Continue),
"true" => tok!(True),
"false" => tok!(False),
_ => None
};
tok
}
fn check_two_char<'a>(word: &'a str) -> Option<Token<'a>> {
macro_rules! tok {
($tt:expr) => {
Some(Token::new($tt, word))
};
};
let tok = match word {
"==" => tok!(EqualEqual),
"!=" => tok!(BangEqual),
"<=" => tok!(LessEqual),
">=" => tok!(GreaterEqual),
_ => None
};
tok
}
fn match_string_literal<'a>(word: &'a str) -> Option<Token<'a>> {
macro_rules! tok {
($tt:expr) => {
Some(Token::new($tt, word))
};
};
let chars = word.chars();
if word.starts_with("\"") {
while let Some(char) = chars.next() {
if char == '\"' {
return tok!(String);
}
}
}
if word.starts_with("\'") {
while let Some(char) = chars.next() {
if char == '\'' {
return tok!(String);
}
}
}
None
}
fn match_int_literal<'a>(word: &'a str) -> Option<Token<'a>> {
macro_rules! tok {
($tt:expr) => {
Some(Token::new($tt, word))
};
};
let chars = word.chars();
while let Some(char) = chars.next() {
if char.is_digit(10) {
return tok!(Number);
} else {
return None;
}
}
None
}
fn match_identifier<'a>(word: &'a str) -> Option<Token<'a>> {
macro_rules! tok {
($tt:expr) => {
Some(Token::new($tt, word))
};
};
let chars = word.chars();
if chars.next().is_ascii_alphabetic() {
while let Some(char) = chars.next() {
if chars.next().is_ascii() {
}
}
}
}

View file

@ -106,3 +106,51 @@ pub fn lex_str(this: &str) -> Vec<(Token, &str)> {
buf
}
impl std::fmt::Display for Token {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Semicolon => write!(f, ";"),
Equal => write!(f, "="),
LeftParen => write!(f, "("),
RightParen => write!(f, ")"),
LeftBrace => write!(f, "{{"),
RightBrace => write!(f, "}}"),
Comma => write!(f, ","),
Dot => write!(f, "."),
Minus => write!(f, "-"),
Plus => write!(f, "+"),
Slash => write!(f, "/"),
Star => write!(f, "*"),
Percent => write!(f, "%"),
Bang => write!(f, "!"),
Colon => write!(f, ":"),
Less => write!(f, "<"),
Greater => write!(f, ">"),
Pipe => write!(f, "|"),
Fnaf => write!(f, "fnaf"),
Let => write!(f, "let"),
Global => write!(f, "global"),
If => write!(f, "if"),
Else => write!(f, "else"),
While => write!(f, "while"),
Elif => write!(f, "elif"),
Return => write!(f, "return"),
For => write!(f, "for"),
In => write!(f, "in"),
Break => write!(f, "break"),
Continue => write!(f, "continue"),
EqualEqual => write!(f, "=="),
BangEqual => write!(f, "!="),
LessEqual => write!(f, "<="),
GreaterEqual => write!(f, ">="),
String => write!(f, "[string]"),
Number(n) => write!(f, "{}", n),
Identifier => write!(f, "identifier"),
True => write!(f, "true"),
False => write!(f, "false"),
Null => write!(f, "none"),
}
}
}

View file

@ -1,124 +0,0 @@
#![allow(unused)]
pub use TokenType::*;
use super::parse::*;
#[derive(Debug)]
pub struct Token<'a> {
tt: TokenType,
word: &'a str,
}
#[derive(Debug)]
pub enum TokenType {
EOF,
// SINGLE CHARACTER TOKENS
Semicolon, // ;
Equal, // =
LeftParen, // (
RightParen, // )
LeftBrace, // {
RightBrace, // }
Comma, // ,
Dot, // .
Minus, // -
Plus, // +
Slash, // /
Star, // *
Percent, // %
Bang, // !
Colon, // :
Less, // <
Greater, // >
// KEYWORDS
Fn, // fn
Let, // let
If, // if
Else, // else
While, // while
Elif, // elif
Return, // return
For, // for
In, // in
Break, // break
Continue, // continue
// TWO CHARACTER TOKENS
EqualEqual, // ==
BangEqual, // !=
LessEqual, // <=
GreaterEqual, // >=
// LITERALS
String, // A string literal.
Number, // An integer.
Identifier, // An identifier.
True, // true
False, // false
Null, // None
// ERROR
Error, // A syntax error.
}
#[derive(Debug)]
pub struct Lexer<'a> {
source: &'a str,
tokens: Vec<Token<'a>>,
current: usize,
after: &'a str
}
impl<'a> Lexer<'a> {
pub fn new() -> Self {
Lexer {
source: "",
tokens: Vec::new(),
current: 0,
after: ""
}
}
}
impl<'a> std::iter::Iterator for Lexer<'a> {
}
impl<'a> From<&'a str> for Lexer<'a> {
fn from(value: &'a str) -> Self {
Lexer {
source: value,
tokens: Vec::new(),
current: 0,
after: value
}
}
}
impl<'a> From<&'a std::string::String> for Lexer<'a> {
fn from(value: &'a std::string::String) -> Self {
Lexer {
source: value.as_str(),
tokens: Vec::new(),
current: 0,
after: value.as_str()
}
}
}
impl<'a> Token<'a> {
pub fn new(tt: TokenType, word: &'a str) -> Self {
Token {
tt,
word
}
}
pub fn empty() -> Self {
Token {
tt: EOF,
word: ""
}
}
}

View file

@ -1,11 +1,9 @@
#![feature(associated_type_bounds)]
#![allow(warnings)]
pub mod lex;
pub mod codegen;
use crate::codegen::fasm::*;
use crate::lex::tok::*;
use crate::parse::ast::*;
use crate::parse::parse::*;
use logos::Logos;
@ -54,7 +52,7 @@ fn main() {
// println!("{}", fc);
let parsed = "3*10+5";
let mut lexer = Token::lexer(parsed);
let lexer = Token::lexer(parsed);
println!("\"{}\"", parsed);
arrow!(" ");
@ -63,6 +61,7 @@ fn main() {
let parsed = parse_math(lexer);
println!("{:?}", parsed);
arrow!(" ");
println!("{}", FasmCodegen::new().fasm_codegen(&vec![parsed.unwrap()], true));
let mut code = FasmCodegen::new();
println!("{}", code.fasm_codegen(&vec![parsed.unwrap()], true));
}

View file

@ -1,5 +0,0 @@
pub mod lex;
fn main() {
println!("{:?}", lex::parse::match_identifier("goren-"));
}

View file

View file

View file

@ -27,19 +27,17 @@ pub fn parse_math(mut tokens: Lexer<Token>) -> Option<Expr> {
pub fn parse_global_declaration(mut tokens: Lexer<Token>) -> Option<Expr> {
let mut tok = None;
if unwrap!(tokens) == Let {
if unwrap!(tokens) == Identifier {
let name = tokens.slice();
if unwrap!(tokens) == Let && unwrap!(tokens) == Identifier {
let name = tokens.slice();
println!("{:?}", name);
if unwrap!(tokens) == Equal {
let temp_token = unwrap!(tokens);
if let Number(n) = temp_token {
tok = Some(Expr::GlobalDefinition(Rc::new(VarDefinition {name, value: n})));
}
}
}
}
println!("{:?}", name);
if unwrap!(tokens) == Equal {
let temp_token = unwrap!(tokens);
if let Number(n) = temp_token {
tok = Some(Expr::GlobalDefinition(Rc::new(VarDefinition {name, value: n})));
}
}
}
tok
}

View file