private static OperatorResult SetFunc(OperatorOperands operands, BinaryArithmeticInstructionType operatorType) { //if(!operands.A.Type.Equals(operands.B.Type)) //return new OperatorResult(new CompileError(CompileErrorType.IncompatibleTypes, operands.A.Token)); //if(operands.LineItem.Operand1 == null) // return new OperatorResult(new CompileError(CompileErrorType.WrongAssignmentOperation, operands.A.Token)); if (operands.A.VariableType != VariableType.Variable && operands.A.VariableType != VariableType.ArrayItem) { return(new OperatorResult(new CompileError(CompileErrorType.WrongAssignmentOperation, operands.A.Token))); } if (!Type.CanCastAssignment(operands.A.Type, operands.B.Type)) { return(new OperatorResult(new CompileError(CompileErrorType.IncompatibleTypes, operands.A.Token))); } var casts = new List <InstructionCast>(); if (operands.B.Type != operands.A.Type) { var castedB = new Variable(operands.A.Type, "__castedReg", operands.Function.Scope, operands.B.Token, -1, VariableType.Variable); casts.Add(new InstructionCast( castedB, operands.B, operands.Function, operands.ByteCode, operands.Label )); operands.B = castedB; } return(new OperatorResult(new BinaryArithmeticInstruction(operatorType, null, operands.A, operands.B, operands.Function, operands.ByteCode, operands.Label), operands.A.Type, casts)); }
private void GetInstructionList(Lexeme rootLexeme, Function function, ref int localVarIndex, ref int regCount, ref int labelIndex, List <Variable> registers, FunctionInstructions instructionsSet, List <NumeratedVariable> locals) { foreach (var lexeme in rootLexeme.ChildLexemes) { //localVarIndex = locals.Count; switch (lexeme.Type) { case LexemeType.Block: break; case LexemeType.Var: { //Calculate expression var expression = ((VarLexeme)lexeme).Expression; //declaration only if (expression == null) { continue; } var storeResult = locals.Find(p => p.Index == ((VarLexeme)lexeme).Index + Program.ProgramGlobals.Count).Variable; Variable variable; ExpressionToList(expression, lexeme, function, out variable, ref labelIndex, ref localVarIndex, ref regCount, registers, instructionsSet, locals, storeResult); } break; case LexemeType.If: { var ifLexeme = lexeme as IfLexeme; //Calculate expression var expression = ((IfLexeme)lexeme).Expression; Variable variable; ExpressionToList(expression, lexeme, function, out variable, ref labelIndex, ref localVarIndex, ref regCount, registers, instructionsSet, locals, null); if (variable == null) { throw new CompileException(CompileErrorType.ExpressionIsNotVariable, lexeme.Tokens[1]); } instructionsSet.Instructions.Add(new InstructionBrEq(variable, -1, function, this, labelIndex++)); var eq = instructionsSet.Instructions.Last() as InstructionBrEq; //Proceed block GetInstructionList(ifLexeme.Block, function, ref localVarIndex, ref regCount, ref labelIndex, registers, instructionsSet, locals); if (ifLexeme.ElseLexeme != null) { instructionsSet.Instructions.Add(new InstructionJmp(-1, function, this, labelIndex++)); var jmp = instructionsSet.Instructions.Last() as InstructionJmp; eq.Index = labelIndex; //Proceed else block GetInstructionList(ifLexeme.ElseLexeme.Block, function, ref localVarIndex, ref regCount, ref labelIndex, registers, instructionsSet, locals); jmp.Index = labelIndex; } else { eq.Index = labelIndex; } } break; case LexemeType.Expression: { //Calculate expression Variable variable; ExpressionToList((ExpressionLexeme)lexeme, lexeme, function, out variable, ref labelIndex, ref localVarIndex, ref regCount, registers, instructionsSet, locals, null); } break; case LexemeType.While: { var whileLexeme = lexeme as WhileLexeme; int startIndex = labelIndex; //Calculate expression var expression = whileLexeme.Expression; Variable variable; ExpressionToList(expression, lexeme, function, out variable, ref labelIndex, ref localVarIndex, ref regCount, registers, instructionsSet, locals, null); if (variable == null) { throw new CompileException(CompileErrorType.ExpressionIsNotVariable, lexeme.Tokens[1]); } instructionsSet.Instructions.Add(new InstructionBrEq(variable, -1, function, this, labelIndex++)); var eq = instructionsSet.Instructions.Last() as InstructionBrEq; //Proceed block GetInstructionList(whileLexeme.Block, function, ref localVarIndex, ref regCount, ref labelIndex, registers, instructionsSet, locals); instructionsSet.Instructions.Add( new InstructionJmp(startIndex, function, this, labelIndex++)); eq.Index = labelIndex; } break; case LexemeType.Return: { //Calculate expression Variable variable; ExpressionToList(((ReturnLexeme)lexeme).Expression, lexeme, function, out variable, ref labelIndex, ref localVarIndex, ref regCount, registers, instructionsSet, locals, null); if (variable.Type != function.ReturnType) { //but can we cast? if (!Type.CanCastAssignment(function.ReturnType, variable.Type)) { throw new CompileException(CompileErrorType.IncompatibleTypes, lexeme.Tokens[1]); } //casting var castedVar = new Variable(function.ReturnType, "__castedReg", function.Scope, null, localVarIndex++, VariableType.Variable); instructionsSet.Instructions.Add(new InstructionCast(castedVar, variable, function, this, labelIndex++)); variable = castedVar; registers.Add(castedVar); } instructionsSet.Instructions.Add(new InstructionPush(variable, function, this, labelIndex++)); } break; } } }
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; }