ironwork_syntax/ast/
oo.rs1use super::{DataEntry, Operand, Program, Ref, Stmt};
5use crate::Pos;
6
7#[derive(Clone, Debug, Default, PartialEq, Eq)]
9pub struct Oo {
10 pub repository: Vec<ClassEntry>,
13 pub unit: OoUnit,
14}
15
16#[derive(Clone, Debug, Default, PartialEq, Eq)]
17pub enum OoUnit {
18 #[default]
19 Program,
20 Class(Box<ClassDef>),
21 Method(MethodOf),
22}
23
24#[derive(Clone, Debug, PartialEq, Eq)]
26pub struct ClassEntry {
27 pub name: String,
28 pub external: String,
30 pub pos: Pos,
31}
32
33pub fn external_class_name(name: &str) -> String {
36 name.to_ascii_uppercase()
37 .chars()
38 .enumerate()
39 .map(|(i, c)| match c {
40 '-' => '0',
41 '0' if i == 0 => 'J',
42 '1'..='9' if i == 0 => (b'A' + (c as u8 - b'1')) as char,
43 c => c,
44 })
45 .collect()
46}
47
48impl Oo {
49 pub fn external(&self, name: &str) -> Option<&str> {
51 self.repository.iter().find(|e| e.name == name).map(|e| e.external.as_str())
52 }
53
54 pub fn class(&self) -> Option<&ClassDef> {
55 match &self.unit {
56 OoUnit::Class(c) => Some(c),
57 _ => None,
58 }
59 }
60
61 pub fn method(&self) -> Option<&MethodOf> {
62 match &self.unit {
63 OoUnit::Method(m) => Some(m),
64 _ => None,
65 }
66 }
67}
68
69#[derive(Clone, Debug, PartialEq, Eq)]
70pub struct ClassDef {
71 pub name: String,
72 pub inherits: String,
74 pub factory: Option<ClassPart>,
75 pub object: Option<ClassPart>,
76 pub pos: Pos,
77}
78
79#[derive(Clone, Debug, Default, PartialEq, Eq)]
81pub struct ClassPart {
82 pub working_storage: Vec<DataEntry>,
83 pub methods: Vec<Program>,
84 pub pos: Pos,
85}
86
87#[derive(Clone, Debug, PartialEq, Eq)]
89pub struct MethodOf {
90 pub class: String,
91 pub factory: bool,
92 pub name: String,
93 pub pos: Pos,
94}
95
96#[derive(Clone, Debug, PartialEq, Eq)]
97pub enum InvokeMethod {
98 New,
99 Named(String),
101 Identifier(Ref),
103}
104
105#[derive(Clone, Debug, PartialEq, Eq)]
107pub struct Invoke {
108 pub target: Ref,
109 pub method: InvokeMethod,
110 pub using: Vec<Operand>,
112 pub returning: Option<Ref>,
113 pub on_exception: Option<Vec<Stmt>>,
114 pub not_on_exception: Option<Vec<Stmt>>,
115 pub pos: Pos,
116}
117
118#[cfg(test)]
119mod tests {
120 use super::*;
121
122 #[test]
123 fn external_names_as_ibm_forms_them() {
124 assert_eq!(external_class_name("Account"), "ACCOUNT");
125 assert_eq!(external_class_name("my-class_1"), "MY0CLASS_1");
126 assert_eq!(external_class_name("1st-class"), "AST0CLASS");
127 assert_eq!(external_class_name("0ne"), "JNE");
128 }
129}