示例#1
0
        public static bool IsExpressionValid(
            Context context,
            Scope environment,
            IExpression expression)
        {
            var self = new ExpressionAnalyzer(context, environment);

            return(expression.Accept(self));
        }
示例#2
0
        public void VisitReturnStatement(ReturnStatement returnStatement)
        {
            if (_functionContext == null)
            {
                _context.Error(returnStatement.Span, "return statement outside of a function");
            }

            ExpressionAnalyzer.IsExpressionValid(
                _context,
                _currentScope,
                returnStatement.Expression);
        }
示例#3
0
        private void CheckIfCase(IExpression condition, Block body)
        {
            if (!ExpressionAnalyzer.IsExpressionValid(_context, _currentScope, condition))
            {
                return;
            }

            var conditionType = Typer.GetExpressionType(_context, _currentScope, condition);

            if (conditionType != null && !(conditionType is BooleanType))
            {
                _context.Error(
                    condition.Span,
                    "condition does not evaluate to \"bool\" type");
            }

            AnalyzeBlock(body);
        }
示例#4
0
        public void VisitAssignmentStatement(AssignmentStatement assignmentStatement)
        {
            if (!ExpressionAnalyzer.IsExpressionValid(
                    _context,
                    _currentScope,
                    assignmentStatement.Target) ||
                !ExpressionAnalyzer.IsExpressionValid(
                    _context,
                    _currentScope,
                    assignmentStatement.Value))
            {
                return;
            }

            if (!IsLValue(assignmentStatement.Target))
            {
                _context.Error(
                    assignmentStatement.Target.Span,
                    "left-hand of the assignment is not assignable");
                return;
            }

            var targetType = Typer.GetExpressionType(
                _context,
                _currentScope,
                assignmentStatement.Target);
            var valueType = Typer.GetExpressionType(
                _context,
                _currentScope,
                assignmentStatement.Value);

            if (targetType == null || valueType == null)
            {
                return;
            }
            if (!targetType.IsSame(valueType))
            {
                _context.Error(
                    assignmentStatement.Value.Span,
                    $"type mismatch; expected \"{targetType}\", but found \"{valueType}\"");
            }
        }
示例#5
0
        public void VisitAssertStatement(AssertStatement assertStatement)
        {
            if (!ExpressionAnalyzer.IsExpressionValid(
                    _context,
                    _currentScope,
                    assertStatement.Condition))
            {
                return;
            }

            var conditionType = Typer.GetExpressionType(
                _context,
                _currentScope,
                assertStatement.Condition);

            if (conditionType != null && !(conditionType is BooleanType))
            {
                _context.Error(
                    assertStatement.Condition.Span,
                    $"type mismatch; expected \"bool\", but found \"{conditionType}\"");
            }
        }
示例#6
0
        public void VisitWhileStatement(WhileStatement whileStatement)
        {
            if (ExpressionAnalyzer.IsExpressionValid(
                    _context,
                    _currentScope,
                    whileStatement.Condition))
            {
                var conditionType = Typer.GetExpressionType(
                    _context,
                    _currentScope,
                    whileStatement.Condition);
                if (conditionType != null && !conditionType.IsSame(new BooleanType()))
                {
                    _context.Error(
                        whileStatement.Condition.Span,
                        "while loop condition does not evaluate to type \"bool\"");
                }
            }

            _loopNestLevel++;
            AnalyzeBlock(whileStatement.Body);
            _loopNestLevel--;
        }
示例#7
0
        public void VisitVariableDefinition(VariableDefinition variableDefinition)
        {
            if (variableDefinition.TypeSignature != null && variableDefinition.Initializer != null)
            {
                var variableType = TypeSignatureParser.ParseTypeSignature(
                    _context,
                    variableDefinition.TypeSignature);

                if (!ExpressionAnalyzer.IsExpressionValid(
                        _context,
                        _currentScope,
                        variableDefinition.Initializer))
                {
                    return;
                }

                var initializerType = Typer.GetExpressionType(
                    _context,
                    _currentScope,
                    variableDefinition.Initializer);

                if (variableType != null && !variableType.IsSame(initializerType))
                {
                    // We made sure in the StatementParser that a definition without both initializer
                    // and type signature is not a valid AST item and discarded it with an error.
                    Debug.Assert(variableDefinition.Initializer != null);
                    _context.Error(
                        variableDefinition.Initializer.Span,
                        $"expected type \"{variableType}\", but found \"{initializerType}\"");
                }

                _astContext.AddNodeType(variableDefinition.NodeId, variableType);
            }
            else if (variableDefinition.TypeSignature != null &&
                     variableDefinition.Initializer == null)
            {
                var variableType =
                    TypeSignatureParser.ParseTypeSignature(
                        _context,
                        variableDefinition.TypeSignature);

                _astContext.AddNodeType(variableDefinition.NodeId, variableType);
            }
            else // variableDefinition.TypeSignature == null && variableDefinition.Initializer != null
            {
                if (!ExpressionAnalyzer.IsExpressionValid(
                        _context,
                        _currentScope,
                        variableDefinition.Initializer))
                {
                    return;
                }

                var initializerType = Typer.GetExpressionType(
                    _context,
                    _currentScope,
                    variableDefinition.Initializer);
                switch (initializerType)
                {
                case VoidType _:
                    // Again, the linter is overly sensitive. There's no way for the Initializer
                    // field to be null at this point.
                    Debug.Assert(variableDefinition.Initializer != null);
                    _context.Error(
                        variableDefinition.Initializer.Span,
                        "type \"void\" cannot be assigned to a variable");
                    break;

                case null:
                    return;

                default:
                    _astContext.AddNodeType(variableDefinition.NodeId, initializerType);
                    break;
                }
            }

            if (!_currentScope.DefineSymbol(
                    variableDefinition,
                    _astContext.GetNodeType(variableDefinition.NodeId)))
            {
                _context.Error(
                    variableDefinition.Span,
                    $"redefined previously defined symbol \"{variableDefinition.Identifier}\"");
            }
        }
示例#8
0
 public void VisitExpressionStatement(ExpressionStatement expressionStatement) =>
 ExpressionAnalyzer.IsExpressionValid(
     _context,
     _currentScope,
     expressionStatement.Expression);