Made the backend compile and be more recursive :3.

recursive
Goren Barak 2023-11-30 12:55:41 -05:00
parent db6d6a91a1
commit b4e60f09e5
5 changed files with 32 additions and 26 deletions

View File

@ -3,6 +3,9 @@ name = "skylang"
version = "0.1.0"
edition = "2021"
[lib]
proc-macro = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

View File

@ -1,5 +1,6 @@
use crate::parse::ast::*;
use std::rc::Rc;
use skylang::temp;
#[macro_export]
macro_rules! fasm_codegen {
@ -20,10 +21,9 @@ pub fn fasm_codegen(exprs: &Vec<Expr>, not_a_function: bool) -> String {
let mut asm_data = String::new();
// Define asm_start, used for the entry point.
let mut asm_start = String::new();
macro_rules! unwrap {
($item:expr) => {
asm_start.push_str(fasm_codegen!(fun: &vec![*$item.as_ref()]).as_str());
asm_start.push_str(fasm_codegen!(fun: &vec![$item.as_ref().clone()]).as_str());
}
}
@ -36,7 +36,7 @@ pub fn fasm_codegen(exprs: &Vec<Expr>, not_a_function: bool) -> String {
asm_start.push_str("_start:\n");
asm_data.push_str("\nsegment readable writable\n");
}
// Iterate over expressions.
for expr in exprs.iter() {
// Use patern matching on `expr`.
@ -46,7 +46,7 @@ pub fn fasm_codegen(exprs: &Vec<Expr>, not_a_function: bool) -> String {
unwrap!(e.left);
asm_start.push_str(format!("\tmov r10, rax\n").as_str());
unwrap!(e.right);
asm_start.push_str(format!("\tmov r11, rax").as_str());
asm_start.push_str(format!("\tmov r11, rax\n").as_str());
match e.operator {
// If the operator is addition.
MathOperator::OP_ADD => {
@ -181,31 +181,37 @@ pub fn fasm_codegen(exprs: &Vec<Expr>, not_a_function: bool) -> String {
Expr::If(e) => {
// Increment the temporary variable/function counter.
tmp_counter += 1;
// Compare the left and right value.
asm_start.push_str(format!("\tcmp rax, {}\n", e.left, e.right.unwrap()).as_str());
unwrap!(e.left);
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());
// Check what the condition is.
match e.cond {
COND_OP::EQ => {
// If the compared values are equal to each other jump to the temporary function.
asm_start.push_str(format!("je .{}", temp(tmp_counter)).as_str());
asm_start.push_str(format!("je .{}", temp!()).as_str());
},
COND_OP::NE => {
// If the compared values are not equal to eachother jump to the temporary function.
asm_start.push_str(format!("jne .{}", temp(tmp_counter)).as_str());
asm_start.push_str(format!("jne .{}", temp!()).as_str());
}
}
// Create the temporary function.
asm_func.push_str(format!(".{}:\n", temp(tmp_counter)).as_str());
asm_func.push_str(format!(".{}:\n", temp!()).as_str());
asm_func.push_str(fasm_codegen!(fun: &e.action).as_str());
asm_func.push_str("\tret\n");
}
_ => unsafe {
},
Expr::Number(n) => {
asm_func.push_str(format!("\tmov rax, {}\n", n).as_str())
},
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;
::std::ptr::write(ptr, 124010240120401240.12410240124120401240);
},

View File

@ -51,6 +51,8 @@ pub enum Token {
Fnaf, // fnaf
#[token("let")]
Let, // let
#[token("global")]
Global, // global
#[token("if")]
If, // if
#[token("else")]

View File

@ -1,6 +1,6 @@
use std::rc::Rc;
#[derive(Debug)]
#[derive(Debug, Clone)]
pub enum Expr<'a> {
MathExpr(Math<'a>),
FunCall(FunCall<'a>),
@ -35,7 +35,7 @@ pub enum MathOperator {
// FUNCTIONS
#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct FunCall<'a> {
pub name: &'a str,
pub params: Vec<Rc<Expr<'a>>>,
@ -81,8 +81,8 @@ pub struct ParamReference {
#[derive(Debug)]
pub struct IfCondition<'a> {
pub left: Expr<'a>,
pub right: Expr<'a>,
pub left: Rc<Expr<'a>>,
pub right: Rc<Expr<'a>>,
pub cond: COND_OP,
pub action: Vec<Expr<'a>>
}

View File

@ -34,7 +34,7 @@ pub fn parse_math(mut tokens: Lexer<Token>) -> Option<Expr> {
None
}
pub fn parse_var_declaration(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 {
@ -44,12 +44,7 @@ pub fn parse_var_declaration(mut tokens: Lexer<Token>) -> Option<Expr> {
if unwrap!(tokens) == Equal {
let temp_token = unwrap!(tokens);
if let Number(n) = temp_token {
let value = Value::Number(n);
println!("{:?}", value);
tok = Some(Expr::VarDefinition(VarDefinition {name, value}));
} else if temp_token == Identifier {
let value = Value::Var(VarReference { name: tokens.slice() });
tok = Some(Expr::VarDefinition(VarDefinition {name, value}));
tok = Some(Expr::GlobalDefinition(Rc::new(VarDefinition {name, value: n})));
}
}
}
@ -62,9 +57,9 @@ pub fn parse_value<'a>(token: &(Option<Result<Token, ()>>, &'a str)) -> Option<E
let mut value = None;
if let Number(n) = tt {
value = Some(Value::Number(*n));
value = Some(Expr::Number(*n));
} else if *tt == Identifier {
value = Some(Value::Var(VarReference { name: token.1 }));
value = Some(Expr::Var(VarReference { name: token.1 }));
}
value
@ -85,7 +80,7 @@ pub fn parse_fun_call(mut tokens: Lexer<Token>) -> Option<Expr> {
if unwrap!(tokens) == LeftParen {
let mut params = Vec::new();
while let Some(value) = parse_value!(tokens) {
params.push(value);
params.push(Rc::new(value));
}
tok = Some(Expr::FunCall(FunCall {name, params: params.clone()}));
}