Skip to content

Commit

Permalink
Conversion of &'a str to Cow<'a, str> in LanguageElement and Statemen…
Browse files Browse the repository at this point in the history
…tElement
  • Loading branch information
SKyletoft committed Feb 28, 2021
1 parent 5882bb8 commit 3953968
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 105 deletions.
122 changes: 72 additions & 50 deletions src/compile_flisp.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
use std::collections::HashMap;
use std::{borrow::Cow, collections::HashMap};

use crate::*;

///Technically illegal address for use in register -> register transfers
const ABOVE_STACK_OFFSET: isize = -1;

///Name (lifetime from source code), (Type, Stack position (from the bottom))
type Variables<'a, 'b> = &'b mut HashMap<&'a str, (Type, isize)>;
type Variables<'a, 'b> = &'b mut HashMap<Cow<'a, str>, (Type, isize)>;

///Name (lifetime from source code), Type
type GlobalVariables<'a, 'b> = &'b mut HashMap<&'a str, Type>;
type GlobalVariables<'a, 'b> = &'b mut HashMap<Cow<'a, str>, Type>;

///Name, Argument list (not named)
type Functions<'a, 'b> = &'b mut HashMap<&'a str, &'a [Variable<'a>]>;
type Functions<'a, 'b> = &'b mut HashMap<Cow<'a, str>, &'a [Variable<'a>]>;

#[derive(Debug, PartialEq)]
struct State<'a, 'b, 'c, 'd, 'e, 'f> {
Expand Down Expand Up @@ -88,7 +88,7 @@ fn compile_element<'a>(
dbg!(element);
return Err(CompileError(line!(), "Name already exists in scope!"));
}
state.global_variables.insert(*name, typ.clone());
state.global_variables.insert(name.clone(), typ.clone());
vec![]
} else {
if state.variables.contains_key(name) {
Expand All @@ -100,11 +100,11 @@ fn compile_element<'a>(
}
state
.variables
.insert(*name, (typ.clone(), *state.stack_size));
.insert(name.clone(), (typ.clone(), *state.stack_size));
*state.stack_size += 1;
vec![(
Instruction::LEASP(Addressing::SP(ABOVE_STACK_OFFSET)),
Some(*name),
Some(Cow::Borrowed(name.as_ref())),
)]
}
}
Expand All @@ -120,7 +120,7 @@ fn compile_element<'a>(
*state.stack_size,
)?;
let mut statement = compile_statement(value, state)?;
statement.push((Instruction::STA(adr), Some(name)));
statement.push((Instruction::STA(adr), Some(Cow::Borrowed(name.as_ref()))));
statement
}

Expand Down Expand Up @@ -148,7 +148,9 @@ fn compile_element<'a>(
return Err(CompileError(line!(), "Name already exists in scope!"));
}
if let StatementElement::Array(elements) = value {
state.global_variables.insert(*name, typ.clone());
state
.global_variables
.insert(Cow::Borrowed(name.as_ref()), typ.clone());
let values = elements
.iter()
.map(global_def)
Expand All @@ -158,7 +160,9 @@ fn compile_element<'a>(
(Instruction::FCB(values), None),
]
} else {
state.global_variables.insert(*name, typ.clone());
state
.global_variables
.insert(Cow::Borrowed(name.as_ref()), typ.clone());
vec![
(Instruction::Label(name.to_string()), None),
(Instruction::FCB(vec![global_def(value)?]), None),
Expand All @@ -179,21 +183,23 @@ fn compile_element<'a>(
statement.append(&mut compile_statement(element, state)?);
assert_eq!(*state.stack_size, stack_copy);
*state.stack_size += 1;
statement.push((Instruction::PSHA, Some(*name)));
statement.push((Instruction::PSHA, Some(Cow::Borrowed(name.as_ref()))));
}
state
.variables
.insert(*name, (typ.clone(), *state.stack_size));
state.variables.insert(
Cow::Borrowed(name.as_ref()),
(typ.clone(), *state.stack_size),
);
statement
} else {
let stack_copy = *state.stack_size;
let mut statement = compile_statement(value, state)?;
assert_eq!(*state.stack_size, stack_copy);
state
.variables
.insert(*name, (typ.clone(), *state.stack_size));
state.variables.insert(
Cow::Borrowed(name.as_ref()),
(typ.clone(), *state.stack_size),
);
*state.stack_size += 1;
statement.push((Instruction::PSHA, Some(*name)));
statement.push((Instruction::PSHA, Some(Cow::Borrowed(name.as_ref()))));
statement
}
}
Expand All @@ -208,11 +214,11 @@ fn compile_element<'a>(
let mut statement = get_adr;
statement.push((
Instruction::STA(Addressing::SP(ABOVE_STACK_OFFSET)),
Some("A to X part 1"),
Some("A to X part 1".into()),
));
statement.push((
Instruction::LDX(Addressing::SP(ABOVE_STACK_OFFSET)),
Some("A to X part 2"),
Some("A to X part 2".into()),
));
statement.append(&mut value);
statement.push((Instruction::STA(Addressing::Xn(0)), None));
Expand All @@ -231,15 +237,17 @@ fn compile_element<'a>(
"Function name already exists in scope!",
));
}
state.functions.insert(*name, args.as_slice());
state
.functions
.insert(Cow::Borrowed(name.as_ref()), args.as_slice());
//Stack: Start -> Arguments -> Return adr -> Variables -> Whatever the stack grows to
// If this +1 is removed we can no longer have arguments
// This might waste a byte if there are no arguments?
let mut args_count = args.len() as isize + 1;
let args_base = args_count;
let mut local_variables = HashMap::new();
for (idx, Variable { name, typ }) in args.iter().enumerate() {
local_variables.insert(*name, (typ.clone(), idx as isize));
local_variables.insert(Cow::Borrowed(*name), (typ.clone(), idx as isize));
}
let mut function_body = compile_elements(
block,
Expand All @@ -258,7 +266,7 @@ fn compile_element<'a>(
if args_count != 0 {
function_body.push((
Instruction::LEASP(Addressing::SP(args_count)),
Some("Clearing variables"),
Some("Clearing variables".into()),
));
}
function_body.push((Instruction::RTS, None));
Expand Down Expand Up @@ -317,7 +325,7 @@ fn compile_element<'a>(
if else_stack != *state.stack_size {
cond.push((
Instruction::LEASP(Addressing::SP(else_stack - *state.stack_size)),
Some("This happened"),
Some("This happened".into()),
));
}
} else {
Expand Down Expand Up @@ -480,12 +488,12 @@ fn compile_statement<'a>(
if tmps > 0 {
let mut block = vec![(
Instruction::LEASP(Addressing::SP(-tmps)),
Some("Reserving memory for statement"),
Some(Cow::from("Reserving memory for statement")),
)];
block.append(&mut statement_instructions);
block.append(&mut vec![(
Instruction::LEASP(Addressing::SP(tmps)), //why not -1?
Some("Clearing memory for statement"),
Some(Cow::from("Clearing memory for statement")),
)]);
statement_instructions = block;
};
Expand Down Expand Up @@ -534,7 +542,7 @@ fn compile_statement_inner<'a>(
};
match statement {
StatementElement::Mul { rhs: _, lhs: _ } => {
instructions.push((Instruction::PSHA, Some("mul rhs")));
instructions.push((Instruction::PSHA, Some(Cow::Borrowed("mul rhs"))));
instructions.append(&mut right_instructions_plus_one()?);
instructions.push((
Instruction::JSR(Addressing::Label("__mul__".to_string())),
Expand All @@ -543,7 +551,7 @@ fn compile_statement_inner<'a>(
instructions.push((Instruction::LEASP(Addressing::SP(1)), None));
}
StatementElement::Cmp { rhs: _, lhs: _ } => {
instructions.push((Instruction::PSHA, Some("cmp rhs")));
instructions.push((Instruction::PSHA, Some("cmp rhs".into())));
instructions.append(&mut right_instructions_plus_one()?);
instructions.push((
Instruction::JSR(Addressing::Label("__eq__".to_string())),
Expand All @@ -552,7 +560,7 @@ fn compile_statement_inner<'a>(
instructions.push((Instruction::LEASP(Addressing::SP(1)), None));
}
StatementElement::NotCmp { rhs: _, lhs: _ } => {
instructions.push((Instruction::PSHA, Some("cmp rhs")));
instructions.push((Instruction::PSHA, Some("cmp rhs".into())));
instructions.append(&mut right_instructions_plus_one()?);
instructions.push((
Instruction::JSR(Addressing::Label("__eq__".to_string())),
Expand All @@ -566,7 +574,10 @@ fn compile_statement_inner<'a>(
*tmps_used -= 1;
let mut right_instructions = compile_statement_inner(right, state, tmps_used)?;
if let [(Instruction::LDA(adr), comment)] = &right_instructions.as_slice() {
instructions.push((statement.as_flisp_instruction(adr.clone())?, *comment));
instructions.push((
statement.as_flisp_instruction(adr.clone())?,
comment.clone(),
));
} else {
assert!(right_instructions.len() >= 2);
instructions.push((Instruction::STA(Addressing::SP(*tmps_used)), None));
Expand Down Expand Up @@ -613,7 +624,7 @@ fn compile_statement_inner<'a>(
};
match statement {
StatementElement::Div { rhs: _, lhs: _ } => {
instructions.push((Instruction::PSHA, Some("div rhs")));
instructions.push((Instruction::PSHA, Some("div rhs".into())));
instructions.append(&mut right_instructions_plus_one()?);
instructions.push((
Instruction::JSR(Addressing::Label("__div__".to_string())),
Expand All @@ -622,7 +633,7 @@ fn compile_statement_inner<'a>(
instructions.push((Instruction::LEASP(Addressing::SP(1)), None));
}
StatementElement::Mod { rhs: _, lhs: _ } => {
instructions.push((Instruction::PSHA, Some("mod rhs")));
instructions.push((Instruction::PSHA, Some("mod rhs".into())));
instructions.append(&mut right_instructions_plus_one()?);
instructions.push((
Instruction::JSR(Addressing::Label("__mod__".to_string())),
Expand All @@ -632,7 +643,7 @@ fn compile_statement_inner<'a>(
}
StatementElement::GreaterThan { rhs: _, lhs: _ }
| StatementElement::LessThan { rhs: _, lhs: _ } => {
instructions.push((Instruction::PSHA, Some("gt rhs")));
instructions.push((Instruction::PSHA, Some("gt rhs".into())));
instructions.append(&mut right_instructions_plus_one()?);
instructions.push((
Instruction::JSR(Addressing::Label("__gt__".to_string())),
Expand All @@ -642,7 +653,7 @@ fn compile_statement_inner<'a>(
}
StatementElement::LessThanEqual { rhs: _, lhs: _ }
| StatementElement::GreaterThanEqual { rhs: _, lhs: _ } => {
instructions.push((Instruction::PSHA, Some("lte rhs")));
instructions.push((Instruction::PSHA, Some("lte rhs".into())));
instructions.append(&mut right_instructions_plus_one()?);
instructions.push((
Instruction::JSR(Addressing::Label("__gt__".to_string())),
Expand Down Expand Up @@ -696,7 +707,10 @@ fn compile_statement_inner<'a>(
*tmps_used -= 1;
let mut right_instructions = compile_statement_inner(right, state, tmps_used)?;
if let [(Instruction::LDA(adr), comment)] = &right_instructions.as_slice() {
instructions.push((statement.as_flisp_instruction(adr.clone())?, *comment));
instructions.push((
statement.as_flisp_instruction(adr.clone())?,
comment.clone(),
));
} else {
assert!(instructions.len() >= 2);
instructions.push((Instruction::STA(Addressing::SP(*tmps_used)), None));
Expand Down Expand Up @@ -727,7 +741,7 @@ fn compile_statement_inner<'a>(
) in parametres.iter().zip(arg_names.iter())
{
instructions.append(&mut compile_statement(statement, state)?);
instructions.push((Instruction::PSHA, Some(v_name)));
instructions.push((Instruction::PSHA, Some(Cow::Borrowed(*v_name))));
}
instructions.push((Instruction::JSR(Addressing::Label(name.to_string())), None));
instructions.push((
Expand All @@ -744,7 +758,7 @@ fn compile_statement_inner<'a>(
state.global_variables,
*state.stack_size,
)?;
vec![(Instruction::LDA(adr), Some(*name))]
vec![(Instruction::LDA(adr), Some(Cow::Borrowed(name.as_ref())))]
}

StatementElement::Num(n) => {
Expand All @@ -766,33 +780,33 @@ fn compile_statement_inner<'a>(
//Array opt
(
&StatementElement::Add { lhs: _, rhs: _ },
Some((&StatementElement::Var(name), &StatementElement::Num(offset))),
Some((StatementElement::Var(name), &StatementElement::Num(offset))),
) => {
let adr = adr_for_name(
name,
name.as_ref(),
state.variables,
state.global_variables,
*state.stack_size,
)?;
vec![
(Instruction::LDY(adr), Some(name)),
(Instruction::LDY(adr), Some(Cow::Borrowed(name.as_ref()))),
(Instruction::LDA(Addressing::Yn(offset)), None),
]
}
//General opt
(
&StatementElement::Add { lhs: _, rhs: _ },
Some((&StatementElement::Var(name), rhs)),
Some((StatementElement::Var(name), rhs)),
) => {
let adr = adr_for_name(
name,
name.as_ref(),
state.variables,
state.global_variables,
*state.stack_size,
)?;
let mut statement = compile_statement(rhs, state)?;
statement.append(&mut vec![
(Instruction::LDY(adr), Some(name)),
(Instruction::LDY(adr), Some(Cow::Borrowed(name.as_ref()))),
(Instruction::LDA(Addressing::AY), None),
]);
statement
Expand All @@ -802,11 +816,11 @@ fn compile_statement_inner<'a>(
let mut instructions = compile_statement_inner(adr.as_ref(), state, tmps_used)?;
instructions.push((
Instruction::STA(Addressing::SP(ABOVE_STACK_OFFSET)),
Some("A to X transfer"),
Some("A to X transfer".into()),
));
instructions.push((
Instruction::LDX(Addressing::SP(ABOVE_STACK_OFFSET)),
Some("A to X continued"),
Some("A to X continued".into()),
));
instructions.push((Instruction::LDA(Addressing::Xn(0)), None));
instructions
Expand All @@ -827,12 +841,20 @@ fn compile_statement_inner<'a>(
vec![
(
Instruction::STSP(Addressing::SP(ABOVE_STACK_OFFSET)),
Some("SP -> Stack"),
Some(Cow::from("SP -> Stack")),
),
(
Instruction::ADDA(Addressing::SP(n)),
Some(Cow::Borrowed(name.as_ref())),
),
(Instruction::ADDA(Addressing::SP(n)), Some(*name)),
]
}
Addressing::Adr(n) => vec![(Instruction::LDA(Addressing::Data(n)), Some(*name))],
Addressing::Adr(n) => {
vec![(
Instruction::LDA(Addressing::Data(n)),
Some(Cow::Borrowed(name.as_ref())),
)]
}
Addressing::Label(lbl) => {
vec![(Instruction::LDA(Addressing::DataLabel(lbl)), None)]
}
Expand All @@ -852,8 +874,8 @@ fn compile_statement_inner<'a>(
///Returns addressing for a name. Stack offset for locals and a Label for globals (and not an absolute address)
fn adr_for_name<'a>(
name: &'a str,
variables: &HashMap<&'a str, (Type, isize)>,
global_variables: &HashMap<&'a str, Type>,
variables: &HashMap<Cow<'a, str>, (Type, isize)>,
global_variables: &HashMap<Cow<'a, str>, Type>,
stack_size: isize,
) -> Result<Addressing, CompileError> {
if let Some((_, adr)) = variables.get(name) {
Expand Down
8 changes: 5 additions & 3 deletions src/flisp_instructions.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
use std::borrow::Cow;

use crate::*;

// Replace &'a str with a Cow<String>?
///`(Instruction, Option<&'a str>)`
// Replace Cow<'a, str> with a Cow<String>?
///`(Instruction, Option<Cow<'a, str>>)`
///
/// The comment should have the same lifetime as the input source code (or `&'static`)
pub(crate) type CommentedInstruction<'a> = (Instruction, Option<&'a str>);
pub(crate) type CommentedInstruction<'a> = (Instruction, Option<Cow<'a, str>>);

///A flisp instruction. Usually appears as the first half of a `CommentedInstruction` tuple.
/// Can also be a label or FCB assembler directive.
Expand Down
Loading

0 comments on commit 3953968

Please sign in to comment.