Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
0
        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;
        }
Ejemplo n.º 3
0
        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);
                            });
                        }
                    }
                }
            }
        }