Esempio n. 1
0
 public OperatorOperands(Function function, ByteCode.ByteCode byteCode, int label, Variable a)
 {
     Function = function;
     ByteCode = byteCode;
     Label    = label;
     A        = a;
 }
Esempio n. 2
0
        public static Variable GetVariable(List <NumeratedVariable> locals, ByteCode.ByteCode byteCode, Token token)
        {
            if (token == null)
            {
                return(null);
            }

            var operand = locals.Find(p => p.Variable.Name == token.StringValue)?.Variable;

            if (operand == null)
            {
                if (token.Constant != null)
                {
                    operand = token.Constant.ToVariable(byteCode.Program);
                }
                else if ((operand = byteCode.Header.GetGlobalVariable(token.StringValue)) != null)
                {
                    return(operand);
                }
                else
                {
                    throw new CompileException(CompileErrorType.UndefinedReference, token);
                }
            }

            return(operand);
        }
Esempio n. 3
0
 public OperatorOperands(Function function, ByteCode.ByteCode byteCode, int label, Variable a, Variable b, ExpressionLineItem lineItem)
 {
     LineItem = lineItem;
     Function = function;
     ByteCode = byteCode;
     Label    = label;
     A        = a;
     B        = b;
 }
Esempio n. 4
0
        public static List <Instruction> GetInstructions(Function func, ByteCode.ByteCode byteCode,
                                                         ref int localVarIndex, List <ExpressionLineItem> list,
                                                         out List <Variable> registers, List <NumeratedVariable> locals)
        {
            var currentIndex = 0;
            var instructions = new List <Instruction>();

            registers = new List <Variable>();

            foreach (var item in list)
            {
                OperatorResult result   = null;
                Variable       operand1 = item.RegOperand1 == -1 ? GetVariable(locals, byteCode, item.Operand1.CodeToken) : registers[item.RegOperand1];
                Variable       operand2 = null;

                if (!item.IsUnary)
                {
                    operand2 = item.RegOperand2 == -1 ? GetVariable(locals, byteCode, item.Operand2.CodeToken) : registers[item.RegOperand2];
                    result   = item.Operator.BinaryFunc(new OperatorOperands(func, byteCode, -1, operand1, operand2, item));
                }
                else
                {
                    if (item.FunctionCall != null)
                    {
                        var funcToCall = func.Program.ByteCode.Header
                                         .GetFunction(item.FunctionCall.StringValue, item.NearToken);

                        if (funcToCall == null)
                        {
                            throw new CompileException(CompileErrorType.UndefinedReference, item.FunctionCall);
                        }

                        if (operand1 == null)
                        {
                            if (funcToCall.Parameters.Count != 0)
                            {
                                throw new CompileException(CompileErrorType.WrongParameterCount, item.FunctionCall, funcToCall.Token);
                            }

                            instructions.Add(new InstructionCall(funcToCall, func, byteCode, -1));
                        }
                        else if (operand1.VariableType != VariableType.Tuple)
                        {
                            //if variadic we dont care about types
                            if (funcToCall.IsVariadic)
                            {
                                var countAttribute =
                                    (VarCountAttribute)funcToCall.Attributes.Find(p => p.Type == AttributeType.VarCount);

                                var restrictAttributes =
                                    funcToCall.Attributes.FindAll(p => p.Type == AttributeType.VarRestrict)
                                    .Select(p => (VarRestrictAttribute)p)
                                    .ToList();

                                //User can specify parameters count in a variadic function
                                if (countAttribute != null)
                                {
                                    if (!countAttribute.CheckCount(1))
                                    {
                                        throw new CompileException(CompileErrorType.WrongParameterCount,
                                                                   item.FunctionCall);
                                    }
                                }

                                foreach (var attribute in restrictAttributes)
                                {
                                    if (!attribute.CheckValues(new List <Variable>()
                                    {
                                        operand1
                                    }))
                                    {
                                        throw new CompileException(CompileErrorType.IncompatibleTypes,
                                                                   item.FunctionCall);
                                    }
                                }

                                instructions.Add(new InstructionPushI(
                                                     -byteCode.Header.GetTypeIndex(operand1.Type) - 1, func, byteCode, -1));
                                instructions.Add(new InstructionPush(operand1, func, byteCode, -1));

                                //just one variable
                                instructions.Add(new InstructionPushI(-1 - 1, func, byteCode, -1));
                            }
                            else
                            {
                                if (funcToCall.Parameters.Count != 1)
                                {
                                    throw new CompileException(CompileErrorType.WrongParameterCount, item.FunctionCall, funcToCall.Token);
                                }

                                if (funcToCall.Parameters[0].Type != operand1.Type)
                                {
                                    //not equals, but can we cast?
                                    if (!Type.CanCastAssignment(funcToCall.Parameters[0].Type, operand1.Type))
                                    {
                                        throw new CompileException(CompileErrorType.IncompatibleTypes, item.FunctionCall, funcToCall.Token);
                                    }

                                    //casting
                                    var varCast = new Variable(funcToCall.Parameters[0].Type, $"_castedReg{localVarIndex}",
                                                               func.Scope, null, localVarIndex++, VariableType.Variable);
                                    instructions.Add(new InstructionCast(varCast, operand1, func, byteCode, -1));
                                    operand1 = varCast;
                                }

                                instructions.Add(new InstructionPush(operand1, func, byteCode, -1));
                            }
                            instructions.Add(new InstructionCall(funcToCall, func, byteCode, -1));
                        }
                        else
                        {
                            //if variadic we dont care about types
                            if (funcToCall.IsVariadic)
                            {
                                var countAttribute =
                                    (VarCountAttribute)funcToCall.Attributes.Find(p => p.Type == AttributeType.VarCount);

                                var restrictAttributes =
                                    funcToCall.Attributes.FindAll(p => p.Type == AttributeType.VarRestrict)
                                    .Select(p => (VarRestrictAttribute)p)
                                    .ToList();

                                //User can specify parameters count in a variadic function
                                if (countAttribute != null)
                                {
                                    if (!countAttribute.CheckCount(operand1.Tuple.Count))
                                    {
                                        throw new CompileException(CompileErrorType.WrongParameterCount, item.FunctionCall);
                                    }
                                }

                                foreach (var attribute in restrictAttributes)
                                {
                                    if (!attribute.CheckValues(operand1.Tuple))
                                    {
                                        throw new CompileException(CompileErrorType.IncompatibleTypes, item.FunctionCall);
                                    }
                                }

                                foreach (var variable in operand1.Tuple.ToArray().Reverse())
                                {
                                    instructions.Add(new InstructionPushI(-byteCode.Header.GetTypeIndex(variable.Type) - 1, func, byteCode, -1));
                                    instructions.Add(new InstructionPush(variable, func, byteCode, -1));
                                }
                                instructions.Add(new InstructionPushI(-operand1.Tuple.Count - 1, func, byteCode, -1));
                            }
                            else
                            {
                                if (funcToCall.Parameters.Count != operand1.Tuple.Count)
                                {
                                    throw new CompileException(CompileErrorType.WrongParameterCount, item.FunctionCall,
                                                               funcToCall.Token);
                                }

                                for (int i = 0; i < operand1.Tuple.Count; i++)
                                {
                                    if (funcToCall.Parameters[i].Type != operand1.Tuple[i].Type)
                                    {
                                        //not equals, but can we cast?
                                        if (!Type.CanCastAssignment(funcToCall.Parameters[i].Type,
                                                                    operand1.Tuple[i].Type))
                                        {
                                            throw new CompileException(CompileErrorType.IncompatibleTypes,
                                                                       item.FunctionCall, funcToCall.Token);
                                        }

                                        //casting
                                        var varCast = new Variable(funcToCall.Parameters[i].Type,
                                                                   $"__castedReg{localVarIndex}", func.Scope, null, localVarIndex++,
                                                                   VariableType.Variable);
                                        instructions.Add(new InstructionCast(varCast, operand1.Tuple[i], func, byteCode,
                                                                             -1));
                                        operand1.Tuple[i] = varCast;
                                    }
                                }

                                for (int i = 0; i < operand1.Tuple.Count; i++)
                                {
                                    instructions.Add(new InstructionPush(operand1.Tuple[i], func, byteCode, -1));
                                }

                                //I dunno what is it, just comment it.
                                //registers.RemoveRange(registers.Count - funcToCall.Parameters.Count + 1, funcToCall.Parameters.Count- 1);
                                //localVarIndex -= funcToCall.Parameters.Count - 1;

                                /*for (int i = currentIndex + 1; i < list.Count; i++)
                                 * {
                                 *  if (list[i].RegOperand1 != -1) list[i].RegOperand1 -= funcToCall.Parameters.Count - 1;
                                 *  if (list[i].RegOperand2 != -1) list[i].RegOperand2 -= funcToCall.Parameters.Count - 1;
                                 * }*/
                            }

                            instructions.Add(new InstructionCall(funcToCall, func, byteCode, -1));
                        }

                        if (funcToCall.ReturnType != null)
                        {
                            registers.Add(new Variable(funcToCall.ReturnType, $"__reg{localVarIndex}", func.Scope, null, localVarIndex++, VariableType.Variable));
                            //pop out result
                            instructions.Add(new InstructionPop(registers.Last(), func, byteCode, -1));
                        }
                        else if (currentIndex != list.Count - 1)
                        {
                            throw new CompileException(CompileErrorType.WrongUsageOfVoidFunc, item.NearToken, funcToCall.Token);
                        }
                    }
                    else if (item.UnaryOperator != null)
                    {
                        result = item.UnaryOperator.UnaryFunc(new OperatorOperands(func, byteCode, -1, operand1));
                    }
                    else if (item.Indexer != null)
                    {
                        var array = GetVariable(locals, byteCode, item.Indexer);

                        if (array.Type.ID != TypeID.Array)
                        {
                            throw new CompileException(CompileErrorType.ExpectedArrayType, item.NearToken);
                        }

                        var resultType = (array.Type as ArrayType).BaseType;
                        var arrayDim   = (array.Type as ArrayType).Dimensions;

                        var indexes = new List <Variable>();

                        if (operand1.VariableType == VariableType.Tuple)
                        {
                            if (operand1.Tuple.Count != arrayDim)
                            {
                                throw new CompileException(CompileErrorType.WrongIndicesCount, item.NearToken);
                            }

                            foreach (var variable in operand1.Tuple)
                            {
                                if (variable.Type.ID != TypeID.Integer && variable.Type.ID != TypeID.UInteger)
                                {
                                    throw new CompileException(CompileErrorType.ExpectedIntegerIndex, item.NearToken);
                                }
                            }

                            indexes.AddRange(operand1.Tuple);
                        }
                        else
                        {
                            if (arrayDim != 1)
                            {
                                throw new CompileException(CompileErrorType.WrongIndicesCount, item.NearToken);
                            }

                            if (operand1.Type.ID != TypeID.Integer && operand1.Type.ID != TypeID.UInteger)
                            {
                                throw new CompileException(CompileErrorType.ExpectedIntegerIndex, item.NearToken);
                            }

                            indexes.Add(operand1);
                        }

                        var resultVar = new Variable(resultType, $"__reg{localVarIndex}", func.Scope,
                                                     null, localVarIndex++, VariableType.ArrayItem)
                        {
                            Array     = array,
                            ArrayItem = indexes
                        };

                        registers.Add(resultVar);

                        instructions.Add(new InstructionVget(resultVar, array, indexes, func, byteCode, -1));
                    }
                }

                if (item.FunctionCall == null && item.Indexer == null)
                {
                    if (result.Error != null)
                    {
                        throw new CompileException(result.Error.ErrorType, item.NearToken);
                    }

                    if (result.UsedCasts != null && result.UsedCasts.Count != 0)
                    {
                        instructions.AddRange(result.UsedCasts);
                        foreach (var cast in result.UsedCasts)
                        {
                            cast.Result.Index = localVarIndex++;
                            //registers.Add(cast.Dest);
                        }
                    }

                    var resultVar = new Variable(result.ResultType, $"__reg{localVarIndex}", func.Scope, null, localVarIndex++,
                                                 result.Instruction == null ? VariableType.Tuple : VariableType.Variable);

                    if (result.Instruction != null)
                    {
                        instructions.Add(result.Instruction);
                        (result.Instruction as ArithmeticInstruction).Result = resultVar;
                    }
                    else
                    {
                        resultVar.Tuple = result.ResultTuple;
                    }

                    registers.Add(resultVar);
                }

                currentIndex++;
            }

            registers.AddRange(instructions.FindAll(p => p is InstructionCast)
                               .Select(p => ((InstructionCast)p).Result));

            registers = registers.OrderBy(p => p.Index).ToList();

            return(instructions);
        }