public void Bool_non_constant_unary_expression_compiled_successfully(string expressionString, Opcode expectedOp) { var expressionSyntax = ParseExpression(expressionString); var method = new CompiledMethod("Test::Method"); var builder = new BasicBlockGraphBuilder().GetInitialBlockBuilder(); var diagnostics = new TestingDiagnosticSink(); var variableMap = new ScopedVariableMap(); variableMap.PushScope(); variableMap.TryAddVariable("a", method.AddLocal(SimpleType.Bool, LocalFlags.None)); var localIndex = ExpressionCompiler.TryCompileExpression(expressionSyntax, SimpleType.Bool, method, builder, new TestingResolver(variableMap), diagnostics); Assert.That(diagnostics.Diagnostics, Is.Empty); Assert.That(localIndex, Is.EqualTo(1)); Assert.That(method.Values[localIndex].Type, Is.EqualTo(SimpleType.Bool)); Assert.That(builder.Instructions, Has.Exactly(1).Items); var instruction = builder.Instructions[0]; Assert.That(instruction.Operation, Is.EqualTo(expectedOp)); Assert.That(instruction.Left, Is.EqualTo(0)); Assert.That(instruction.Destination, Is.EqualTo(1)); }
/// <summary> /// Creates and returns a <see cref="SyntaxParser"/> instance for the given source text. /// This allows testing instance methods directly. /// </summary> protected SyntaxParser GetParserInstance(string source, out TestingDiagnosticSink diagnostics) { var sourceBytes = Encoding.UTF8.GetBytes(source); diagnostics = new TestingDiagnosticSink(); return(new SyntaxParser(sourceBytes.AsMemory(), "test.cle", diagnostics)); }
/// <summary> /// Parses the given source text and returns the syntax tree if successful. /// </summary> protected SourceFileSyntax?ParseSource(string source, out TestingDiagnosticSink diagnostics) { var sourceBytes = Encoding.UTF8.GetBytes(source); diagnostics = new TestingDiagnosticSink(); return(SyntaxParser.Parse(sourceBytes.AsMemory(), "test.cle", diagnostics)); }
public void Integer_literal_that_is_too_large_fails() { var position = new TextPosition(10, 3, 4); var syntax = new IntegerLiteralSyntax((ulong)int.MaxValue + 1, position); var method = new CompiledMethod("Test::Method"); var builder = new BasicBlockGraphBuilder().GetInitialBlockBuilder(); var nameResolver = new TestingResolver(new ScopedVariableMap()); var diagnostics = new TestingDiagnosticSink(); var localIndex = ExpressionCompiler.TryCompileExpression( syntax, SimpleType.Int32, method, builder, nameResolver, diagnostics); Assert.That(localIndex, Is.EqualTo(-1)); diagnostics.AssertDiagnosticAt(DiagnosticCode.TypeMismatch, position) .WithActual("uint32").WithExpected("int32"); }
public void Constant_comparison_compiled_successfully(string expressionString, bool expectedValue) { var expressionSyntax = ParseExpression(expressionString); var method = new CompiledMethod("Test::Method"); var builder = new BasicBlockGraphBuilder().GetInitialBlockBuilder(); var diagnostics = new TestingDiagnosticSink(); var nameResolver = new TestingResolver(new ScopedVariableMap()); var localIndex = ExpressionCompiler.TryCompileExpression(expressionSyntax, SimpleType.Bool, method, builder, nameResolver, diagnostics); Assert.That(diagnostics.Diagnostics, Is.Empty); Assert.That(localIndex, Is.EqualTo(0)); Assert.That(method.Values[localIndex].Type, Is.EqualTo(SimpleType.Bool)); AssertSingleLoad(builder, localIndex, expectedValue); }
public void Variable_reference_must_refer_to_existent_variable() { var position = new TextPosition(10, 3, 4); var syntax = new IdentifierSyntax("a", position); var method = new CompiledMethod("Test::Method"); var builder = new BasicBlockGraphBuilder().GetInitialBlockBuilder(); var diagnostics = new TestingDiagnosticSink(); var variableMap = new ScopedVariableMap(); variableMap.PushScope(); var localIndex = ExpressionCompiler.TryCompileExpression( syntax, SimpleType.Int32, method, builder, new TestingResolver(variableMap), diagnostics); Assert.That(localIndex, Is.EqualTo(-1)); diagnostics.AssertDiagnosticAt(DiagnosticCode.VariableNotFound, position).WithActual("a"); }
public void Int32_division_by_zero_in_constant_expression_fails(BinaryOperation op) { var position = new TextPosition(10, 3, 4); var syntax = new BinaryExpressionSyntax(op, new IntegerLiteralSyntax(2ul, default), new IntegerLiteralSyntax(0, default), position); var method = new CompiledMethod("Test::Method"); var builder = new BasicBlockGraphBuilder().GetInitialBlockBuilder(); var diagnostics = new TestingDiagnosticSink(); var nameResolver = new TestingResolver(new ScopedVariableMap()); var localIndex = ExpressionCompiler.TryCompileExpression( syntax, SimpleType.Int32, method, builder, nameResolver, diagnostics); Assert.That(localIndex, Is.EqualTo(-1)); diagnostics.AssertDiagnosticAt(DiagnosticCode.DivisionByConstantZero, position); }
public void Compile_parameterless_int32_method_succeeds() { var position = new TextPosition(280, 14, 8); var syntax = MakeParameterlessMethod(Visibility.Private, "int32", position); var diagnostics = new TestingDiagnosticSink(); var declarationProvider = new TestingSingleFileDeclarationProvider(); var result = MethodDeclarationCompiler.Compile(syntax, "long::ns", "int32.cle", 8, declarationProvider, diagnostics); Assert.That(diagnostics.Diagnostics, Is.Empty); Assert.That(result, Is.InstanceOf <NativeMethodDeclaration>()); Assert.That((result as NativeMethodDeclaration) !.IsEntryPoint, Is.False); Assert.That(result !.ReturnType, Is.EqualTo(SimpleType.Int32)); Assert.That(result.Visibility, Is.EqualTo(Visibility.Private)); Assert.That(result.FullName, Is.EqualTo("long::ns::MethodName")); Assert.That(result.DefiningFilename, Is.EqualTo("int32.cle")); Assert.That(result.DefinitionPosition, Is.EqualTo(position)); Assert.That(result.BodyIndex, Is.EqualTo(8)); }
public void Compile_parameterless_bool_method_succeeds() { var position = new TextPosition(13, 3, 4); var syntax = MakeParameterlessMethod(Visibility.Public, "bool", position); var diagnostics = new TestingDiagnosticSink(); var declarationProvider = new TestingSingleFileDeclarationProvider(); var result = MethodDeclarationCompiler.Compile(syntax, "Namespace", "bool.cle", 7, declarationProvider, diagnostics); Assert.That(diagnostics.Diagnostics, Is.Empty); Assert.That(result, Is.InstanceOf <NativeMethodDeclaration>()); Assert.That((result as NativeMethodDeclaration) !.IsEntryPoint, Is.False); Assert.That(result !.ReturnType, Is.EqualTo(SimpleType.Bool)); Assert.That(result.Visibility, Is.EqualTo(Visibility.Public)); Assert.That(result.FullName, Is.EqualTo("Namespace::MethodName")); Assert.That(result.DefiningFilename, Is.EqualTo("bool.cle")); Assert.That(result.DefinitionPosition, Is.EqualTo(position)); Assert.That(result.BodyIndex, Is.EqualTo(7)); }
public void Operator_not_defined_for_type_in_non_constant(string expressionString, string operatorName, string typeName) { var expressionSyntax = ParseExpression(expressionString); var method = new CompiledMethod("Test::Method"); var builder = new BasicBlockGraphBuilder().GetInitialBlockBuilder(); var diagnostics = new TestingDiagnosticSink(); var variableMap = new ScopedVariableMap(); variableMap.PushScope(); variableMap.TryAddVariable("b", method.AddLocal(SimpleType.Bool, LocalFlags.None)); variableMap.TryAddVariable("i", method.AddLocal(SimpleType.Int32, LocalFlags.None)); var localIndex = ExpressionCompiler.TryCompileExpression( expressionSyntax, SimpleType.Void, method, builder, new TestingResolver(variableMap), diagnostics); Assert.That(localIndex, Is.EqualTo(-1)); diagnostics.AssertDiagnosticAt(DiagnosticCode.OperatorNotDefined, expressionSyntax.Position) .WithActual(operatorName).WithExpected(typeName); }
public void Variable_reference_returns_local_index_of_variable() { var syntax = new IdentifierSyntax("a", default); var method = new CompiledMethod("Test::Method"); var builder = new BasicBlockGraphBuilder().GetInitialBlockBuilder(); var diagnostics = new TestingDiagnosticSink(); var variableMap = new ScopedVariableMap(); variableMap.PushScope(); variableMap.TryAddVariable("a", 0); method.AddLocal(SimpleType.Bool, LocalFlags.None); var localIndex = ExpressionCompiler.TryCompileExpression( syntax, SimpleType.Bool, method, builder, new TestingResolver(variableMap), diagnostics); Assert.That(localIndex, Is.EqualTo(0)); Assert.That(diagnostics.Diagnostics, Is.Empty); }
public void Boolean_literal_stored_in_bool_succeeds() { var syntax = new BooleanLiteralSyntax(true, default); var method = new CompiledMethod("Test::Method"); var builder = new BasicBlockGraphBuilder().GetInitialBlockBuilder(); var nameResolver = new TestingResolver(new ScopedVariableMap()); var diagnostics = new TestingDiagnosticSink(); var localIndex = ExpressionCompiler.TryCompileExpression( syntax, SimpleType.Bool, method, builder, nameResolver, diagnostics); Assert.That(localIndex, Is.EqualTo(0)); Assert.That(diagnostics.Diagnostics, Is.Empty); Assert.That(method.Values, Has.Exactly(1).Items); var local = method.Values[0]; Assert.That(local.Type, Is.EqualTo(SimpleType.Bool)); AssertSingleLoad(builder, localIndex, true); }
public void Variable_reference_must_have_correct_type() { var position = new TextPosition(10, 3, 4); var syntax = new IdentifierSyntax("a", position); var method = new CompiledMethod("Test::Method"); var builder = new BasicBlockGraphBuilder().GetInitialBlockBuilder(); var diagnostics = new TestingDiagnosticSink(); var variableMap = new ScopedVariableMap(); variableMap.PushScope(); variableMap.TryAddVariable("a", 0); method.AddLocal(SimpleType.Bool, LocalFlags.None); var localIndex = ExpressionCompiler.TryCompileExpression( syntax, SimpleType.Int32, method, builder, new TestingResolver(variableMap), diagnostics); Assert.That(localIndex, Is.EqualTo(-1)); diagnostics.AssertDiagnosticAt(DiagnosticCode.TypeMismatch, position) .WithActual("bool").WithExpected("int32"); }
/// <summary> /// Parses the given source code, compiles the method declarations and /// returns the result of <see cref="MethodCompiler.CompileBody"/> on the first method. /// </summary> protected CompiledMethod?TryCompileFirstMethod(string source, out TestingDiagnosticSink diagnostics) { var sourceBytes = Encoding.UTF8.GetBytes(source); diagnostics = new TestingDiagnosticSink(); // Parse the source const string sourceFilename = "test.cle"; var syntaxTree = SyntaxParser.Parse(sourceBytes.AsMemory(), sourceFilename, diagnostics); Assert.That(syntaxTree, Is.Not.Null, "Source file was not parsed successfully."); // Parse the declarations var declarationProvider = new TestingSingleFileDeclarationProvider(); MethodDeclaration?firstDeclaration = null; foreach (var functionSyntax in syntaxTree !.Functions) { var declaration = MethodDeclarationCompiler.Compile(functionSyntax, syntaxTree.Namespace, sourceFilename, declarationProvider.Methods.Count, declarationProvider, diagnostics); Assert.That(declaration, Is.Not.Null, $"Method declaration for {functionSyntax.Name} was not compiled successfully."); if (firstDeclaration is null) { firstDeclaration = declaration; } declarationProvider.Methods.Add(functionSyntax.Name, declaration !); } Assert.That(firstDeclaration, Is.Not.Null, "No methods were declared."); // Then compile the first method return(new MethodCompiler(declarationProvider, diagnostics) .CompileBody(syntaxTree.Functions[0], firstDeclaration !, syntaxTree.Namespace, sourceFilename)); }
public void Non_constant_inequality_compiled_successfully() { var expressionSyntax = ParseExpression("a != b"); var method = new CompiledMethod("Test::Method"); var builder = new BasicBlockGraphBuilder().GetInitialBlockBuilder(); var diagnostics = new TestingDiagnosticSink(); var variableMap = new ScopedVariableMap(); variableMap.PushScope(); variableMap.TryAddVariable("a", method.AddLocal(SimpleType.Int32, LocalFlags.None)); variableMap.TryAddVariable("b", method.AddLocal(SimpleType.Int32, LocalFlags.None)); var localIndex = ExpressionCompiler.TryCompileExpression(expressionSyntax, SimpleType.Bool, method, builder, new TestingResolver(variableMap), diagnostics); Assert.That(diagnostics.Diagnostics, Is.Empty); Assert.That(localIndex, Is.EqualTo(3)); Assert.That(method.Values[localIndex].Type, Is.EqualTo(SimpleType.Bool)); Assert.That(builder.Instructions, Has.Exactly(2).Items); // a != b is compiled as !(a == b) Assert.That(builder.Instructions[0], Is.EqualTo(new Instruction(Opcode.Equal, 0, 1, 2))); Assert.That(builder.Instructions[1], Is.EqualTo(new Instruction(Opcode.BitwiseNot, 2, 0, 3))); }