use crate::ast::UnionDef;
use crate::ffi::FfiBindings;
use crate::types::Type;
use std::collections::HashMap;
use super::specialization::SpecSignature;
pub(super) const UNREACHABLE_PREDECESSOR: &str = "unreachable";
pub(super) const MAX_VIRTUAL_STACK: usize = 4;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(super) enum TailPosition {
Tail,
NonTail,
}
pub(super) struct BranchResult {
pub stack_var: String,
pub emitted_tail_call: bool,
pub predecessor: String,
}
pub(super) fn mangle_name(name: &str) -> String {
let mut result = String::new();
for c in name.chars() {
match c {
'?' => result.push_str("_Q_"),
'>' => result.push_str("_GT_"),
'<' => result.push_str("_LT_"),
'!' => result.push_str("_BANG_"),
'*' => result.push_str("_STAR_"),
'/' => result.push_str("_SLASH_"),
'+' => result.push_str("_PLUS_"),
'=' => result.push_str("_EQ_"),
'-' => result.push('_'),
'_' | '.' | '$' => result.push(c),
c if c.is_alphanumeric() => result.push(c),
_ => result.push_str(&format!("_x{:02X}_", c as u32)),
}
}
result
}
pub(super) struct QuotationFunctions {
pub wrapper: String,
pub impl_: String,
}
#[derive(Clone, Debug)]
pub(super) enum VirtualValue {
Int {
ssa_var: String,
#[allow(dead_code)] value: i64,
},
Float { ssa_var: String },
Bool { ssa_var: String },
}
impl VirtualValue {
pub fn discriminant(&self) -> i64 {
match self {
VirtualValue::Int { .. } => 0,
VirtualValue::Float { .. } => 1,
VirtualValue::Bool { .. } => 2,
}
}
}
pub struct CodeGen {
pub(super) output: String,
pub(super) string_globals: String,
pub(super) temp_counter: usize,
pub(super) string_counter: usize,
pub(super) block_counter: usize, pub(super) quot_counter: usize, pub(super) string_constants: HashMap<String, String>, pub(super) quotation_functions: String, pub(super) type_map: HashMap<usize, Type>, pub(super) external_builtins: HashMap<String, String>, pub(super) inside_closure: bool, pub(super) inside_main: bool, pub(super) inside_quotation: bool, pub(super) unions: Vec<UnionDef>, pub(super) ffi_bindings: FfiBindings, pub(super) ffi_wrapper_code: String, pub(super) pure_inline_test: bool,
pub(super) symbol_globals: String, pub(super) symbol_counter: usize, pub(super) symbol_constants: HashMap<String, String>, pub(super) statement_types: HashMap<(String, usize), Type>,
pub(super) current_word_name: Option<String>,
pub(super) current_stmt_index: usize,
pub(super) codegen_depth: usize,
pub(super) prev_stmt_is_trivial_literal: bool,
pub(super) prev_stmt_int_value: Option<i64>,
pub(super) virtual_stack: Vec<VirtualValue>,
pub(super) specialized_words: HashMap<String, SpecSignature>,
}
impl Default for CodeGen {
fn default() -> Self {
Self::new()
}
}
impl CodeGen {
pub fn new() -> Self {
CodeGen {
output: String::new(),
string_globals: String::new(),
temp_counter: 0,
string_counter: 0,
block_counter: 0,
inside_closure: false,
inside_main: false,
inside_quotation: false,
quot_counter: 0,
string_constants: HashMap::new(),
quotation_functions: String::new(),
type_map: HashMap::new(),
external_builtins: HashMap::new(),
unions: Vec::new(),
ffi_bindings: FfiBindings::new(),
ffi_wrapper_code: String::new(),
pure_inline_test: false,
symbol_globals: String::new(),
symbol_counter: 0,
symbol_constants: HashMap::new(),
statement_types: HashMap::new(),
current_word_name: None,
current_stmt_index: 0,
codegen_depth: 0,
prev_stmt_is_trivial_literal: false,
prev_stmt_int_value: None,
virtual_stack: Vec::new(),
specialized_words: HashMap::new(),
}
}
pub fn new_pure_inline_test() -> Self {
let mut cg = Self::new();
cg.pure_inline_test = true;
cg
}
}