コード例 #1
0
ファイル: InstructionsTask.cs プロジェクト: Coestaris/hasm
        private List <FlashElement> GetFlashElementsNoArguents(Runtime.Structures.Units.Function function, SourceLineInstruction line, out ParseError error)
        {
            Integer currentInstructionProgramIndex = (Integer)function.CompileCache.InstructionIndex++;

            var result = new List <FlashElement>();

            error = null;

            if (line.Instruction.ParameterCount != 0)
            {
                error = new ParseError(
                    ParseErrorType.Syntax_Instruction_WrongParameterCount,
                    line.LineIndex,
                    (line.Comment != null ? line.Comment.Length : 0) + line.Instruction.NameString.Length,
                    line.FileName);
                return(null);
            }

            if (!string.IsNullOrEmpty(line.Label))
            {
                RegisterConstant(function, line.Label, (ulong)currentInstructionProgramIndex);
            }

            result.Add(new FlashElementInstruction(line.Instruction, null, currentInstructionProgramIndex));
            return(result);
        }
コード例 #2
0
        private ParseError Other(Runtime.Structures.Units.Function function)
        {
            //Если размер программы превышает максимально допустимый для этой машины
            int totalFlashSize = function.CompileCache.Compiled.Sum(p => p.FixedSize);

            if (totalFlashSize > source.Machine.Flash)
            {
                return(new ParseError(ParseErrorType.Other_OutOfFlash, function.Directive));
            }
            return(null);
        }
コード例 #3
0
ファイル: InstructionsTask.cs プロジェクト: Coestaris/hasm
 private List <FlashElement> ProceedInstruction(Runtime.Structures.Units.Function function, SourceLineInstruction line, out ParseError error)
 {
     if (line.Parameters == null)
     {
         return(GetFlashElementsNoArguents(function, line, out error));
     }
     else
     {
         return(GetFlashElementsWithArguents(function, line, out error));
     }
 }
コード例 #4
0
        private ParseError JoinComponents(Runtime.Structures.Units.Function function)
        {
            //Пихаем в ее начало
            function.CompileCache.Compiled.InsertRange(0, Constnants.Select(
                                                           p => new FlashElementConstant(p.Value, p.NewIndex)));

            //Пихаем в ее начало
            function.CompileCache.Compiled.InsertRange(0, Expressions);

            function.CompileCache.Compiled.AddRange(Instructions);

            return(null);
        }
コード例 #5
0
ファイル: InstructionsTask.cs プロジェクト: Coestaris/hasm
        private ParseError ParseFunction(Runtime.Structures.Units.Function function)
        {
            function.CompileCache.Compiled = new List <FlashElement>();
            for (int i = 0; i < function.RawLines.Count; i++)
            {
                SourceLineInstruction instruction = new SourceLineInstruction(
                    function.RawLines[i].Input,
                    function.RawLines[i].LineIndex,
                    function.RawLines[i].FileName);
                ParseError error = instruction.Parse();

                function.RawLines[i] = instruction;

                if (error != null)
                {
                    return(error);
                }
            }

            //Разбираем логику типов и пр.
            foreach (SourceLineInstruction line in function.RawLines)
            {
                if (line.IsEmpty)
                {
                    continue;
                }

                ParseError parseError;
                var        res = ProceedInstruction(function, line, out parseError);
                if (parseError != null)
                {
                    return(parseError);
                }

                function.CompileCache.Compiled.AddRange(res);
            }

            //Просматриваем все наши "отложенные" константы
            //Если среди них есть пустые, то бьем тревогу!
            foreach (var item in function.CompileCache.UnknownLabelNameErrorList)
            {
                if (item.memZoneFlashElementConstant.isEmpty)
                {
                    return(item.ParseError);
                }
            }

            return(null);
        }
コード例 #6
0
        private ParseError CheckRetEnding(Runtime.Structures.Units.Function function)
        {
            if (Instructions.Count == 0)
            {
                return(new ParseError(ParseErrorType.Other_FunctionMustEndsWithPassOrRet, function.Directive));
            }

            var last = Instructions.Last();

            if (last.InstructionNumber != (Integer)_retInstructionIndex && last.InstructionNumber != (Integer)_passInstructionIndex)
            {
                return(new ParseError(ParseErrorType.Other_FunctionMustEndsWithPassOrRet, function.Directive));
            }

            return(null);
        }
コード例 #7
0
        private ParseError ResolveConsts(Runtime.Structures.Units.Function function)
        {
            Dictionary <Integer, Integer> plainConstIndexes = new Dictionary <Integer, Integer>();
            Integer ind = (Integer)0;

            //Помещаем все константы в начало флеша для удобства дебага
            //Выбираем с массива константы
            Constnants = function.CompileCache.Compiled
                         .FindAll(p => p.Type == FlashElementType.Constant)
                         .Select(p => p as FlashElementConstant)
                         .GroupBy(p => p.Value)
                         .Select(p =>
            {
                List <Integer> indexes = new List <Integer>();

                foreach (var item in p)
                {
                    indexes.Add(item.Index);
                    plainConstIndexes.Add(item.Index, ind);
                }

                ConstnantGrouping grouping = new ConstnantGrouping(p.Key, indexes, ind);
                ind += (Integer)1;

                return(grouping);
            })
                         .ToList();

            //Удаляем их из коллекции
            function.CompileCache.Compiled.RemoveAll(p => p.Type == FlashElementType.Constant);

            foreach (FlashElementInstruction instruction in Instructions)
            {
                if (instruction.Parameters != null)
                {
                    foreach (ObjectReference reference in instruction.Parameters)
                    {
                        if (reference.Type == ReferenceType.Constant)
                        {
                            reference.Index = plainConstIndexes[reference.Index];
                        }
                    }
                }
            }

            return(null);
        }
コード例 #8
0
        private ParseError GetComponents(Runtime.Structures.Units.Function function)
        {
            Instructions = function.CompileCache.Compiled
                           .FindAll(p => p.Type == FlashElementType.Instruction)
                           .Select(p => p as FlashElementInstruction)
                           .ToList();

            Expressions = function.CompileCache.Compiled
                          .FindAll(p => p.Type == FlashElementType.Expression)
                          .Select(p => p as FlashElementExpression)
                          .ToList();

            //Удаляем их из коллекции
            function.CompileCache.Compiled.RemoveAll(p => p.Type == FlashElementType.Expression);

            //Удаляем их из коллекции
            function.CompileCache.Compiled.RemoveAll(p => p.Type == FlashElementType.Instruction);

            return(null);
        }
コード例 #9
0
        private ParseError ResolveExpressions(Runtime.Structures.Units.Function function)
        {
            Dictionary <Integer, Integer> plainExpIndexes = new Dictionary <Integer, Integer>();

            for (int i = Expressions.Count - 1; i >= 0; i--)
            {
                var flashElement = Expressions[i];
                flashElement.Expression.Calculate(null, false, true);

                if (flashElement.Expression.TokenTree.Value != null)
                {
                    Integer constIndex = (Integer)(++function.CompileCache.ConstIndex);
                    //Integer constIndex = (Integer)0;

                    function.CompileCache.Compiled.Add(new FlashElementConstant(
                                                           flashElement.Expression.TokenTree.Value,
                                                           constIndex));

                    plainExpIndexes.Add(flashElement.Index, constIndex);

                    Expressions.RemoveAt(i);
                }
            }

            foreach (FlashElementInstruction instruction in Instructions)
            {
                if (instruction.Parameters != null)
                {
                    foreach (ObjectReference reference in instruction.Parameters)
                    {
                        if (reference.Type == ReferenceType.Expression && plainExpIndexes.ContainsKey(reference.Index))
                        {
                            reference.Index = plainExpIndexes[reference.Index];
                            reference.Type  = ReferenceType.Constant;
                        }
                    }
                }
            }

            return(null);
        }
コード例 #10
0
ファイル: InstructionsTask.cs プロジェクト: Coestaris/hasm
        private FlashElementConstant RegisterConstant(Runtime.Structures.Units.Function function, string name, ulong value)
        {
            if (function.CompileCache.UnknownLabelNameErrorList.Exists(p => p.Name == name))
            {
                var info = function.CompileCache.UnknownLabelNameErrorList.Find(p => p.Name == name);

                info.namedConstant.Constant = new Constant(value);
                info.memZoneFlashElementConstant.UpdateValue(new Constant((Integer)value), info.ConstIndex);
                return(null);
            }

            int constIndex = ++function.CompileCache.ConstIndex;

            var constant = new FlashElementConstant(new Constant((Integer)value), (Integer)constIndex);

            function.CompileCache.NamedConsts.Add(new ConstantMark(name, (Integer)constIndex, new Constant(value))
            {
                FEReference = constant
            });

            return(constant);
        }
コード例 #11
0
ファイル: InstructionsTask.cs プロジェクト: Coestaris/hasm
        private List <FlashElement> GetFlashElementsWithArguents(Runtime.Structures.Units.Function function, SourceLineInstruction line, out ParseError error)
        {
            Integer currentInstructionProgramIndex = (Integer)(function.CompileCache.InstructionIndex++);
            var     result = new List <FlashElement>();

            if (line.Parameters.Length != line.Instruction.ParameterCount)
            {
                error = new ParseError(
                    ParseErrorType.Syntax_Instruction_WrongParameterCount,
                    line.LineIndex,
                    line.Comment.Length + line.Instruction.NameString.Length,
                    line.FileName);
                return(null);
            }

            if (!string.IsNullOrEmpty(line.Label))
            {
                RegisterConstant(function, line.Label, (ulong)currentInstructionProgramIndex);
            }

            int argIndex    = -1;
            var usedIndexes = new List <ObjectReference>();

            foreach (var argument in line.Parameters)
            {
                argIndex++;

                //Попытка пропарсить константу
                Constant   constant;
                ParseError constError = Constant.Parse(argument, out constant);

                //Попытка пропарсить выражение
                Expression expression;
                ParseError expressionError = expressionError = Expression.Parse(argument, out expression);

                //Грубое определние типа нашего аргумента
                bool isConst = constant != null;
                bool isVar   = function.CompileCache.Variables.Select(p => p.Name).Contains(argument);

                //Если допустимо выражение и если это не просто выражение
                if (line.Instruction.ParameterTypes[argIndex].HasFlag(InstructionParameterType.Expression) && expressionError == null &&
                    (!expression.TokenTree.IsSimple || expression.TokenTree.UnaryFunction != null || expression.TokenTree.UnaryOperator != null))
                {
                    try
                    {
                        Expression.Precompile(expression.TokenTree,
                                              (token) =>
                        {
                            var variable = function.CompileCache.Variables.Find(p => p.Name == token.RawValue);
                            if (variable != null)
                            {
                                //Получаем индекс переменной со списка переменных
                                Integer varIndex = function.CompileCache.Variables.Find(p => p.Name == token.RawValue).Index;
                                //Запоминаем индекс переменной
                                return(new ObjectReference((Integer)varIndex, ReferenceType.Variable)
                                {
                                    Object = null
                                });
                            }

                            //То, возможно, это именная константа...
                            if (function.CompileCache.NamedConsts.Select(p => p.Name).Contains(token.RawValue))
                            {
                                //Получения индекса константы со списка
                                int constantIndex = function.CompileCache.NamedConsts.Select(p => p.Name).ToList().IndexOf(token.RawValue);

                                return(new ObjectReference(function.CompileCache.NamedConsts[constantIndex].Index, ReferenceType.Constant)
                                {
                                    Object = function.CompileCache.NamedConsts[constantIndex].FEReference
                                });
                            }
                            else
                            {
                                //Константа не найдена! Логично было бы выкинуть ошибку
                                //Но жива еще надежда на то, что она будет объявлена чуть позже.
                                //Потому сейчас внесем ее сюда. Создадим новую "пустую" константу во флеше,
                                //И если она таки будет найдена, то подменим ее настоящим значением


                                //Елси на эту неведомую херню уже ссылались, то сошлемся на нее же
                                if (function.CompileCache.UnknownLabelNameErrorList.Exists(p => p.Name == token.RawValue))
                                {
                                    var item = function.CompileCache.UnknownLabelNameErrorList.Find(p => p.Name == token.RawValue);
                                    //После такой "грязной" хуйни мне хочется сходить с душ!
                                    return(new ObjectReference((Integer)item.ConstIndex, ReferenceType.Constant)
                                    {
                                        Object = function.CompileCache.UnknownLabelNameErrorList.Find(p => p.Name == token.RawValue).memZoneFlashElementConstant
                                    });
                                }
                                else
                                {
                                    int constIndex = ++function.CompileCache.ConstIndex;
                                    FlashElementConstantDummy dummyConstant = new FlashElementConstantDummy((Integer)constIndex);
                                    ConstantMark dummyNamedConstant         = new ConstantMark(token.RawValue, (Integer)constIndex, new Constant(BaseIntegerType.CommonType))
                                    {
                                        FEReference = dummyConstant
                                    };

                                    function.CompileCache.UnknownLabelNameErrorList.Add(new ConstantErrorMark(
                                                                                            token.RawValue,
                                                                                            NewParseError(ParseErrorType.Syntax_UnknownConstName, line, argIndex),
                                                                                            (Integer)constIndex,
                                                                                            dummyNamedConstant, dummyConstant));

                                    function.CompileCache.NamedConsts.Add(dummyNamedConstant);
                                    //Записываем его во флеш память
                                    result.Add(dummyConstant);

                                    return(new ObjectReference((Integer)constIndex, ReferenceType.Constant)
                                    {
                                        Object = dummyConstant
                                    });
                                }
                            }
                        }

                                              /*,(c) =>
                                               * {
                                               *  //Расчет нового индекса константы
                                               *  int constIndex = ++function.CompileCache.ConstIndex;
                                               *  //Записываем его во флеш память
                                               *  var flashElement = c.ToFlashElement((Integer)constIndex);
                                               *
                                               *  result.Add(flashElement);
                                               *
                                               *  return new ObjectReference((Integer)constIndex, ReferenceType.Constant)
                                               *  {
                                               *      Object = flashElement
                                               *  };
                                               *
                                               * }*/);

                        Integer index = (Integer)(++function.CompileCache.ExpressionIndex);
                        result.Add(new FlashElementExpression(expression, index));
                        usedIndexes.Add(new ObjectReference(index, ReferenceType.Expression));
                    }
                    catch (ConstantOverflowException ex)
                    {
                        error = NewParseError(ex.Type, line, argIndex);
                        return(null);
                    }
                }
                else
                {
                    if (line.Instruction.ParameterTypes[argIndex] == InstructionParameterType.NewVariable)
                    {
                        function.CompileCache.VarIndex++;
                        function.CompileCache.Variables.Add(new VariableMark(argument)
                        {
                            Index = (Integer)function.CompileCache.VarIndex
                        });
                        usedIndexes.Add(new ObjectReference((Integer)function.CompileCache.VarIndex, ReferenceType.Variable));
                        continue;
                    }

                    if (line.Instruction.ParameterTypes[argIndex] == InstructionParameterType.ClassName)
                    {
                        TypeReference type = new TypeReference(argument, source.Assembly);
                        if (!type.CheckClassType(source.Assembly.AllClasses, source.Assembly))
                        {
                            error = NewParseError(ParseErrorType.Syntax_Instruction_UnknownType, line, argIndex);
                            return(null);
                        }

                        //var _const = RegisterConstant(function, $"__classReference{type.UniqueID}_", (ulong)type.UniqueID);
                        //result.Add(_const);
                        usedIndexes.Add(new ObjectReference((Integer)type.UniqueID, ReferenceType.Type));
                        continue;
                    }

                    if (line.Instruction.ParameterTypes[argIndex] == InstructionParameterType.FieldName)
                    {
                        var field = BaseStructure.GetInstance <Field>(argument, source.Assembly, function.BaseClass);

                        if (field == null)
                        {
                            error = NewParseError(ParseErrorType.Syntax_Instruction_UnknownFieldName,
                                                  line, argIndex);
                            return(null);
                        }

                        //var _const = RegisterConstant(function, $"__fieldRference{field.UniqueID}_", (ulong)field.UniqueID);
                        //result.Add(_const);
                        usedIndexes.Add(new ObjectReference((Integer)field.UniqueID, ReferenceType.Field));
                        continue;
                    }

                    if (line.Instruction.ParameterTypes[argIndex] == InstructionParameterType.FunctionName)
                    {
                        var func = BaseStructure.GetInstance <Runtime.Structures.Units.Function>(argument, source.Assembly,
                                                                                                 function.BaseClass);

                        if (func == null)
                        {
                            error = NewParseError(ParseErrorType.Syntax_Instruction_UnknownFuncName,
                                                  line, argIndex);
                            return(null);
                        }

                        //var _const = RegisterConstant(function, $"__funcRference{func.UniqueID}_", (ulong)func.UniqueID);
                        //result.Add(_const);
                        usedIndexes.Add(new ObjectReference((Integer)func.UniqueID, ReferenceType.Function));
                        continue;
                    }


                    //Если это не выражение, то просто разбираем его дальше по типам...
                    //Если допустимо и константа и переменная, то выходит неоднозначность
                    if (isVar && isConst &&
                        line.Instruction.ParameterTypes[argIndex].HasFlag(InstructionParameterType.Variable) &&
                        line.Instruction.ParameterTypes[argIndex].HasFlag(InstructionParameterType.Constant))
                    {
                        error = NewParseError(ParseErrorType.Syntax_AmbiguityBetweenVarAndConst, line, argIndex);
                        return(null);
                    }

                    //Если мы определили, что это может быть как переменная, так и константа,
                    //то смотрим что от нас хочет инструкция
                    if (isVar && isConst)
                    {
                        //Если необходима коснтанта, а не переменная
                        if (line.Instruction.ParameterTypes[argIndex].HasFlag(InstructionParameterType.Constant) &&
                            !line.Instruction.ParameterTypes[argIndex].HasFlag(InstructionParameterType.Variable))
                        {
                            //Запоминаем индекс константы
                            usedIndexes.Add(new ObjectReference((Integer)(++function.CompileCache.ConstIndex), ReferenceType.Constant));
                            //Записываем во флеш константу
                            result.Add(constant.ToFlashElement((Integer)function.CompileCache.ConstIndex));
                        }
                        ;

                        //Если необходима переменная, а не константа
                        if (line.Instruction.ParameterTypes[argIndex].HasFlag(InstructionParameterType.Variable) &&
                            !line.Instruction.ParameterTypes[argIndex].HasFlag(InstructionParameterType.Constant))
                        {
                            //Получаем индекс переменной со списка переменных
                            Integer varIndex = function.CompileCache.Variables.Find(p => p.Name == argument).Index;
                            //Запоминаем индекс переменной
                            usedIndexes.Add(new ObjectReference(varIndex, ReferenceType.Variable));
                        }
                        continue;
                    }

                    //Если это однозначно константа, не переменная
                    if (isConst)
                    {
                        //А ожидалась не константа, то ошибка
                        if (!line.Instruction.ParameterTypes[argIndex].HasFlag(InstructionParameterType.Constant))
                        {
                            error = NewParseError(ParseErrorType.Syntax_ExpectedVar, line, argIndex);
                            return(null);
                        }

                        //Если константу он то пропарсил, но было переполение
                        if (constError != null && (
                                constError.Type == ParseErrorType.Syntax_Constant_BaseOverflow ||
                                constError.Type == ParseErrorType.Syntax_Constant_WrongType ||
                                constError.Type == ParseErrorType.Syntax_Constant_TooLong))
                        {
                            error = NewParseError(constError.Type, line, argIndex);
                            return(null);
                        }

                        //Запоминаем индекс константы
                        usedIndexes.Add(new ObjectReference((Integer)(++function.CompileCache.ConstIndex), ReferenceType.Constant));
                        //Заносим константу во флеш
                        result.Add(constant.ToFlashElement((Integer)function.CompileCache.ConstIndex));
                        continue;
                    }

                    //Если это не константа...
                    //Если это однозначно переменная...
                    if (isVar)
                    {
                        //А ожидалась не переменная, то ошибка
                        if (!line.Instruction.ParameterTypes[argIndex].HasFlag(InstructionParameterType.Variable))
                        {
                            error = NewParseError(ParseErrorType.Syntax_ExpectedСonst, line, argIndex);
                            return(null);
                        }

                        //Получаем индекс переменной со списка переменных
                        Integer varIndex = function.CompileCache.Variables.Find(p => p.Name == argument).Index;
                        //Запоминаем индекс переменной
                        usedIndexes.Add(new ObjectReference(varIndex, ReferenceType.Variable));
                        continue;
                    }

                    //Если это не переменная, а просили константу, не переменную
                    if (line.Instruction.ParameterTypes[argIndex].HasFlag(InstructionParameterType.Constant))
                    {
                        //То, возможно, это именная константа...
                        if (function.CompileCache.NamedConsts.Select(p => p.Name).Contains(argument))
                        {
                            //Получения индекса константы со списка
                            int constantIndex = function.CompileCache.NamedConsts.Select(p => p.Name).ToList().IndexOf(argument);
                            //Запоминания индекса
                            usedIndexes.Add(new ObjectReference(function.CompileCache.NamedConsts[constantIndex].Index, ReferenceType.Constant));
                            //Запись константы во флеш
                            result.Add(function.CompileCache.NamedConsts[constantIndex].Constant.ToFlashElement(function.CompileCache.NamedConsts[constantIndex].Index));
                        }
                        else
                        {
                            //Константа не найдена! Логично было бы выкинуть ошику
                            //Но жива еще надежда на то, что она будет объявлена чуть позже.
                            //Потому сейчас внесем ее сюда. Создадим новую "пустую" константу во флеше,
                            //И если она таки будет найдена, то подменим ее настоящим значением


                            //Елси на эту неведомую херню уже ссылались, то сослемся на нее же
                            if (function.CompileCache.UnknownLabelNameErrorList.Exists(p => p.Name == argument))
                            {
                                var item = function.CompileCache.UnknownLabelNameErrorList.Find(p => p.Name == argument);

                                //После такой "грязной" хуйни мне хочется сходить с душ!
                                usedIndexes.Add(new ObjectReference((Integer)item.ConstIndex, ReferenceType.Constant));
                            }
                            else
                            {
                                int constIndex = ++function.CompileCache.ConstIndex;
                                FlashElementConstantDummy dummyConstant = new FlashElementConstantDummy((Integer)constIndex);
                                ConstantMark dummyNamedConstant         = new ConstantMark(argument, (Integer)constIndex, new Constant(BaseIntegerType.CommonType))
                                {
                                    FEReference = dummyConstant
                                };

                                function.CompileCache.UnknownLabelNameErrorList.Add(new ConstantErrorMark(
                                                                                        argument,
                                                                                        NewParseError(expressionError == null ? ParseErrorType.Syntax_UnknownConstName : expressionError.Type, line, argIndex),
                                                                                        (Integer)constIndex,
                                                                                        dummyNamedConstant, dummyConstant));

                                function.CompileCache.NamedConsts.Add(dummyNamedConstant);
                                //Записываем его во флеш память
                                result.Add(dummyConstant);

                                usedIndexes.Add(new ObjectReference((Integer)constIndex, ReferenceType.Constant));
                            }

                            //error = NewParseError (ParseErrorType.Syntax_UnknownConstName, label, stringParts, argIndex, index);
                        }
                        continue;
                    }

                    //Если удалось частично пропарсить константу, но были переполнения и тд...
                    if (constError.Type == ParseErrorType.Syntax_Constant_BaseOverflow ||
                        constError.Type == ParseErrorType.Syntax_Constant_WrongType ||
                        constError.Type == ParseErrorType.Syntax_Constant_WrongEscapeSymbol ||
                        constError.Type == ParseErrorType.Syntax_Constant_TooLong)
                    {
                        //Вернуть новую ошибку с типо старой
                        error = NewParseError(constError.Type, line, argIndex);
                        return(null);
                    }

                    //Если ничего не известно, то вернем что неизвестное имя переменной
                    if (expressionError != null && line.Instruction.ParameterTypes[argIndex].HasFlag(InstructionParameterType.Expression))
                    {
                        error = NewParseError(expressionError.Type, line, argIndex);
                        return(null);
                    }

                    error = NewParseError(ParseErrorType.Syntax_UnknownVariableName, line, argIndex);
                    return(null);
                }
            }

            result.Add(new FlashElementInstruction(line.Instruction, usedIndexes, currentInstructionProgramIndex)
            {
                Line = line
            });
            error = null;
            return(result);
        }