A toy dynamic programming language written in Ruby
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

function_call_spec.rb 4.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. RSpec.describe AST::FunctionCall do
  2. it 'evaluates built-in functions' do
  3. expect {
  4. AST::FunctionCall.new(
  5. AST::Identifier.new('print'),
  6. [AST::String.new('hello world')]
  7. ).execute(Environment.new)
  8. }.to output("hello world\n").to_stdout
  9. end
  10. it 'evaluates user-defined functions' do
  11. env = Environment.new
  12. AST::FunctionDefinition.new(
  13. AST::Identifier.new('add_one'),
  14. [AST::Identifier.new('n')],
  15. AST::Block.new([
  16. AST::Binary.new(
  17. AST::Operators::ADD,
  18. AST::Identifier.new('n'),
  19. AST::Number.new(1.0)
  20. )
  21. ])
  22. ).execute(env)
  23. expect(
  24. AST::FunctionCall.new(
  25. AST::Identifier.new('add_one'),
  26. [AST::Number.new(5.0)]
  27. ).execute(env)
  28. ).to eq(6.0)
  29. end
  30. # This corresponds to the program
  31. # function factorial(n) {
  32. # if n == 0 {
  33. # 1;
  34. # } else {
  35. # n * factorial(n - 1);
  36. # }
  37. # }
  38. # factorial(5);
  39. it 'evaluates recursive functions' do
  40. env = Environment.new
  41. AST::FunctionDefinition.new(
  42. AST::Identifier.new('factorial'),
  43. [AST::Identifier.new('n')],
  44. AST::Block.new([
  45. AST::Conditional.new(
  46. [
  47. AST::Branch.new(
  48. AST::Binary.new(
  49. AST::Operators::DOUBLE_EQUALS,
  50. AST::Identifier.new('n'),
  51. AST::Number.new(0.0),
  52. ),
  53. AST::Block.new([
  54. AST::Number.new(1.0),
  55. ])
  56. ),
  57. AST::Branch.new(
  58. AST::Boolean.new(true),
  59. AST::Block.new([
  60. AST::Binary.new(
  61. AST::Operators::MULTIPLY,
  62. AST::Identifier.new('n'),
  63. AST::FunctionCall.new(
  64. AST::Identifier.new('factorial'),
  65. [
  66. AST::Binary.new(
  67. AST::Operators::SUBTRACT,
  68. AST::Identifier.new('n'),
  69. AST::Number.new(1.0),
  70. )
  71. ]
  72. )
  73. )
  74. ])
  75. ),
  76. ]
  77. )
  78. ])
  79. ).execute(env)
  80. expect(
  81. AST::FunctionCall.new(
  82. AST::Identifier.new('factorial'),
  83. [AST::Number.new(5.0)]
  84. ).execute(env)
  85. ).to eq(120.0)
  86. end
  87. # This is equivalent to the program
  88. #
  89. # function add_one(n) {
  90. # n + 1;
  91. # }
  92. # add_one(5);
  93. # print(n);
  94. #
  95. # This test is ensuring that `n` is not still defined outside the scope of
  96. # add_one after the function finishes executing
  97. it 'destroys variables when they go out of scope' do
  98. env = Environment.new
  99. AST::FunctionDefinition.new(
  100. AST::Identifier.new('add_one'),
  101. [AST::Identifier.new('n')],
  102. AST::Block.new([
  103. AST::Binary.new(
  104. AST::Operators::ADD,
  105. AST::Identifier.new('n'),
  106. AST::Number.new(1.0)
  107. )
  108. ])
  109. ).execute(env)
  110. AST::FunctionCall.new(
  111. AST::Identifier.new('add_one'),
  112. [
  113. AST::Number.new(5)
  114. ]
  115. ).execute(env)
  116. expect do
  117. AST::FunctionCall.new(
  118. AST::Identifier.new('print'),
  119. [
  120. AST::Identifier.new('n')
  121. ]
  122. ).execute(env)
  123. end.to raise_error('Undefined variable n')
  124. end
  125. # let add_one = function(n) { n + 1; };
  126. # let do = function(f, n) { f(n); };
  127. # do(5);
  128. it 'executes higher order functions' do
  129. env = Environment.new
  130. AST::VariableDeclaration.new(
  131. AST::Identifier.new('add_one'),
  132. AST::FunctionDefinition.new(
  133. nil,
  134. [
  135. AST::Identifier.new('n'),
  136. ],
  137. AST::Block.new(
  138. [
  139. AST::Binary.new(
  140. AST::Operators::ADD,
  141. AST::Identifier.new('n'),
  142. AST::Number.new(1.0)
  143. )
  144. ]
  145. )
  146. )
  147. ).execute(env)
  148. AST::VariableDeclaration.new(
  149. AST::Identifier.new('do'),
  150. AST::FunctionDefinition.new(
  151. nil,
  152. [
  153. AST::Identifier.new('f'),
  154. AST::Identifier.new('x'),
  155. ],
  156. AST::Block.new(
  157. [
  158. AST::FunctionCall.new(
  159. AST::Identifier.new('f'),
  160. [
  161. AST::Identifier.new('x')
  162. ]
  163. )
  164. ]
  165. )
  166. )
  167. ).execute(env)
  168. result = AST::FunctionCall.new(
  169. AST::Identifier.new('do'),
  170. [
  171. AST::Identifier.new('add_one'),
  172. AST::Number.new(5.0)
  173. ]
  174. ).execute(env)
  175. expect(result).to eq(6)
  176. end
  177. end