diff --git a/src/compile_flisp.rs b/src/compile_flisp.rs index d6b3ead..ec803cc 100644 --- a/src/compile_flisp.rs +++ b/src/compile_flisp.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::{borrow::Cow, collections::HashMap}; use crate::*; @@ -6,13 +6,13 @@ use crate::*; 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, (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, 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, &'a [Variable<'a>]>; #[derive(Debug, PartialEq)] struct State<'a, 'b, 'c, 'd, 'e, 'f> { @@ -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) { @@ -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())), )] } } @@ -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 } @@ -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) @@ -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), @@ -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 } } @@ -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)); @@ -231,7 +237,9 @@ 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? @@ -239,7 +247,7 @@ fn compile_element<'a>( 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, @@ -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)); @@ -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 { @@ -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; }; @@ -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())), @@ -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())), @@ -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())), @@ -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)); @@ -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())), @@ -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())), @@ -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())), @@ -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())), @@ -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)); @@ -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(( @@ -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) => { @@ -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 @@ -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 @@ -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)] } @@ -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, (Type, isize)>, + global_variables: &HashMap, Type>, stack_size: isize, ) -> Result { if let Some((_, adr)) = variables.get(name) { diff --git a/src/flisp_instructions.rs b/src/flisp_instructions.rs index 21c319b..ad6aba6 100644 --- a/src/flisp_instructions.rs +++ b/src/flisp_instructions.rs @@ -1,10 +1,12 @@ +use std::borrow::Cow; + use crate::*; -// Replace &'a str with a Cow? -///`(Instruction, Option<&'a str>)` +// Replace Cow<'a, str> with a Cow? +///`(Instruction, Option>)` /// /// 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>); ///A flisp instruction. Usually appears as the first half of a `CommentedInstruction` tuple. /// Can also be a label or FCB assembler directive. diff --git a/src/language_element.rs b/src/language_element.rs index 7cc4628..f4be643 100644 --- a/src/language_element.rs +++ b/src/language_element.rs @@ -1,4 +1,5 @@ use crate::*; +use std::borrow::Cow; ///Internal representation of the program. /// Can represent any language pattern considered valid. @@ -8,16 +9,16 @@ use crate::*; pub(crate) enum LanguageElement<'a> { VariableDeclaration { typ: Type, - name: &'a str, + name: Cow<'a, str>, is_static: bool, }, VariableAssignment { - name: &'a str, + name: Cow<'a, str>, value: StatementElement<'a>, }, VariableDeclarationAssignment { typ: Type, - name: &'a str, + name: Cow<'a, str>, value: StatementElement<'a>, is_static: bool, }, @@ -27,7 +28,7 @@ pub(crate) enum LanguageElement<'a> { }, FunctionDeclaration { typ: Type, - name: &'a str, + name: Cow<'a, str>, args: Vec>, block: Block<'a>, }, diff --git a/src/optimise_flisp.rs b/src/optimise_flisp.rs index 22abe24..edff338 100644 --- a/src/optimise_flisp.rs +++ b/src/optimise_flisp.rs @@ -34,7 +34,7 @@ fn load_xy(instructions: &mut Vec) { let mut idx = 0; while instructions.len() >= 3 && idx < instructions.len() - 3 { if let ( - (Instruction::LDA(addressing), comment), + (Instruction::LDA(addressing), _), (Instruction::STA(Addressing::SP(-1)), _), (Instruction::LDX(Addressing::SP(-1)), _), ) = ( @@ -42,12 +42,12 @@ fn load_xy(instructions: &mut Vec) { &instructions[idx + 1], &instructions[idx + 2], ) { - instructions[idx] = (Instruction::LDX(addressing.clone()), *comment); + instructions[idx].0 = Instruction::LDX(addressing.clone()); instructions.remove(idx + 2); //Order matters! instructions.remove(idx + 1); } if let ( - (Instruction::LDA(addressing), comment), + (Instruction::LDA(addressing), _), (Instruction::STA(Addressing::SP(-1)), _), (Instruction::LDY(Addressing::SP(-1)), _), ) = ( @@ -55,12 +55,12 @@ fn load_xy(instructions: &mut Vec) { &instructions[idx + 1], &instructions[idx + 2], ) { - instructions[idx] = (Instruction::LDY(addressing.clone()), *comment); + instructions[idx].0 = Instruction::LDY(addressing.clone()); instructions.remove(idx + 2); //Order matters! instructions.remove(idx + 1); } if let ( - &(Instruction::LDX(Addressing::Data(x_adr)), x_comment), + (Instruction::LDX(Addressing::Data(x_adr)), x_comment), (Instruction::LDA(a_adr), a_comment), (Instruction::STA(Addressing::Xn(0)), _), ) = ( @@ -68,8 +68,10 @@ fn load_xy(instructions: &mut Vec) { &instructions[idx + 1], &instructions[idx + 2], ) { - let a_comment = *a_comment; + let a_comment = a_comment.clone(); let a_adr = a_adr.clone(); + let x_comment = x_comment.clone(); + let x_adr = *x_adr; instructions[idx] = (Instruction::LDA(a_adr), a_comment); instructions[idx + 1] = (Instruction::STA(Addressing::Adr(x_adr)), x_comment); instructions.remove(idx + 2); @@ -228,15 +230,15 @@ fn load_a(instructions: &mut Vec) { if let ( (Instruction::STA(Addressing::SP(-1)), _), (Instruction::LDX(Addressing::SP(-1)), _), - (Instruction::LDA(Addressing::Xn(0)), comment), + (Instruction::LDA(Addressing::Xn(0)), _), ) = ( &instructions[idx], &instructions[idx + 1], &instructions[idx + 2], ) { - instructions[idx + 1] = (Instruction::LDA(Addressing::AX), *comment); instructions[idx] = (Instruction::LDX(Addressing::Data(0)), None); - instructions.remove(idx + 2); + instructions[idx + 2].0 = Instruction::LDA(Addressing::AX); //To keep the existing comment on the third instruction + instructions.remove(idx + 1); } if let ((Instruction::PSHA, _), (Instruction::LDA(Addressing::SP(0)), _)) = (&instructions[idx], &instructions[idx + 1]) @@ -402,7 +404,7 @@ fn dec(instructions: &mut Vec) { while instructions.len() >= 3 && idx < instructions.len() - 3 { if let ( (Instruction::LDA(Addressing::Data(1)), _), - (Instruction::SUBA(from), comment), + (Instruction::SUBA(from), _), (Instruction::STA(to), _), ) = ( &instructions[idx], @@ -410,9 +412,9 @@ fn dec(instructions: &mut Vec) { &instructions[idx + 2], ) { if to == from { - instructions[idx] = (Instruction::DEC(to.clone()), *comment); - instructions.remove(idx + 2); + instructions[idx + 2].0 = Instruction::DEC(to.clone()); instructions.remove(idx + 1); + instructions.remove(idx); } } idx += 1; @@ -424,7 +426,7 @@ fn inc(instructions: &mut Vec) { let mut idx = 0; while instructions.len() >= 3 && idx < instructions.len() - 3 { if let ( - (Instruction::LDA(from), comment), + (Instruction::LDA(from), _), (Instruction::ADDA(Addressing::Data(1)), _), (Instruction::STA(to), _), ) = ( @@ -433,7 +435,7 @@ fn inc(instructions: &mut Vec) { &instructions[idx + 2], ) { if to == from { - instructions[idx] = (Instruction::INC(to.clone()), *comment); + instructions[idx].0 = Instruction::INC(to.clone()); instructions.remove(idx + 2); instructions.remove(idx + 1); } @@ -466,7 +468,7 @@ fn cmp_eq_jmp(instructions: &mut Vec) { let mut idx = 0; while instructions.len() >= 6 && idx < instructions.len() - 6 { if let ( - (Instruction::PSHA, Some("cmp rhs")), + (Instruction::PSHA, Some(text)), (Instruction::LDA(lhs), lhs_comment), (Instruction::JSR(Addressing::Label(function_name)), None), (Instruction::LEASP(Addressing::SP(1)), None), @@ -480,7 +482,7 @@ fn cmp_eq_jmp(instructions: &mut Vec) { &instructions[idx + 4], &instructions[idx + 5], ) { - if function_name != "__eq__" { + if !(function_name == "__eq__" && text == "cmp rhs") { idx += 1; continue; } @@ -489,7 +491,7 @@ fn cmp_eq_jmp(instructions: &mut Vec) { } else { lhs.clone() }; - let lhs_comment = *lhs_comment; + let lhs_comment = lhs_comment.clone(); let jump_adr = jump_adr.clone(); instructions[idx] = (Instruction::CMPA(lhs), lhs_comment); instructions[idx + 5] = (Instruction::BNE(jump_adr), None); @@ -508,7 +510,7 @@ fn cmp_neq_jmp(instructions: &mut Vec) { let mut idx = 0; while instructions.len() >= 7 && idx < instructions.len() - 7 { if let ( - (Instruction::PSHA, Some("cmp rhs")), + (Instruction::PSHA, Some(text)), (Instruction::LDA(lhs), lhs_comment), (Instruction::JSR(Addressing::Label(function_name)), None), (Instruction::LEASP(Addressing::SP(1)), None), @@ -524,7 +526,7 @@ fn cmp_neq_jmp(instructions: &mut Vec) { &instructions[idx + 5], &instructions[idx + 6], ) { - if function_name != "__eq__" { + if !(function_name == "__eq__" && text == "cmp rhs") { idx += 1; continue; } @@ -533,7 +535,7 @@ fn cmp_neq_jmp(instructions: &mut Vec) { } else { lhs.clone() }; - let lhs_comment = *lhs_comment; + let lhs_comment = lhs_comment.clone(); let jump_adr = jump_adr.clone(); instructions[idx] = (Instruction::CMPA(lhs), lhs_comment); instructions[idx + 1] = (Instruction::BEQ(jump_adr), None); @@ -553,7 +555,7 @@ fn cmp_gt_jmp(instructions: &mut Vec) { let mut idx = 0; while instructions.len() >= 6 && idx < instructions.len() - 6 { if let ( - (Instruction::PSHA, Some("gt rhs")), + (Instruction::PSHA, Some(text)), (Instruction::LDA(lhs), lhs_comment), (Instruction::JSR(Addressing::Label(function_name)), None), (Instruction::LEASP(Addressing::SP(1)), None), @@ -567,7 +569,7 @@ fn cmp_gt_jmp(instructions: &mut Vec) { &instructions[idx + 4], &instructions[idx + 5], ) { - if function_name != "__gt__" { + if !(function_name == "__gt__" && text == "gt rhs") { idx += 1; continue; } @@ -576,7 +578,7 @@ fn cmp_gt_jmp(instructions: &mut Vec) { } else { lhs.clone() }; - let lhs_comment = *lhs_comment; + let lhs_comment = lhs_comment.clone(); let jump_adr = jump_adr.clone(); instructions[idx] = (Instruction::CMPA(lhs), lhs_comment); instructions[idx + 1] = (Instruction::BGE(jump_adr), None); @@ -595,7 +597,7 @@ fn cmp_gte_jmp(instructions: &mut Vec) { let mut idx = 0; while instructions.len() >= 7 && idx < instructions.len() - 7 { if let ( - (Instruction::PSHA, Some("lte rhs")), + (Instruction::PSHA, Some(text)), (Instruction::LDA(lhs), lhs_comment), (Instruction::JSR(Addressing::Label(function_name)), None), (Instruction::LEASP(Addressing::SP(1)), None), @@ -611,7 +613,7 @@ fn cmp_gte_jmp(instructions: &mut Vec) { &instructions[idx + 5], &instructions[idx + 6], ) { - if function_name != "__gt__" { + if !(function_name == "__gt__" && text == "lte rhs") { idx += 1; continue; } @@ -620,7 +622,7 @@ fn cmp_gte_jmp(instructions: &mut Vec) { } else { lhs.clone() }; - let lhs_comment = *lhs_comment; + let lhs_comment = lhs_comment.clone(); let jump_adr = jump_adr.clone(); instructions[idx] = (Instruction::CMPA(lhs), lhs_comment); instructions[idx + 1] = (Instruction::BLT(jump_adr), None); diff --git a/src/parser.rs b/src/parser.rs index 50df2a3..6eee5c0 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,4 +1,5 @@ use crate::*; +use std::borrow::Cow; pub(crate) fn parse<'a>( source: &'a str, @@ -40,7 +41,7 @@ fn construct_structure_from_tokens<'a>( let code_parsed = construct_block(&code_tokenised, move_first)?; LanguageElement::FunctionDeclaration { typ: t.clone(), - name: *n, + name: Cow::Borrowed(n), args: args_parsed, block: code_parsed, } @@ -66,7 +67,7 @@ fn construct_structure_from_tokens<'a>( let rhs_parsed = StatementElement::from_tokens(rhs_verified)?; LanguageElement::VariableDeclarationAssignment { typ, - name, + name: Cow::Borrowed(name), value: rhs_parsed, is_static: false, } @@ -92,7 +93,7 @@ fn construct_structure_from_tokens<'a>( let rhs_parsed = StatementElement::from_tokens(rhs_verified)?; LanguageElement::VariableDeclarationAssignment { typ, - name, + name: Cow::Borrowed(name), value: rhs_parsed, is_static: true, } @@ -105,7 +106,7 @@ fn construct_structure_from_tokens<'a>( let rhs_parsed = StatementElement::from_tokens(rhs_verified)?; LanguageElement::VariableDeclarationAssignment { typ: t.clone(), - name: *n, + name: Cow::Borrowed(n), value: rhs_parsed, is_static: false, } @@ -118,7 +119,7 @@ fn construct_structure_from_tokens<'a>( let rhs_parsed = StatementElement::from_tokens(rhs_verified)?; LanguageElement::VariableDeclarationAssignment { typ: t.clone(), - name: *n, + name: Cow::Borrowed(n), value: rhs_parsed, is_static: true, } @@ -130,7 +131,7 @@ fn construct_structure_from_tokens<'a>( let rhs_verified = StatementToken::from_tokens(rhs)?; let rhs_parsed = StatementElement::from_tokens(rhs_verified)?; LanguageElement::VariableAssignment { - name: *n, + name: Cow::Borrowed(n), value: rhs_parsed, } } @@ -150,14 +151,14 @@ fn construct_structure_from_tokens<'a>( //Variable declaration (without init) [Decl(t), Token::Name(n)] => LanguageElement::VariableDeclaration { typ: t.clone(), - name: *n, + name: Cow::Borrowed(n), is_static: false, }, //Static variable declaration (without init) [Static, Decl(t), Token::Name(n)] => LanguageElement::VariableDeclaration { typ: t.clone(), - name: *n, + name: Cow::Borrowed(n), is_static: true, }, @@ -286,7 +287,7 @@ pub(crate) fn type_check( is_static: _, } => variables.push(Variable { typ: typ.clone(), - name: *name, + name: name.as_ref(), }), LanguageElement::VariableAssignment { name: _, value } => { @@ -303,7 +304,7 @@ pub(crate) fn type_check( } => { variables.push(Variable { typ: typ.clone(), - name: *name, + name: name.as_ref(), }); if !value.type_check(&variables, &functions)? { return Ok(false); @@ -326,7 +327,7 @@ pub(crate) fn type_check( } => { functions.push(Function { return_type: typ.clone(), - name: *name, + name: name.as_ref(), parametres: args.clone(), }); diff --git a/src/statement_element.rs b/src/statement_element.rs index d14619b..4c7a9d0 100644 --- a/src/statement_element.rs +++ b/src/statement_element.rs @@ -1,4 +1,5 @@ use crate::*; +use std::borrow::Cow; ///Tree structure to represent a statement. Boolean and bitwise logic are combined #[derive(Debug, Clone, PartialEq)] @@ -71,16 +72,16 @@ pub(crate) enum StatementElement<'a> { rhs: Box>, }, FunctionCall { - name: &'a str, + name: Cow<'a, str>, parametres: Vec>, }, - Var(&'a str), + Var(Cow<'a, str>), Num(isize), Char(char), Bool(bool), Array(Vec>), Deref(Box>), - AdrOf(&'a str), + AdrOf(Cow<'a, str>), } ///Takes two `StatementElement`s and returns a single `StatementElement`. All lifetimes are the same @@ -184,15 +185,18 @@ impl<'a> StatementElement<'a> { StatementToken::Bool(b) => Parsed(StatementElement::Bool(b)), StatementToken::Char(c) => Parsed(StatementElement::Char(c)), StatementToken::Num(n) => Parsed(StatementElement::Num(n)), - StatementToken::Var(v) => Parsed(StatementElement::Var(v)), - StatementToken::AdrOf(n) => Parsed(StatementElement::AdrOf(n)), + StatementToken::Var(v) => Parsed(StatementElement::Var(Cow::Borrowed(v))), + StatementToken::AdrOf(n) => Parsed(StatementElement::AdrOf(Cow::Borrowed(n))), StatementToken::FunctionCall(name, ts) => { let parametres = ts .into_iter() .map(StatementElement::from_tokens) .collect::, _>>()?; - Parsed(StatementElement::FunctionCall { name, parametres }) + Parsed(StatementElement::FunctionCall { + name: Cow::Borrowed(name), + parametres, + }) } StatementToken::Array(arr) => { @@ -205,7 +209,7 @@ impl<'a> StatementElement<'a> { StatementToken::ArrayAccess { ptr, idx } => { Parsed(StatementElement::Deref(Box::new(StatementElement::Add { - lhs: Box::new(StatementElement::Var(ptr)), + lhs: Box::new(StatementElement::Var(Cow::Borrowed(ptr))), rhs: Box::new(StatementElement::from_tokens(idx)?), }))) } @@ -399,13 +403,13 @@ impl<'a> StatementElement<'a> { parametres: _, } => functions .iter() - .find(|f| &f.name == name) + .find(|f| f.name == name) .map(|f| f.return_type.clone()) .ok_or(ParseError(line!(), "Cannot resolve function!"))?, StatementElement::Var(name) => variables .iter() - .find(|f| &f.name == name) + .find(|f| f.name == name) .map(|v| v.typ.clone()) .ok_or(ParseError(line!(), "Cannot resolve variable!"))?, @@ -420,7 +424,7 @@ impl<'a> StatementElement<'a> { StatementElement::AdrOf(name) => Type::Ptr(Box::new( variables .iter() - .find(|f| &f.name == name) + .find(|f| f.name == name) .map(|v| v.typ.clone()) .ok_or(ParseError(line!(), "Cannot resolve variable!"))?, )), @@ -435,7 +439,7 @@ impl<'a> StatementElement<'a> { ) -> Result { let res = match self { StatementElement::FunctionCall { name, parametres } => { - if let Some(f) = functions.iter().find(|f| &f.name == name) { + if let Some(f) = functions.iter().find(|f| f.name == name) { let len_eq = f.parametres.len() == parametres.len(); let types_are_eq = { for (l, r) in f