コード例 #1
0
        public AssemblyBuilder(bool verbose = true)
        {
            ExecBlocks          = new List <BaseExecBlockContext>();
            Symbols             = new List <DatSymbol>();
            _symbolsDict        = new Dictionary <string, DatSymbol>();
            _activeContext      = null;
            ActiveExecBlock     = null;
            _assignmentLeftSide = new List <SymbolInstruction>();
            FuncCallCtx         = null;


            _nextStringSymbolNumber     = 10000;
            IsInsideConstDef            = false;
            IsCurrentlyParsingExternals = false;

            IsInsideArgList         = false;
            IsInsideAssignment      = false;
            IsInsideReturnStatement = false;
            AssignmentType          = DatSymbolType.Undefined;
            _nextSymbolIndex        = 0;
            _verbose = verbose;

            Errors       = new List <CompilationMessage>();
            ErrorContext = new ErrorContext(this);
        }
コード例 #2
0
        public AssemblyElement GetProperPushInstruction(DatSymbol symbol, int arrIndex)
        {
            BaseExecBlockContext activeBlock = ActiveExecBlock;

            if (arrIndex > 0)
            {
                return(new PushArrayVar(symbol, arrIndex));
            }

            if (IsInsideArgList)
            {
                return(PushSymbol(symbol, FuncCallCtx.GetParameterType()));
            }

            if (IsInsideReturnStatement && activeBlock != null)
            {
                return(PushSymbol(symbol, activeBlock.GetSymbol().ReturnType));
            }

            if (IsInsideAssignment)
            {
                return(PushSymbol(symbol, AssignmentType));
            }

            if (IsInsideIfCondition)
            {
                return(PushSymbol(symbol, DatSymbolType.Int));
            }

            return(PushSymbol(symbol));
        }
コード例 #3
0
        public override void ExitParameterList(DaedalusParser.ParameterListContext context)
        {
            var parameterDeclContexts = context.parameterDecl();

            foreach (var parameterDeclContext in parameterDeclContexts.Reverse())
            {
                BaseExecBlockContext baseExecBlock = _assemblyBuilder.ExecBlocks.Last();
                string    execBlockName            = baseExecBlock.GetSymbol().Name;
                string    parameterLocalName       = parameterDeclContext.nameNode().GetText();
                string    parameterName            = $"{execBlockName}.{parameterLocalName}";
                DatSymbol parameterSymbol          = _assemblyBuilder.ResolveSymbol(parameterName);

                var assignInstruction =
                    AssemblyBuilderHelpers.GetAssignInstructionForDatSymbolType(parameterSymbol.Type);

                if (parameterSymbol.Type is DatSymbolType.Instance)
                {
                    _assemblyBuilder.AddInstruction(new PushInstance(parameterSymbol));
                }
                else
                {
                    _assemblyBuilder.AddInstruction(new PushVar(parameterSymbol));
                }

                _assemblyBuilder.AddInstruction(assignInstruction);
            }
        }
コード例 #4
0
        public override void EnterVarDecl([NotNull] DaedalusParser.VarDeclContext context)
        {
            if (context.Parent.Parent is DaedalusParser.DaedalusFileContext || _assemblyBuilder.IsContextInsideExecBlock())
            {
                var typeName = context.typeReference().GetText();
                var type     = DatSymbolTypeFromString(typeName);
                if (type == DatSymbolType.Class)
                {
                    type = DatSymbolType.Instance;
                }

                for (int i = 0; i < context.ChildCount; i++)
                {
                    var varContext = context.GetChild(i);

                    if (varContext is TerminalNodeImpl)
                    {
                        continue; // skips ','
                    }
                    if (varContext is DaedalusParser.VarValueDeclContext varValueContext)
                    {
                        var name = varValueContext.nameNode().GetText();
                        if (_assemblyBuilder.IsContextInsideExecBlock())
                        {
                            // TODO consider making assemblyBuilder.active public and using it here
                            BaseExecBlockContext baseExecBlock = _assemblyBuilder.ExecBlocks.Last();
                            string execBlockName = baseExecBlock.GetSymbol().Name;
                            name = $"{execBlockName}.{name}";
                        }

                        var location = GetLocation(context);

                        int           parentIndex       = DatSymbol.NULL_INDEX;
                        string        parameterTypeName = context.typeReference().GetText();
                        DatSymbolType?parameterType     = DatSymbolTypeFromString(parameterTypeName);
                        if (parameterType is DatSymbolType.Class)
                        {
                            var parentSymbol = _assemblyBuilder.ResolveSymbol(parameterTypeName);
                            parentIndex = parentSymbol.Index;
                        }

                        var symbol = SymbolBuilder.BuildVariable(name, type, location, parentIndex); // TODO : Validate params
                        _assemblyBuilder.AddSymbol(symbol);
                    }

                    if (varContext is DaedalusParser.VarArrayDeclContext varArrayContext)
                    {
                        var name     = varArrayContext.nameNode().GetText();
                        var location = GetLocation(context);
                        var size     = EvaluatorHelper.EvaluteArraySize(varArrayContext.arraySize(), _assemblyBuilder);

                        var symbol =
                            SymbolBuilder.BuildArrOfVariables(name, type, (uint)size,
                                                              location); // TODO : Validate params
                        _assemblyBuilder.AddSymbol(symbol);
                    }
                }
            }
        }
コード例 #5
0
 public AssemblyBuilderSnapshot(AssemblyBuilder assemblyBuilder)
 {
     ActiveExecBlock         = assemblyBuilder.ActiveExecBlock;
     IsInsideArgList         = assemblyBuilder.IsInsideArgList;
     IsInsideAssignment      = assemblyBuilder.IsInsideAssignment;
     IsInsideIfCondition     = assemblyBuilder.IsInsideIfCondition;
     IsInsideReturnStatement = assemblyBuilder.IsInsideReturnStatement;
     AssignmentType          = assemblyBuilder.AssignmentType;
     FuncCallCtx             = assemblyBuilder.FuncCallCtx == null ? null : new FuncCallContext(assemblyBuilder.FuncCallCtx);
 }
コード例 #6
0
        public void LoadStateFromSnapshot(AssemblyBuilderSnapshot snapshot)
        {
            ActiveExecBlock = snapshot.ActiveExecBlock;

            IsInsideArgList         = snapshot.IsInsideArgList;
            IsInsideAssignment      = snapshot.IsInsideAssignment;
            IsInsideIfCondition     = snapshot.IsInsideIfCondition;
            IsInsideReturnStatement = snapshot.IsInsideReturnStatement;
            AssignmentType          = snapshot.AssignmentType;
            FuncCallCtx             = snapshot.FuncCallCtx;
        }
コード例 #7
0
        public override void EnterParameterDecl(DaedalusParser.ParameterDeclContext context)
        {
            BaseExecBlockContext baseExecBlock = _assemblyBuilder.ExecBlocks.Last();
            string execBlockName      = baseExecBlock.GetSymbol().Name;
            string parameterLocalName = context.nameNode().GetText();
            string parameterName      = $"{execBlockName}.{parameterLocalName}";

            int parentIndex = DatSymbol.NULL_INDEX;

            string        parameterTypeName = context.typeReference().GetText();
            DatSymbolType?parameterType     = DatSymbolTypeFromString(parameterTypeName);

            if (parameterType is DatSymbolType.Class)
            {
                parameterType = DatSymbolType.Instance;
                var parentSymbol = _assemblyBuilder.ResolveSymbol(parameterTypeName);
                parentIndex = parentSymbol.Index;
            }

            DatSymbol symbol;
            var       location = GetLocation(context);

            var arraySizeContext = context.arraySize();

            if (arraySizeContext != null)
            {
                if (!uint.TryParse(arraySizeContext.GetText(), out var arrIndex))
                {
                    var constSymbol = _assemblyBuilder.ResolveSymbol(arraySizeContext.GetText());
                    if (constSymbol.Flags != DatSymbolFlag.Const || constSymbol.Type != DatSymbolType.Int)
                    {
                        throw new Exception($"Expected integer constant: {arraySizeContext.GetText()}");
                    }

                    arrIndex = (uint)(int)constSymbol.Content[0];
                }

                symbol = SymbolBuilder.BuildArrOfVariables(parameterName, parameterType.Value, arrIndex, location);
            }
            else
            {
                if (_assemblyBuilder.IsCurrentlyParsingExternals)
                {
                    symbol = SymbolBuilder.BuildExternalParameter(parameterName, parameterType.Value, location, parentIndex);
                }
                else
                {
                    symbol = SymbolBuilder.BuildParameter(parameterName, parameterType.Value, location, parentIndex);
                }
            }

            _assemblyBuilder.AddSymbol(symbol);
        }
コード例 #8
0
        private Dictionary <string, int> GetLabelToAddressDict(BaseExecBlockContext execBlock)
        {
            Dictionary <string, int> labelToAddress = new Dictionary <string, int>();

            foreach (var instruction in execBlock.Body)
            {
                switch (instruction)
                {
                case PushArrayVar _:
                {
                    _currentAddress += 6;
                    break;
                }

                case JumpToLabel _:
                case SymbolInstruction _:
                case ValueInstruction _:
                {
                    _currentAddress += 5;
                    break;
                }

                case ParamLessInstruction _:
                {
                    _currentAddress += 1;
                    break;
                }


                case AssemblyLabel assemblyLabel:
                {
                    labelToAddress[assemblyLabel.Label] = _currentAddress;
                    break;
                }
                }
            }

            return(labelToAddress);
        }
コード例 #9
0
        public void ExecBlockStart(DatSymbol symbol, ExecBlockType blockType)
        {
            switch (blockType)
            {
            case ExecBlockType.Function:
                ActiveExecBlock = new FunctionBlockContext(symbol);
                break;

            case ExecBlockType.Instance:
                ActiveExecBlock = new InstanceBlockContext(symbol);
                break;

            case ExecBlockType.Prototype:
                ActiveExecBlock = new PrototypeBlockContext(symbol);
                break;

            default:
                throw new NotImplementedException();
            }

            _activeContext = ActiveExecBlock;
            ExecBlocks.Add(ActiveExecBlock);
        }
コード例 #10
0
 public void ExecBlockEnd()
 {
     ActiveExecBlock = null;
     ActiveContextEnd();
 }
コード例 #11
0
 public void SharedBlockStart(List <DatSymbol> symbols)
 {
     ActiveExecBlock = new SharedExecBlockContext(symbols);
     _activeContext  = ActiveExecBlock;
     ExecBlocks.Add(ActiveExecBlock);
 }
コード例 #12
0
        public override void EnterConstDef([NotNull] DaedalusParser.ConstDefContext context)
        {
            _assemblyBuilder.IsInsideConstDef = true;
            var typeName = context.typeReference().GetText();
            var type     = DatSymbolTypeFromString(typeName);

            if (type == DatSymbolType.Func)
            {
                type = DatSymbolType.Int;
            }

            for (int i = 0; i < context.ChildCount; i++)
            {
                var constContext = context.GetChild(i);

                if (constContext is TerminalNodeImpl)
                {
                    continue; // skips ','
                }
                if (constContext is DaedalusParser.ConstValueDefContext constValueContext)
                {
                    var name = constValueContext.nameNode().GetText();
                    if (_assemblyBuilder.IsContextInsideExecBlock())
                    {
                        BaseExecBlockContext baseExecBlock = _assemblyBuilder.ExecBlocks.Last();
                        string execBlockName = baseExecBlock.GetSymbol().Name;
                        name = $"{execBlockName}.{name}";
                    }

                    var location             = GetLocation(context);
                    var assignmentExpression = constValueContext.constValueAssignment().expressionBlock().expression();
                    var value = EvaluatorHelper.EvaluateConst(assignmentExpression, _assemblyBuilder, type);

                    var symbol = SymbolBuilder.BuildConst(name, type, value, location); // TODO : Validate params
                    _assemblyBuilder.AddSymbol(symbol);

                    continue;
                }

                if (constContext is DaedalusParser.ConstArrayDefContext constArrayContext)
                {
                    _assemblyBuilder.ErrorContext.Context = constArrayContext;

                    var name     = constArrayContext.nameNode().GetText();
                    var location = GetLocation(context);

                    int  declaredSize = 0;
                    bool compareDeclaredSizeAndElementsCount = true;

                    try
                    {
                        _assemblyBuilder.ErrorContext.Context = constArrayContext.arraySize();
                        declaredSize = EvaluatorHelper.EvaluteArraySize(constArrayContext.arraySize(), _assemblyBuilder);
                    }
                    catch (System.ArgumentNullException)
                    {
                        compareDeclaredSizeAndElementsCount = false;
                    }

                    if (declaredSize == 0 && compareDeclaredSizeAndElementsCount)
                    {
                        compareDeclaredSizeAndElementsCount = false;
                        _assemblyBuilder.Errors.Add(
                            new InvalidArraySizeError(
                                _assemblyBuilder.ErrorContext,
                                name,
                                declaredSize
                                )
                            );
                    }


                    var elements = constArrayContext.constArrayAssignment().expressionBlock()
                                   .Select(expr => EvaluatorHelper.EvaluateConst(expr.expression(), _assemblyBuilder, type))
                                   .ToArray();


                    if (compareDeclaredSizeAndElementsCount && declaredSize != elements.Length)
                    {
                        _assemblyBuilder.Errors.Add(
                            new InconsistentArraySizeError(
                                _assemblyBuilder.ErrorContext,
                                name,
                                declaredSize,
                                elements.Length
                                )
                            );
                    }

                    var symbol =
                        SymbolBuilder.BuildArrOfConst(name, type, elements, location); // TODO : Validate params
                    _assemblyBuilder.AddSymbol(symbol);
                }
            }
        }
コード例 #13
0
        private List <DatToken> GetTokens(BaseExecBlockContext execBlock)
        {
            List <DatToken>          tokens         = new List <DatToken>();
            Dictionary <string, int> labelToAddress = GetLabelToAddressDict(execBlock);

            foreach (var instruction in execBlock.Body)
            {
                if (instruction is AssemblyLabel)
                {
                    continue;
                }


                int? intParam  = null;
                byte?byteParam = null;
                switch (instruction)
                {
                case Call call:
                {
                    intParam = call.Symbol.FirstTokenAddress;
                    break;
                }

                case PushArrayVar pushArrVar:
                {
                    intParam  = pushArrVar.Symbol.Index;
                    byteParam = (byte)pushArrVar.Index;
                    break;
                }

                case JumpToLabel jumpToLabel:
                {
                    intParam = labelToAddress[jumpToLabel.Label];
                    break;
                }

                case SymbolInstruction symbolInstruction:
                {
                    intParam = symbolInstruction.Symbol.Index;
                    break;
                }

                case ValueInstruction valueInstruction:
                {
                    intParam = (int)valueInstruction.Value;
                    break;
                }

                case AddressInstruction addressInstruction:     // TODO check if there is any possibility for this
                {
                    intParam = addressInstruction.Address;
                    break;
                }
                }


                string tokenName = instruction.GetType().Name;
                if (instruction is JumpToLabel)
                {
                    tokenName = tokenName.Substring(0, tokenName.Length - "ToLabel".Length);
                }

                DatTokenType datTokenType = Enum.Parse <DatTokenType>(tokenName);
                tokens.Add(new DatToken {
                    TokenType = datTokenType, IntParam = intParam, ByteParam = byteParam
                });
            }

            return(tokens);
        }