public void VisitReturnStatement(ReturnStatement returnStatement) { if (_functionContext == null) { _context.Error(returnStatement.Span, "return statement outside of a function"); } ExpressionAnalyzer.IsExpressionValid( _context, _currentScope, returnStatement.Expression); }
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); }
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}\""); } }
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}\""); } }
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--; }
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}\""); } }
public void VisitExpressionStatement(ExpressionStatement expressionStatement) => ExpressionAnalyzer.IsExpressionValid( _context, _currentScope, expressionStatement.Expression);