vm_test.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. package vm
  2. import (
  3. "fmt"
  4. "github/runnignwater/monkey/ast"
  5. "github/runnignwater/monkey/compiler"
  6. "github/runnignwater/monkey/lexer"
  7. "github/runnignwater/monkey/object"
  8. "github/runnignwater/monkey/parser"
  9. "testing"
  10. )
  11. type vmTestCase struct {
  12. input string
  13. expected interface{}
  14. }
  15. func TestIntegerArithmetic(t *testing.T) {
  16. tests := []vmTestCase{
  17. {"1", 1},
  18. {"2", 2},
  19. {"1 + 2", 3},
  20. {"1 - 2", -1},
  21. {"1 * 2", 2},
  22. {"4 / 2", 2},
  23. {"50 / 2 * 2 + 10 - 5", 55},
  24. {"5 * (2 + 10)", 60},
  25. {"5 + 5 + 5 + 5 - 10", 10},
  26. {"2 * 2 * 2 * 2 * 2", 32},
  27. {"5 * 2 + 10", 20},
  28. {"5 + 2 * 10", 25},
  29. {"5 * (2 + 10)", 60},
  30. }
  31. runVmTests(t, tests)
  32. }
  33. func TestBooleanExpression(t *testing.T) {
  34. tests := []vmTestCase{
  35. {"true", true},
  36. {"false", false},
  37. }
  38. runVmTests(t, tests)
  39. }
  40. func runVmTests(t *testing.T, tests []vmTestCase) {
  41. t.Helper()
  42. for _, tt := range tests {
  43. program := parse(tt.input)
  44. comp := compiler.New()
  45. err := comp.Compile(program)
  46. if err != nil {
  47. t.Fatalf("compler error: %s", err)
  48. }
  49. vm := New(comp.ByteCode())
  50. err = vm.Run()
  51. if err != nil {
  52. t.Fatalf("vm error: %s", err)
  53. }
  54. stackElem := vm.LastPopStackElem()
  55. testExpectedObject(t, tt.expected, stackElem)
  56. }
  57. }
  58. func parse(input string) *ast.Program {
  59. l := lexer.New(input)
  60. p := parser.New(l)
  61. return p.ParseProgram()
  62. }
  63. func testExpectedObject(
  64. t *testing.T,
  65. expected interface{},
  66. actual object.Object,
  67. ) {
  68. t.Helper()
  69. switch expected := expected.(type) {
  70. case int:
  71. err := testIntegerObject(int64(expected), actual)
  72. if err != nil {
  73. t.Errorf("testIntegerObject failed: %s", err)
  74. }
  75. case bool:
  76. err := testBooleanObject(expected, actual)
  77. if err != nil {
  78. t.Errorf("testBooleanObject failed: %s", err)
  79. }
  80. }
  81. }
  82. func testIntegerObject(expected int64, actual object.Object) error {
  83. result, ok := actual.(*object.Integer)
  84. if !ok {
  85. return fmt.Errorf("object is not Integer. got=%T (%+v)", actual, actual)
  86. }
  87. if result.Value != expected {
  88. return fmt.Errorf("object has wrong value. got=%d, want=%d", result.Value, expected)
  89. }
  90. return nil
  91. }
  92. func testBooleanObject(expected bool, actual object.Object) error {
  93. result, ok := actual.(*object.Boolean)
  94. if !ok {
  95. return fmt.Errorf("object is not Boolean. got=%T (%+v)", actual, actual)
  96. }
  97. if result.Value != expected {
  98. return fmt.Errorf("object has wrong value. got=%t, want=%t", result.Value, expected)
  99. }
  100. return nil
  101. }