}
}
- // Data stack
- self.label(".data\n");
- self.label(".align 3\n");
- self.label("data_stack:");
- self.line(format!(".space {}", self.data_stack_size));
- self.label(".globl data_stack_end\ndata_stack_end:\n");
-
// Code
self.label(".text\n");
self.label(".align 3\n");
let mut loop_stack = vec![];
let mut seen_else = HashSet::new();
let mut last_label = "";
+ let mut var_decls = vec![];
for ir in &self.module.text {
match ir {
self.line("ret");
}
},
+ IR::VarDecl(name) => {
+ var_decls.push(name);
+ },
+ IR::StackPushVar(name) => {
+ self.label(format!("# stackpushvar {}", name));
+ self.line(format!("la t0, {}", name));
+ self.push_from("t0");
+ },
IR::Load8 => {
self.label("# load 8");
self.copy_top_stack_value_to("t0");
}
}
+ // Data stack
+ self.label(".bss\n");
+ self.label(".align 3\n");
+ self.label("data_stack:");
+ self.line(format!(".space {}", self.data_stack_size));
+ self.label(".globl data_stack_end\ndata_stack_end:\n");
+ for decl in var_decls {
+ self.label(format!("{}:", decl));
+ self.line(".space 8");
+ }
+
Ok(self.lines.join("\n"))
}
}
let externs = module.externs.iter().map(|s| s.to_string()).collect();
- text.push(module.words.iter().flat_map(|def| {
- let mut body = def.instructions.iter().map(|inst| {
- IR::from_token(inst, &mut data)
- }).collect::<Vec<_>>();
+ module.words.iter().try_for_each(|def| -> Result<(), anyhow::Error> {
+ let mut body = vec![];
+ let mut last_call_was_var = false;
+ let mut vars = vec![];
+ def.instructions.iter().try_for_each(|inst| {
+ let new_token = IR::from_token(inst, &mut data);
+ if let IR::Call(thing) = new_token {
+ if thing == "var" {
+ last_call_was_var = true;
+ } else {
+ if last_call_was_var {
+ body.push(IR::VarDecl(thing.clone()));
+ vars.push(thing);
+ last_call_was_var = false;
+ } else {
+ if vars.contains(&thing) {
+ body.push(IR::StackPushVar(thing));
+ } else {
+ body.push(IR::Call(thing));
+ }
+ }
+ }
+ } else {
+ if last_call_was_var {
+ bail!("word must come after var!")
+ } else {
+ body.push(new_token);
+ }
+ }
+ Ok(())
+ })?;
let mut result = vec![IR::Label(def.name.to_string())];
result.append(&mut body);
result.push(IR::Ret);
- result
- }).collect::<Vec<_>>());
+ text.push(result);
+ Ok(())
+ })?;
let number = self.module_count;
self.module_count += 1;
}
}
+ let mut last_label_name = String::from("");
for instruction in &module.text {
let new_instruction = match instruction {
IR::StackPushString(name) => {
},
IR::Label(name) => {
if is_entrypoint && name == "main" {
+ last_label_name = String::from("main");
instruction.clone()
} else {
+ let label_name = module.get_label(name);
+ last_label_name = label_name.clone();
IR::Label(module.get_label(name))
}
},
+ IR::VarDecl(name) => {
+ IR::VarDecl(format!("_var_{}_{}", last_label_name, name))
+ },
+ IR::StackPushVar(name) => {
+ IR::StackPushVar(format!("_var_{}_{}", last_label_name, name))
+ },
IR::Call(name) => {
IR::Call(module.get_label_for_call(name))
},