public void ThrowOnUnknownExpressionType()
        {
            var m = new Module(null);
            var e = new UnknownExpression();

            Assert.Throws <InvalidOperationException>(() => ConstantSolver.Solve(e, m.Block));
        }
        private TypeDefinition CheckArrayIndexSelector(
            IndexSelector indexSelector,
            TypeDefinition type)
        {
            if (!(type is ArrayTypeDefinition arrayType))
            {
                _parser.NotifyErrorListeners(indexSelector.Token, "Array reference expected", null);
                return(SimpleTypeDefinition.VoidType);
            }

            indexSelector.IndexDefinition = ConstantSolver.Solve(indexSelector.IndexDefinition, _parser.currentBlock);
            if (indexSelector.IndexDefinition.TargetType.Type != BaseTypes.Int)
            {
                _parser.NotifyErrorListeners(indexSelector.Token, "Array reference must be INTEGER", null);
                return(SimpleTypeDefinition.VoidType);
            }

            if (indexSelector.IndexDefinition.IsConst)
            {
                var ce    = (ConstantExpression)indexSelector.IndexDefinition;
                int index = ce.ToInt32();
                if (index < 1 || index > arrayType.Size)
                {
                    _parser.NotifyErrorListeners(indexSelector.Token, "Array index out of bounds", null);
                    return(SimpleTypeDefinition.VoidType);
                }
            }

            return(arrayType.ArrayType); // types match
        }
        public override void ExitConstDeclarationElement(OberonGrammarParser.ConstDeclarationElementContext context)
        {
            if (_parser.currentBlock.LookupVar(context.c.Text, false) != null)
            {
                _parser.NotifyErrorListeners(
                    context.c,
                    "A variable/constant with this name has been defined already",
                    null);
                return;
            }

            if (!(ConstantSolver.Solve(context.e.expReturn, _parser.currentBlock) is ConstantExpression
                  constantExpression))
            {
                _parser.NotifyErrorListeners(context.e.start, "A constant must resolve during compile time", null);
                return;
            }

            var constDeclaration = new ConstDeclaration(
                context.c.Text,
                constantExpression.TargetType,
                constantExpression,
                _parser.currentBlock)
            {
                Exportable = context.export != null
            };

            CheckExportable(context.export, constDeclaration.Exportable);

            _parser.currentBlock.Declarations.Add(constDeclaration);
        }
예제 #4
0
        public void ExpressionNot()
        {
            var m      = new Module(null);
            var e      = BinaryExpression.Create(OberonGrammarLexer.NOT, new ConstantBoolExpression(true), null, m.Block);
            var result = ConstantSolver.Solve(e, m.Block) as ConstantBoolExpression;

            Assert.NotNull(result);
            Assert.False(result.ToBool());
        }
예제 #5
0
        public void ExpressionConstantStringReturnsIdentity()
        {
            const string test = "This is a test";

            var m      = new Module(null);
            var e      = new StringExpression(test);
            var result = ConstantSolver.Solve(e, m.Block) as StringExpression;

            Assert.NotNull(result);
            Assert.True(result.IsConst);
            Assert.Equal(test, result.Value);
        }
        public void ExpressionMult2()
        {
            var m = new Module(null);
            var e = BinaryExpression.Create(
                OberonGrammarLexer.STAR,
                ConstantExpression.Create(6.1),
                ConstantExpression.Create(7),
                m.Block);
            var result = ConstantSolver.Solve(e, m.Block) as ConstantDoubleExpression;

            Assert.NotNull(result);
            Assert.True(result.ToDouble() - 42.7 < double.Epsilon);
        }
예제 #7
0
        public void ExpressionRelGe1()
        {
            var m = new Module(null);
            var e = BinaryExpression.Create(
                OberonGrammarLexer.GE,
                ConstantExpression.Create(4),
                ConstantExpression.Create(4),
                m.Block);
            var result = ConstantSolver.Solve(e, m.Block) as ConstantBoolExpression;

            Assert.NotNull(result);
            Assert.True(result.ToBool());
        }
        public void ExpressionDiv3()
        {
            var m = new Module(null);
            var e = BinaryExpression.Create(
                OberonGrammarLexer.DIV,
                ConstantExpression.Create("10.0"),
                ConstantExpression.Create(4),
                m.Block);
            var result = ConstantSolver.Solve(e, m.Block) as ConstantDoubleExpression;

            Assert.NotNull(result);
            Assert.Equal(2.5, result.ToDouble());
        }
        public void ExpressionDiv1()
        {
            var m = new Module(null);
            var e = BinaryExpression.Create(
                OberonGrammarLexer.DIV,
                ConstantExpression.Create(10),
                ConstantExpression.Create(2),
                m.Block);
            var result = ConstantSolver.Solve(e, m.Block) as ConstantIntExpression;

            Assert.NotNull(result);
            Assert.Equal(5, result.ToInt32());
        }
        public void ExpressionDiv0()
        {
            var m = new Module(null);
            var e = BinaryExpression.Create(
                OberonGrammarLexer.DIV,
                ConstantExpression.Create("10.0"),
                ConstantIntExpression.Zero,
                m.Block);
            var result = ConstantSolver.Solve(e, m.Block) as ConstantDoubleExpression;

            Assert.NotNull(result);
            Assert.True(double.IsInfinity(result.ToDouble()));
        }
        public void ExpressionAnd()
        {
            var m = new Module(null);
            var e = BinaryExpression.Create(
                OberonGrammarLexer.AND,
                ConstantExpression.Create(false),
                ConstantExpression.Create("true"),
                m.Block);
            var result = ConstantSolver.Solve(e, m.Block) as ConstantBoolExpression;

            Assert.NotNull(result);
            Assert.False(result.ToBool());
        }
        public void ExpressionAdd2()
        {
            var m = new Module(null);
            var e = BinaryExpression.Create(
                OberonGrammarLexer.PLUS,
                ConstantExpression.Create(1),
                ConstantExpression.Create(1.42),
                m.Block);
            var result = ConstantSolver.Solve(e, m.Block) as ConstantDoubleExpression;

            Assert.NotNull(result);
            Assert.Equal(2.42, result.ToDouble());
        }
예제 #13
0
        public void ExpressionNot2()
        {
            var m = new Module(null);

            m.Block.Declarations.Add(new Declaration("a", m.Block.LookupType("BOOLEAN")));
            var e = BinaryExpression.Create(
                OberonGrammarLexer.NOT,
                VariableReferenceExpression.Create(m.Block.LookupVar("a"), null),
                null,
                m.Block);
            var result = ConstantSolver.Solve(e, m.Block) as BinaryExpression;

            Assert.NotNull(result);
        }
예제 #14
0
        public void ExpressionRelVar()
        {
            var m = new Module(null);

            m.Block.Declarations.Add(new Declaration("a", m.Block.LookupType("INTEGER")));
            var e = BinaryExpression.Create(
                OberonGrammarLexer.NOTEQUAL,
                VariableReferenceExpression.Create(m.Block.LookupVar("a"), null),
                ConstantExpression.Create(10),
                m.Block);
            var result = ConstantSolver.Solve(e, m.Block) as BinaryExpression;

            Assert.NotNull(result);
            Assert.False(result.IsConst);
        }
        public void ExpressionAddRes0()
        {
            var m = new Module(null);
            var e = BinaryExpression.Create(
                OberonGrammarLexer.PLUS,
                ConstantExpression.Create(1),
                ConstantDoubleExpression.Zero,
                m.Block);
            var result = ConstantSolver.Solve(e, m.Block) as ConstantDoubleExpression;

            Assert.NotNull(result);
            Assert.Equal(1, result.ToInt32());
            Assert.Equal(1.0, result.ToDouble());
            Assert.True(result.ToBool());
            Assert.False(result.IsUnary);
            Assert.True(result.IsConst);
        }
        public override void ExitArrayType(OberonGrammarParser.ArrayTypeContext context)
        {
            var constExpression =
                ConstantSolver.Solve(context.e.expReturn, _parser.currentBlock);

            if (constExpression is ConstantIntExpression cie)
            {
                context.returnType = new ArrayTypeDefinition(cie.ToInt32(), context.t.returnType);
            }
            else
            {
                _parser.NotifyErrorListeners(
                    context.Start,
                    "The array size must return a constant integer expression",
                    null);
                context.returnType = new ArrayTypeDefinition(0, context.t.returnType);
            }
        }
        public override void ExitAssign_statement(OberonGrammarParser.Assign_statementContext context)
        {
            var v = _parser.currentBlock.LookupVar(context.id.Text);

            if (v == null)
            {
                _parser.NotifyErrorListeners(context.id, $"Variable {context.id.Text} not known", null);
                return;
            }

            var targetType = v.Type;

            if (context.s.vsRet != null)
            {
                targetType = context.s.vsRet.SelectorResultType;
            }

            if (context.r?.expReturn == null)
            {
                _parser.NotifyErrorListeners(context.id, "Cannot parse right side of assignment", null);
                return;
            }

            var e = ConstantSolver.Solve(context.r.expReturn, _parser.currentBlock);

            if (!targetType.IsAssignable(e.TargetType))
            {
                _parser.NotifyErrorListeners(context.id, "Left & right side do not match types", null);
                return;
            }

            _parser.currentBlock.Statements.Add(
                new AssignmentStatement {
                Variable = v, Selector = context.s.vsRet, Expression = e
            });
        }
예제 #18
0
 public void ConstantSolverNullInputExceptionForExpression()
 {
     Assert.Throws <ArgumentNullException>(
         () => ConstantSolver.Solve(null, new Block(null, new Module(null))));
 }