public void Pushing_and_popping_very_many_scopes() { var map = new ScopedVariableMap(); const int scopeCount = 100; for (var i = 0; i < scopeCount; i++) { map.PushScope(); map.TryAddVariable(i.ToString(), i); } for (var i = 0; i < scopeCount; i++) { map.PopScope(); } // Now some of the new scopes should come from the cache // Verify that the cached scopes are empty for (var i = 0; i < scopeCount; i++) { map.PushScope(); } for (var i = 0; i < scopeCount; i++) { Assert.That(map.TryGetVariable(i.ToString(), out _), Is.False); } for (var i = 0; i < scopeCount; i++) { map.PopScope(); } }
public void Cannot_add_same_name_to_inner_scope() { var map = new ScopedVariableMap(); map.PushScope(); Assert.That(map.TryAddVariable("a", 1), Is.True); map.PushScope(); Assert.That(map.TryAddVariable("a", 2), Is.False); }
public void Variable_not_found_in_any_scope() { var map = new ScopedVariableMap(); map.PushScope(); Assert.That(map.TryAddVariable("a", 1), Is.True); map.PushScope(); Assert.That(map.TryAddVariable("b", 2), Is.True); Assert.That(map.TryGetVariable("c", out _), Is.False); }
public void Variable_found_in_outer_scope() { var map = new ScopedVariableMap(); map.PushScope(); Assert.That(map.TryAddVariable("a", 1), Is.True); map.PushScope(); Assert.That(map.TryGetVariable("a", out var index), Is.True); Assert.That(index, Is.EqualTo(1)); }
public void Can_add_variable_to_outer_scope_after_defining_in_inner() { // TODO: This behavior could be changed; for now it is simpler var map = new ScopedVariableMap(); map.PushScope(); map.PushScope(); Assert.That(map.TryAddVariable("a", 1), Is.True); map.PopScope(); Assert.That(map.TryAddVariable("a", 2), Is.True); }
public void Reset_clears_stack() { var map = new ScopedVariableMap(); map.PushScope(); map.PushScope(); map.TryAddVariable("a", 1); map.PushScope(); map.Reset(); Assert.That(() => map.TryGetVariable("a", out _), Throws.InvalidOperationException); }
public void Variable_visible_in_inner_but_not_outer_scope() { var map = new ScopedVariableMap(); map.PushScope(); Assert.That(map.TryAddVariable("a", 1), Is.True); map.PushScope(); Assert.That(map.TryAddVariable("b", 2), Is.True); Assert.That(map.TryGetVariable("b", out var index), Is.True); Assert.That(index, Is.EqualTo(2)); map.PopScope(); Assert.That(map.TryGetVariable("b", out _), Is.False); }
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)); }
public void Variable_found_in_same_scope() { var map = new ScopedVariableMap(); map.PushScope(); Assert.That(map.TryAddVariable("a", 1), Is.True); Assert.That(map.TryAddVariable("b", 17), Is.True); Assert.That(map.TryGetVariable("a", out var a), Is.True); Assert.That(a, Is.EqualTo(1)); Assert.That(map.TryGetVariable("b", out var b), Is.True); Assert.That(b, Is.EqualTo(17)); }
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 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 int SmallMethod() { // This is based on NameParsing.IsDigit var map = new ScopedVariableMap(); var sum = 0; // Execute the scenario a few times to simulate the map being reused for (var i = 0; i < 5; i++) { map.PushScope(); map.TryAddVariable("ch", 1); map.TryGetVariable("ch", out var a); map.TryGetVariable("ch", out var b); map.PopScope(); sum += a + b; } return(sum); }
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"); }
public int LargerMethod() { // This is a synthetic benchmark, aiming to still be somewhat realistic var map = new ScopedVariableMap(); var sum = 0; // Execute the scenario a few times to simulate the map being reused for (var iteration = 0; iteration < 5; iteration++) { // Create a lot of nested scopes and add variables to them for (var i = 0; i < ScopeCount; i++) { map.PushScope(); for (var j = 0; j < VariablesPerScope; j++) { var index = i * ScopeCount + j; map.TryAddVariable(_variableNames[index], index); } } // Go through all the variables for (var i = 0; i < ScopeCount * VariablesPerScope; i++) { // Do not go through them in exact order map.TryGetVariable(_variableNames[i * 3 % (ScopeCount * VariablesPerScope)], out var index); sum += index; } // Remove the scopes for (var i = 0; i < ScopeCount; i++) { map.PopScope(); } } return(sum); }
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))); }