1pub use compile::oo::*;
5pub use compile::oo::{ClassCode, MethodCode, Part};
6pub use rt::oo::*;
7
8use syntax::ast::Program;
9
10pub(crate) fn refuse_to_run(program: &Program) -> Result<(), crate::Abend> {
11 match program.oo.as_ref().and_then(|o| o.class()) {
12 Some(c) => Err(crate::Abend { code: crate::abend::AbendCode::Ironwork, message: format!("{} is a class definition: run a program that uses it", c.name), pos: c.pos, file: None }),
13 None => Ok(()),
14 }
15}
16
17pub(crate) fn find_class(library: &mut crate::unit::Library, external: &str) -> Result<Option<(Program, Option<String>)>, String> {
22 if external == JAVA_LANG_OBJECT {
23 return Ok(None);
24 }
25 if let Some(i) = library.programs.iter().position(|p| defined_class(p).as_deref() == Some(external)) {
26 return Ok(Some((library.programs.remove(i), None)));
27 }
28 let member = |n: &str| !n.is_empty() && n.chars().all(|c| c.is_ascii_alphanumeric() || c == '_' || c == '$');
29 let simple = external.rsplit('.').next().unwrap_or(external).to_owned();
30 let mut names = vec![simple, external.replace('.', "_")];
31 names.dedup();
32 names.retain(|n| member(n));
33 for dir in library.dirs.clone() {
34 for name in &names {
35 for variant in [name.clone(), name.to_ascii_lowercase(), name.to_ascii_uppercase()] {
36 for ext in ["", ".cbl", ".CBL", ".cob", ".COB"] {
37 let path = dir.join(format!("{variant}{ext}"));
38 if !path.is_file() {
39 continue;
40 }
41 let text = std::fs::read(&path).map(|b| syntax::copy::decode(&b)).map_err(|e| format!("{}: {e}", path.display()))?;
42 let mut programs = syntax::parse_all_with(&text, &library.copy.with_program(&path)).map_err(|e| format!("class {external} does not compile: {}", e.place(&path.display().to_string())))?;
43 if defined_class(&programs[0]).as_deref() == Some(external) {
44 return Ok(Some((programs.remove(0), Some(path.display().to_string()))));
45 }
46 }
47 }
48 }
49 }
50 Ok(None)
51}