Ejemplo n.º 1
0
        protected override void InnerRun()
        {
            if (source.Assembly == null)
            {
                InnerEnd();
                return;
            }

            foreach (var function in source.Assembly.AllFunctions)
            {
                if (!function.IsStatic)
                {
                    function.CompileCache.VarIndex++;

                    TypeReference type = new TypeReference(function.BaseClass, source.Assembly);
                    type.CheckClassType(source.Assembly.AllClasses, source.Assembly);

                    function.CompileCache.Variables.Add(
                        new VariableMark(Runtime.Structures.Units.Function.SelfParameter, type)
                    {
                        Index = (Integer)function.CompileCache.VarIndex
                    });
                }

                foreach (var parameter in function.Parameters)
                {
                    function.CompileCache.VarIndex++;
                    function.CompileCache.Variables.Add(new VariableMark(parameter.Name, parameter.Type)
                    {
                        Index = (Integer)function.CompileCache.VarIndex
                    });
                }

                var error = ParseFunction(function);
                if (error != null)
                {
                    InnerEnd(error);
                    return;
                }
            }

            InnerEnd();
        }
Ejemplo n.º 2
0
        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);
        }
Ejemplo n.º 3
0
        private ParseError CheckNames()
        {
            List <string> funcNames  = new List <string>();
            List <string> fieldNames = new List <string>();
            List <string> classNames = new List <string>();

            foreach (var function in PlainFunctionsList)
            {
                if (funcNames.Contains(function.Signature))
                {
                    return(new ParseError(ParseErrorType.Directives_FunctionWithThatNameAlreadyExists, function.Directive));
                }

                funcNames.Add(function.Signature);

                if (function.IsEntryPoint)
                {
                    if (source.Assembly._entryPoint != null)
                    {
                        return(new ParseError(ParseErrorType.Directives_MoreThanOneEntryPointDeclared, function.Directive));
                    }

                    source.Assembly._entryPoint = function;
                }
            }

            foreach (var field in PlainFiledsList)
            {
                if (fieldNames.Contains(field.Signature))
                {
                    return(new ParseError(ParseErrorType.Directives_FieldWithThatNameAlreadyExists, field.Directive));
                }

                fieldNames.Add(field.Signature);

                if (field.IsStatic)
                {
                    field.BaseClass.StaticFields.Add(field.UniqueID,
                                                     new Object(field.Type));
                }
            }

            foreach (var Class in PlainClassesList)
            {
                if (classNames.Contains(Class.FullName))
                {
                    return(new ParseError(ParseErrorType.Directives_ClassWithThatNameAlreadyExists, Class.Directive));
                }
                classNames.Add(Class.FullName);

                var extends = Class.Modifiers.FindAll(p => p.Name == Class.ExtendsKeyword);
                foreach (var extend in extends)
                {
                    var type = new TypeReference(extend.Value, source.Assembly);
                    if (!type.CheckClassType(PlainClassesList, source.Assembly))
                    {
                        return(new ParseError(ParseErrorType.Directives_WrongTypeReference, Class.Directive));
                    }

                    if (type.Type != TypeReferenceType.Class)
                    {
                        return(new ParseError(ParseErrorType.Directives_ClassNameExpected, Class.Directive));
                    }

                    Class.Extends.Add(type.ClassType);
                    Class.Functions.AddRange(type.ClassType.Functions);
                    Class.Fields.AddRange(type.ClassType.Fields);
                }
            }

            return(null);
        }