use crate::parser::ast::*;
use std::collections::HashMap;
pub struct CodeGenerator {
output: String,
data_section: String,
bss_section: String,
functions_section: String,
label_counter: usize,
string_counter: usize,
float_counter: usize,
empty_string_label: Option<String>,
variables: HashMap<String, i64>,
variable_types: HashMap<String, VarType>,
global_constants: HashMap<String, Expr>,
list_element_types: HashMap<String, VarType>,
mixed_lists: std::collections::HashSet<String>,
unprovable_scalars: std::collections::HashSet<String>,
mixed_tag_slots: HashMap<String, i64>,
file_mode: HashMap<String, FileMode>,
local_mixed_lists: HashMap<String, std::collections::HashSet<String>>,
local_unprovable_scalars: HashMap<String, std::collections::HashSet<String>>,
local_names: HashMap<String, std::collections::HashSet<String>>,
stack_offset: i64,
shared_lib_mode: bool,
exported_functions: Vec<String>,
library_blocks: Vec<LibBlock>,
current_library: Option<(String, String)>,
imports: Vec<crate::lib_file::ImportedFunction>,
import_labels: HashMap<String, String>,
imported_symbols: Vec<String>,
uses_ints: bool,
uses_floats: bool,
uses_files: bool,
uses_buffers: bool,
uses_io: bool,
uses_format: bool,
uses_time: bool,
uses_funcs: bool,
uses_lists: bool,
uses_maps: bool,
uses_strings: bool,
function_return_types: std::collections::HashMap<String, VarType>,
function_param_types: std::collections::HashMap<String, Vec<Type>>,
function_return_full_types: std::collections::HashMap<String, Type>,
current_function_return_type: Option<Type>,
current_thing_return_slot: Option<i64>,
loop_stack: Vec<(String, String)>, flag_schemas: Vec<FlagSchemaRuntime>,
parsed_args_active: bool,
global_var_labels: HashMap<String, String>,
global_var_counter: usize,
global_value_tag_labels: HashMap<String, String>,
declared_types: HashMap<String, Type>,
initialized_globals: std::collections::HashSet<String>,
in_function_codegen: bool,
target_arch: String,
things: crate::analyzer::things::ThingRegistry,
thing_vars: HashMap<String, String>,
}
#[derive(Clone, PartialEq)]
pub(crate) enum VarType {
Integer,
Float, String, Buffer, List, Map, Boolean,
Mixed, Unknown,
}
pub(crate) enum VarTarget {
Local(i64),
Global(String),
}
const TAG_INTEGER: u8 = 0;
const TAG_STRING: u8 = 1;
const TAG_FLOAT: u8 = 2;
const TAG_BOOLEAN: u8 = 3;
const TAG_LIST: u8 = 4;
const TAG_MAP: u8 = 5;
const TAG_NOTHING: u8 = 6;
const BUF_DATA_OFFSET: i64 = 24;
const LIST_DATA_OFFSET: i64 = 24;
#[allow(dead_code)]
const MAP_HEADER_SIZE: i64 = 24;
mod mangling;
pub(crate) use mangling::{mangle_symbol, mangle_library_symbol, make_function_label, format_lib_name};
mod lib_output;
pub use lib_output::{LibFunction, LibBlock, render_lib_file};
use lib_output::{collect_lib_function_return_types, infer_list_element_type, infer_return_list_element_type, list_element_vartype, type_noun_name};
mod flags;
use flags::FlagSchemaRuntime;
mod syscalls;
mod buffers;
mod format;
pub(crate) use format::{read_format_spec, FormatSpecFault, FORMAT_MAX_COUNT};
mod vars;
mod functions;
mod tags;
use tags::type_to_tag;
mod collections;
mod print;
mod expr;
mod statements;
mod things;
#[derive(Clone, Copy, PartialEq, Eq)]
pub(crate) enum TagInfo {
Known(u8),
Unknowable,
}
pub(crate) enum RuntimeTagSource {
R11,
ShadowSlot(i64),
ShadowSlotGlobal(String),
}
pub(crate) enum ShadowTagLoc {
Local(i64),
Global(String),
}
#[derive(Clone, Debug, PartialEq)]
enum IntegerBase {
Decimal,
HexLower,
HexUpper,
Binary,
Octal,
}
#[derive(Clone, Debug, PartialEq)]
pub(crate) struct FormatSpec {
width: Option<i64>,
zero_pad: bool,
base: IntegerBase,
precision: Option<i64>,
}
pub(crate) enum FormatPartValue {
Loaded(Option<VarType>),
Literal(String),
Unknown,
}
#[cfg(test)]
mod tests;
impl CodeGenerator {
pub fn new() -> Self {
CodeGenerator {
output: String::new(),
data_section: String::new(),
bss_section: String::new(),
functions_section: String::new(),
label_counter: 0,
string_counter: 0,
float_counter: 0,
empty_string_label: None,
variables: HashMap::new(),
variable_types: HashMap::new(),
global_constants: HashMap::new(),
list_element_types: HashMap::new(),
mixed_lists: std::collections::HashSet::new(),
unprovable_scalars: std::collections::HashSet::new(),
mixed_tag_slots: HashMap::new(),
file_mode: HashMap::new(),
local_mixed_lists: HashMap::new(),
local_unprovable_scalars: HashMap::new(),
local_names: HashMap::new(),
stack_offset: 0,
shared_lib_mode: false,
exported_functions: Vec::new(),
library_blocks: Vec::new(),
current_library: None,
imports: Vec::new(),
import_labels: HashMap::new(),
imported_symbols: Vec::new(),
uses_ints: false,
uses_floats: false,
uses_files: false,
uses_buffers: false,
uses_io: false,
uses_format: false,
uses_time: false,
uses_funcs: false,
uses_lists: false,
uses_maps: false,
uses_strings: false,
function_return_types: std::collections::HashMap::new(),
function_param_types: std::collections::HashMap::new(),
function_return_full_types: std::collections::HashMap::new(),
current_function_return_type: None,
current_thing_return_slot: None,
loop_stack: Vec::new(),
flag_schemas: Vec::new(),
parsed_args_active: false,
global_var_labels: HashMap::new(),
global_var_counter: 0,
global_value_tag_labels: HashMap::new(),
declared_types: HashMap::new(),
initialized_globals: std::collections::HashSet::new(),
in_function_codegen: false,
target_arch: "x86_64".to_string(),
things: HashMap::new(),
thing_vars: HashMap::new(),
}
}
fn new_label(&mut self, prefix: &str) -> String {
let label = format!(".{}_{}", prefix, self.label_counter);
self.label_counter += 1;
label
}
fn emit(&mut self, code: &str) {
self.output.push_str(code);
self.output.push('\n');
}
fn emit_indent(&mut self, code: &str) {
self.output.push_str(" ");
self.output.push_str(code);
self.output.push('\n');
}
}