|
|
|
@ -7,6 +7,8 @@ use std::fmt::Write;
|
|
|
|
|
|
|
|
|
|
use super::StorageClass;
|
|
|
|
|
|
|
|
|
|
use crate::parser::Ast;
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, PartialEq, Clone)]
|
|
|
|
|
pub enum Type {
|
|
|
|
|
Pointer(Box<Type>, 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<i32>,
|
|
|
|
|
mut stack: &mut Vec<String>,
|
|
|
|
|
mut out: &mut Vec<(Option<String>, 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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|