From cb89bc0e9a26d6539111f82331996e142b94df9c Mon Sep 17 00:00:00 2001 From: Goren Barak Date: Tue, 28 Nov 2023 18:00:31 -0500 Subject: [PATCH] Made skylang more recursive. --- src/codegen/fasm.rs | 48 +++++++++++++++++++-------- src/parse/ast.rs | 80 +++++++++++++++++++++------------------------ src/parse/parse.rs | 2 +- 3 files changed, 72 insertions(+), 58 deletions(-) diff --git a/src/codegen/fasm.rs b/src/codegen/fasm.rs index 6f2f0a2..05ca253 100644 --- a/src/codegen/fasm.rs +++ b/src/codegen/fasm.rs @@ -1,4 +1,5 @@ use crate::parse::ast::*; +use std::rc::Rc; #[macro_export] macro_rules! fasm_codegen { @@ -27,6 +28,13 @@ pub fn fasm_codegen(exprs: &Vec, not_a_function: bool) -> String { // 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());- + } + } + + // If not_a_function, push necessary headers to the asm_start variable. if not_a_function { asm_start.push_str("format ELF64 executable 3\n"); @@ -42,8 +50,10 @@ pub fn fasm_codegen(exprs: &Vec, not_a_function: bool) -> String { match expr { // If the expression is a math expression. Expr::MathExpr(e) => { - asm_start.push_str(format!("\tmov r10, {}\n", e.left.unwrap()).as_str()); - asm_start.push_str(format!("\tmov r11, {}\n", e.right.unwrap()).as_str()); + 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()); match e.operator { // If the operator is addition. MathOperator::OP_ADD => { @@ -91,43 +101,51 @@ pub fn fasm_codegen(exprs: &Vec, not_a_function: bool) -> String { for (i, p) in e.params.iter().enumerate() { match i { 0 => { - // First parameter. Put in %rdi.← asm_start.push_str(format!("\tmov rdi, {}\n", p.unwrap()).as_str()); + // First parameter. Put in %rdi. + unwrap!(p); + asm_start.push_str(format!("\tmov rdi, rax\n").as_str()); // rdi ← e.params[0]; }, 1 => { // Second parameter. Put in %rsi. - asm_start.push_str(format!("\tmov rsi, {}\n", p.unwrap()).as_str()); + unwrap!(p); + asm_start.push_str(format!("\tmov rsi, rax\n").as_str()); // rsi ← e.params[1]; }, - 2 => { + 2 => { // Third parameter. Put in %rdx. - asm_start.push_str(format!("\tmov rdx, {}\n", p.unwrap()).as_str()); + unwrap!(p); + asm_start.push_str(format!("\tmov rdx, rax\n").as_str()); // rdx ← e.params[2]; }, 3 => { // Fourth parameter. Put in %rcx. - asm_start.push_str(format!("\tmov rcx, {}\n", p.unwrap()).as_str()); + unwrap!(p); + asm_start.push_str(format!("\tmov rcx, rax\n").as_str()); // rcx ← e.params[3]; }, 4 => { // Fifth parameter. Put in %r8. - asm_start.push_str(format!("\tmov r8, {}\n", p.unwrap()).as_str()); + unwrap!(p); + asm_start.push_str(format!("\tmov r8, rax").as_str()); // r8 ← e.params[4]; }, 5 => { // Sixth parameter. Put in %r9. - asm_start.push_str(format!("\tmov r9, {}\n", p.unwrap()).as_str()); + unwrap!(p); + asm_start.push_str(format!("\tmov r9, rax\n").as_str()); // r9 ← e.params[5]; }, _ => { // Parameters after the sixth parameter are pushed to the stack. - asm_start.push_str(format!("\tpush {}\n", p.unwrap()).as_str()); + unwrap!(p); + asm_start.push_str(format!("\tpush rax\n").as_str()); // STACK_TOP ← e.params[(6+)]; } } @@ -138,9 +156,10 @@ pub fn fasm_codegen(exprs: &Vec, not_a_function: bool) -> String { }, // Define a global variable. - Expr::VarDefinition(e) => { - // Define a 64-bit variable. - asm_data.push_str(format!("\t{} dq {}", e.name, e.value.unwrap()).as_str()); + Expr::GlobalDefinition(e) => { + // Define a 64-bit global variable. + + asm_data.push_str(format!("\t{} dq {}", e.name, e.value).as_str()); }, // Breakpoint. @@ -173,7 +192,8 @@ pub fn fasm_codegen(exprs: &Vec, not_a_function: bool) -> String { // Increment the temporary variable/function counter. tmp_counter += 1; // Compare the left and right value. - asm_start.push_str(format!("\tcmp {}, {}\n", e.left.unwrap(), e.right.unwrap()).as_str()); + + asm_start.push_str(format!("\tcmp rax, {}\n", e.left, e.right.unwrap()).as_str()); // Check what the condition is. match e.cond { COND_OP::EQ => { diff --git a/src/parse/ast.rs b/src/parse/ast.rs index 3dbb355..c792afc 100644 --- a/src/parse/ast.rs +++ b/src/parse/ast.rs @@ -4,11 +4,14 @@ use std::rc::Rc; pub enum Expr<'a> { MathExpr(Math<'a>), FunCall(FunCall<'a>), - FunDefinition(FunDefinition<'a>), - VarDefinition(VarDefinition<'a>), + FunDefinition(Rc>), + GlobalDefinition(Rc>), Return(Vec>), - If(IfCondition<'a>), - + If(Rc>), + Var(VarReference<'a>), + Param(ParamReference), + Number(u64), + Breakpoint } @@ -16,8 +19,8 @@ pub enum Expr<'a> { #[derive(Debug, Clone)] pub struct Math<'a> { - pub left: Rc>, - pub right: Rc>, + pub left: Rc>, + pub right: Rc>, pub operator: MathOperator } @@ -35,7 +38,7 @@ pub enum MathOperator { #[derive(Debug)] pub struct FunCall<'a> { pub name: &'a str, - pub params: Vec>, + pub params: Vec>>, } #[derive(Debug)] @@ -52,7 +55,7 @@ pub struct FunParamDef<'a> { #[derive(Debug)] pub struct FunParamCall<'a> { - pub value: Value<'a>, + pub value: Expr<'a>, } // VARIABLES @@ -60,7 +63,7 @@ pub struct FunParamCall<'a> { #[derive(Debug)] pub struct VarDefinition<'a> { pub name: &'a str, - pub value: Value<'a>, + pub value: u64, } @@ -78,8 +81,8 @@ pub struct ParamReference { #[derive(Debug)] pub struct IfCondition<'a> { - pub left: Value<'a>, - pub right: Value<'a>, + pub left: Expr<'a>, + pub right: Expr<'a>, pub cond: COND_OP, pub action: Vec> } @@ -91,37 +94,28 @@ pub enum COND_OP { } // VALUE - -#[derive(Debug, Copy, Clone)] -pub enum Value<'a> { - Var(VarReference<'a>), - Param(ParamReference), - Number(u64), -} - - -impl<'a> Value<'a> { - pub fn unwrap(&self) -> String { - match self { - Value::Param(e) => { - match e.param_number { - 0 => { return "rdi".to_string(); }, - 1 => { return "rsi".to_string(); }, - 2 => { return "rdx".to_string(); }, - 3 => { return "rcx".to_string(); }, - 4 => { return "r8".to_string(); }, - 5 => { return "r9".to_string(); }, - _ => { unimplemented!() } - } - }, +// impl<'a> Value<'a> { +// pub fn unwrap(&self) -> String { +// match self { +// Value::Param(e) => { +// match e.param_number { +// 0 => { return "rdi".to_string(); }, +// 1 => { return "rsi".to_string(); }, +// 2 => { return "rdx".to_string(); }, +// 3 => { return "rcx".to_string(); }, +// 4 => { return "r8".to_string(); }, +// 5 => { return "r9".to_string(); }, +// _ => { unimplemented!() } +// } +// }, - Value::Number(e) => { - return e.to_string(); - }, +// Value::Number(e) => { +// return e.to_string(); +// }, - Value::Var(e) => { - return format!("[{}]", e.name.to_string()); - }, - } - } -} +// Value::Var(e) => { +// return format!("[{}]", e.name.to_string()); +// }, +// } +// } +// } diff --git a/src/parse/parse.rs b/src/parse/parse.rs index 15f0e44..99598e7 100644 --- a/src/parse/parse.rs +++ b/src/parse/parse.rs @@ -57,7 +57,7 @@ pub fn parse_var_declaration(mut tokens: Lexer) -> Option { tok } -pub fn parse_value<'a>(token: &(Option>, &'a str)) -> Option> { +pub fn parse_value<'a>(token: &(Option>, &'a str)) -> Option> { if let Some(Ok(tt)) = &token.0 { let mut value = None;