From e33e43e221f4baff583c9a8ed4aeccfd5d24550b Mon Sep 17 00:00:00 2001 From: itycodes Date: Mon, 10 Mar 2025 06:41:21 +0100 Subject: [PATCH] Initial work on function compilation So far we only got constants and store-ptr. Not supported by the frontend yet, so far only in tests. --- src/compiler/backend/mod.rs | 115 ++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) diff --git a/src/compiler/backend/mod.rs b/src/compiler/backend/mod.rs index a53e767..5748cc0 100644 --- a/src/compiler/backend/mod.rs +++ b/src/compiler/backend/mod.rs @@ -7,6 +7,8 @@ use std::fmt::Write; use super::StorageClass; +use crate::parser::Ast; + #[derive(Debug, PartialEq, Clone)] pub enum Type { Pointer(Box, StorageClass), @@ -292,3 +294,116 @@ pub fn spirv_meta(module: Module) -> String { } spirv_asm } + +enum Number { + Int(i32), + Float(f32), + NotANumber, +} + +fn match_number(s: &str) -> Number { + // floats have to be in the format of [0-9]+\.[0-9]* + // integers have to be in the format of [0-9]+ + let mut chars = s.chars(); + let mut has_dot = false; + while let Some(c) = chars.next() { + if c == '.' { + if has_dot { + // only one dot allowed. + return Number::NotANumber; + } + has_dot = true; + } else if !c.is_digit(10) { + // not a number; + // has a character that is not a digit or a dot. + return Number::NotANumber; + } + } + if has_dot { + // we have checked that the whole thing is numbers and dots + // and that there is precisely one dot + // that matches the regex. + Number::Float(s.parse().unwrap()) + } else { + // this is an integer, since no dots. + Number::Int(s.parse().unwrap()) + } +} + +pub fn compile_ast_ssa( + ast: Ast, + vars: &mut Vec<(String, String)>, + mut constants: &mut Vec<(String, String)>, + mut counter: &mut Box, + mut stack: &mut Vec, + mut out: &mut Vec<(Option, String)>, +) { + match ast.clone().list() { + Some(l) => { + let mut lst = l.clone(); + assert!(!lst.is_empty()); + let fun = lst.remove(0); + assert!(true); // no safe remove, thanks Rust + let fun_name = fun.symbol(); + assert!(fun_name.is_some()); + let fun_name = fun_name.unwrap(); + match fun_name.as_str() { + "store-ptr" => { + assert!(lst.len() == 2); + let ptr = lst.pop().unwrap(); + let val = lst.pop().unwrap(); + compile_ast_ssa(ptr, vars, constants, counter, stack, out); + compile_ast_ssa(val, vars, constants, counter, stack, out); + let val_id = stack.pop().unwrap(); + let ptr_id = stack.pop().unwrap(); + out.push((None, format!("OpStore {} {}", fix_name(&val_id), fix_name(&ptr_id)))); + } + s => { + panic!("Unknown function: {} with params {:#?} in context:\n{:#?}", s, lst, ast); + } + } + } + None => { + let sym = ast.clone().symbol(); + assert!(sym.is_some()); + let sym = sym.unwrap(); + match match_number(&sym) { + Number::Int(i) => { + let key = format!("i32_{}", i); + let mut contains = false; + for c in constants.iter() { + if c.0 == key { + contains = true; + } + } + if contains { + constants.push((key.clone(), format!("OpConstant %i32 {}", i.to_string()))); + } + stack.push(key); + } + Number::Float(f) => { + let key = format!("f32_{}", f); + let mut contains = false; + for c in constants.iter() { + if c.0 == key { + contains = true; + } + } + if contains { + constants.push((key.clone(), format!("OpConstant %f32 {}", f.to_string()))); + } + stack.push(key); + } + Number::NotANumber => { + for v in vars.iter() { + if v.0 == sym { + stack.push(v.0.clone()); + return; + } + } + panic!("Unknown variable or constant: {}", sym); + } + } + } + } +}