imports: Vec<Rc<IRModule>>,
exports: Vec<String>,
source_file: PathBuf,
+ number: usize,
+}
+
+impl IRModule {
+ fn get_label_for_call(&self, name: &String) -> String {
+ let mut found: Option<usize> = None;
+ for imported in &self.imports {
+ if imported.exports.contains(name) {
+ found = Some(imported.number);
+ // Don't break here, since the last one should win.
+ }
+ }
+ if let Some(found) = found {
+ format!("_m{}_{}", found, name)
+ } else {
+ // TODO check if it's even a word locally. If not, bail.
+ format!("_m{}_{}", self.number, name)
+ }
+ }
+
+ fn get_label(&self, name: &String) -> String {
+ format!("_m{}_{}", self.number, name)
+ }
}
#[derive(Default)]
result
}).flatten().collect::<Vec<_>>());
+ let number = self.module_count;
+ self.module_count += 1;
IRModule {
text: text.into_iter().flatten().collect::<Vec<_>>(),
imports,
exports,
source_file: path,
+ number,
}
}
let is_entrypoint = module.source_file == self.entrypoint.source_file;
- let module_number = self.module_count;
- self.module_count += 1;
+ let module_number = module.number;
for string in &module.data {
if let IR::StringDef(name, val) = string {
IR::StackPushString(new_name)
},
IR::Label(name) => {
- if is_entrypoint || module.exports.contains(name) {
+ if is_entrypoint && name == "main" {
instruction.clone()
} else {
- let new_name = format!("_m{}_{}", module_number, name);
- IR::Label(new_name)
+ IR::Label(module.get_label(name))
}
},
IR::Call(name) => {
- if is_entrypoint || self.all_exports.contains(name) {
- instruction.clone()
- } else {
- let new_name = format!("_m{}_{}", module_number, name);
- IR::Label(new_name)
- }
+ IR::Call(module.get_label_for_call(name))
},
_ => instruction.clone()
};
}
}
-
-
pub fn compile(path: &str) -> Result<IRObject> {
let dir = std::env::current_dir()?;
let mut tree: ImportTree = Default::default();