private void ExpressionToList( ExpressionLexeme expression, Lexeme lexeme, Function function, out Variable resultVar, ref int labelIndex, ref int localVarIndex, ref int regCount, List <Variable> outRegisters, FunctionInstructions instructionsSet, List <NumeratedVariable> locals, Variable storeResultTo) { ExpressionToList_GetList(expression, lexeme, function, out resultVar, ref labelIndex, ref localVarIndex, ref regCount, outRegisters, instructionsSet, locals, storeResultTo); ExpressionToList_FixIndexerAssignment(expression, lexeme, function, ref labelIndex, ref localVarIndex, ref regCount, outRegisters, instructionsSet, locals, storeResultTo); ExpressionToList_IndexerMultiply(function, ref labelIndex, instructionsSet); }
private void ExpressionToList_GetList( ExpressionLexeme expression, Lexeme lexeme, Function function, out Variable resultVar, ref int labelIndex, ref int localVarIndex, ref int regCount, List <Variable> outRegisters, FunctionInstructions instructionsSet, List <NumeratedVariable> locals, Variable storeResultTo) { var list = expression.ToList(); var labelIndexCopy = labelIndex; if (list == null) { if (expression.Root.SubTokens.Count == 1) { ExpressionToken token = expression.Root.SubTokens[0]; Variable src = ExpressionLineItem.GetVariable(locals, this, token.CodeToken); if (token.UnaryOperators.Count != 0 && token.UnaryOperators[0] != null) { var unaryRes = token.UnaryOperators[0].UnaryFunc(new OperatorOperands(function, this, labelIndexCopy++, src)); if (unaryRes.Error != null) { throw new CompileException(unaryRes.Error.ErrorType, token.CodeToken); } instructionsSet.Instructions.Add(unaryRes.Instruction); if (storeResultTo != null) { var lastInstruction = (UnaryArithmeticInstruction)unaryRes.Instruction; if (unaryRes.ResultType != storeResultTo.Type) { //but can we cast? if (!Type.CanCastAssignment(storeResultTo.Type, unaryRes.ResultType)) { throw new CompileException(CompileErrorType.IncompatibleTypes, lexeme.Tokens[0]); } var castedVar = new Variable(unaryRes.ResultType, "__unaryReg", function.Scope, null, localVarIndex++, VariableType.Variable); instructionsSet.Instructions.Add(new InstructionCast(storeResultTo, castedVar, function, this, labelIndexCopy++)); lastInstruction.Result = castedVar; outRegisters.Add(castedVar); } else { lastInstruction.Result = storeResultTo; } resultVar = storeResultTo; } else { resultVar = (unaryRes.Instruction as UnaryArithmeticInstruction).Result; } } else { if (storeResultTo != null) { if (storeResultTo.Type != src.Type) { //Not equal, cast is needed. if (!Type.CanCastAssignment(storeResultTo.Type, src.Type)) { throw new CompileException(CompileErrorType.IncompatibleTypes, lexeme.Tokens[0]); } instructionsSet.Instructions.Add(new InstructionCast(storeResultTo, src, function, this, labelIndexCopy++)); resultVar = storeResultTo; } else { instructionsSet.Instructions.Add(new InstructionLdi(src, storeResultTo, function, this, labelIndexCopy++)); resultVar = storeResultTo; } } else { resultVar = src; } } } else { throw new CompileException(CompileErrorType.WrongOperandList, lexeme.Tokens[0]); } } else { if (function.Program.Verbose) { Console.WriteLine(string.Join("\n", list)); } List <Variable> registers; var res = ExpressionLineItem.GetInstructions(function, this, ref localVarIndex, list, out registers, locals); if ( (res.Last() is BinaryArithmeticInstruction) && ((BinaryArithmeticInstruction)res.Last()).CanBeSimplified() && (res.Count < 2 || res[res.Count - 2].Type != InstructionType.Vget || (res.Last() as BinaryArithmeticInstruction).Operand1.VariableType != VariableType.ArrayItem)) { var last = (BinaryArithmeticInstruction)res.Last(); if (last.AType == BinaryArithmeticInstructionType.A_Set && res.Count != 1) { res.RemoveAt(res.Count - 1); (res[res.Count - 1] as ArithmeticInstruction).Result = last.Operand1; } else { res[res.Count - 1] = last.Simplify(); } registers.RemoveAt(registers.Count - 1); } regCount += registers.Count; outRegisters.AddRange(registers); res.ForEach(p => p.Label = labelIndexCopy++); instructionsSet.Instructions.AddRange(res); if (storeResultTo != null) { if (!(instructionsSet.Instructions.Last() is ArithmeticInstruction)) { throw new CompileException(CompileErrorType.ExpressionIsNotVariable, lexeme.Tokens[1]); } var lastInstruction = (ArithmeticInstruction)instructionsSet.Instructions.Last(); if (lastInstruction.Result.Type != storeResultTo.Type) { //but can we cast? if (!Type.CanCastAssignment(storeResultTo.Type, lastInstruction.Result.Type)) { throw new CompileException(CompileErrorType.IncompatibleTypes, lexeme.Tokens[0]); } instructionsSet.Instructions.Add(new InstructionCast(storeResultTo, lastInstruction.Result, function, this, labelIndexCopy++)); } else { lastInstruction.Result = storeResultTo; } resultVar = storeResultTo; } else { var last = instructionsSet.Instructions.Last(); if (!(last is ArithmeticInstruction)) { resultVar = null; } else { resultVar = (last as ArithmeticInstruction).Result; } } } labelIndex = labelIndexCopy; }
private void ExpressionToList_FixIndexerAssignment( ExpressionLexeme expression, Lexeme lexeme, Function function, ref int labelIndex, ref int localVarIndex, ref int regCount, List <Variable> outRegisters, FunctionInstructions instructionsSet, List <NumeratedVariable> locals, Variable storeResultTo) { //find assignment to array elements and replace it by vset and remove first vget for (int i = 0; i < instructionsSet.Instructions.Count; i++) { Variable result = null; var simplified = false; var set = false; if (instructionsSet.Instructions[i] is ArithmeticInstruction && !(instructionsSet.Instructions[i] is InstructionVget)) { if (instructionsSet.Instructions[i] is BinaryArithmeticInstruction && (instructionsSet.Instructions[i] as BinaryArithmeticInstruction).CanBeSimplified()) { var instruction = ((BinaryArithmeticInstruction)instructionsSet.Instructions[i]); result = instruction.Operand1; simplified = true; if (instruction.AType == BinaryArithmeticInstructionType.A_Set) { set = true; } } else { result = ((ArithmeticInstruction)instructionsSet.Instructions[i]).Result; } } else { continue; } InstructionVset vset; if (result.VariableType == VariableType.ArrayItem) { if (!simplified) { var newReg = new Variable(result.Type, "__arrayReg", function.Scope, result.Token, localVarIndex++, VariableType.Variable); vset = new InstructionVset( result.Array, newReg, result.ArrayItem, function, this, labelIndex++); outRegisters.Add(newReg); instructionsSet.Instructions.Insert(i + 1, vset); var globalIndex = 0; var deleted = instructionsSet.Instructions.RemoveAll(p => { var vget = p as InstructionVget; if (vget == null) { return(false); } var used = false; for (var j = globalIndex + 1; j < instructionsSet.Instructions.Count; j++) { var count = instructionsSet.Instructions[j].FetchUsedVariables(vget.Result.Index).Count; count -= (instructionsSet.Instructions[j] as ArithmeticInstruction)?.Result.Index == vget.Result.Index ? 1 : 0; if (count > 0) { used = true; break; } } globalIndex++; return(vget.Result.Index == result.Index && !used); }); (instructionsSet.Instructions[i - deleted] as ArithmeticInstruction).Result = newReg; } else { if (!set) { instructionsSet.Instructions[i] = ((BinaryArithmeticInstruction)instructionsSet.Instructions[i]).Simplify(); vset = new InstructionVset( result.Array, (instructionsSet.Instructions[i] as ArithmeticInstruction).Result, result.ArrayItem, function, this, labelIndex++); instructionsSet.Instructions.Insert(i + 1, vset); } else { vset = new InstructionVset( result.Array, result, result.ArrayItem, function, this, labelIndex++); instructionsSet.Instructions.Insert(i + 1, vset); instructionsSet.Instructions.RemoveAt(i); instructionsSet.Instructions.RemoveAll(p => { var vget = p as InstructionVget; return(vget != null && vget.Result.Index == result.Index); }); } } } } }