use super::{DataEntry, Operand, Program, Ref, Stmt};
use crate::Pos;
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct Oo {
pub repository: Vec<ClassEntry>,
pub unit: OoUnit,
}
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub enum OoUnit {
#[default]
Program,
Class(Box<ClassDef>),
Method(MethodOf),
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ClassEntry {
pub name: String,
pub external: String,
pub pos: Pos,
}
pub fn external_class_name(name: &str) -> String {
name.to_ascii_uppercase()
.chars()
.enumerate()
.map(|(i, c)| match c {
'-' => '0',
'0' if i == 0 => 'J',
'1'..='9' if i == 0 => (b'A' + (c as u8 - b'1')) as char,
c => c,
})
.collect()
}
impl Oo {
pub fn external(&self, name: &str) -> Option<&str> {
self.repository.iter().find(|e| e.name == name).map(|e| e.external.as_str())
}
pub fn class(&self) -> Option<&ClassDef> {
match &self.unit {
OoUnit::Class(c) => Some(c),
_ => None,
}
}
pub fn method(&self) -> Option<&MethodOf> {
match &self.unit {
OoUnit::Method(m) => Some(m),
_ => None,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ClassDef {
pub name: String,
pub inherits: String,
pub factory: Option<ClassPart>,
pub object: Option<ClassPart>,
pub pos: Pos,
}
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct ClassPart {
pub working_storage: Vec<DataEntry>,
pub methods: Vec<Program>,
pub pos: Pos,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct MethodOf {
pub class: String,
pub factory: bool,
pub name: String,
pub pos: Pos,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum InvokeMethod {
New,
Named(String),
Identifier(Ref),
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Invoke {
pub target: Ref,
pub method: InvokeMethod,
pub using: Vec<Operand>,
pub returning: Option<Ref>,
pub on_exception: Option<Vec<Stmt>>,
pub not_on_exception: Option<Vec<Stmt>>,
pub pos: Pos,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn external_names_as_ibm_forms_them() {
assert_eq!(external_class_name("Account"), "ACCOUNT");
assert_eq!(external_class_name("my-class_1"), "MY0CLASS_1");
assert_eq!(external_class_name("1st-class"), "AST0CLASS");
assert_eq!(external_class_name("0ne"), "JNE");
}
}