A fork of Crisp for HARP
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.

90 lignes
1.8 KiB

  1. #! /usr/bin/env crystal run
  2. require "./readline"
  3. require "./reader"
  4. require "./printer"
  5. require "./types"
  6. # Note:
  7. # Employed downcase names because Crystal prohibits uppercase names for methods
  8. def eval_error(msg)
  9. raise Mal::EvalException.new msg
  10. end
  11. def num_func(func)
  12. -> (args : Array(Mal::Type)) {
  13. x, y = args[0].unwrap, args[1].unwrap
  14. eval_error "invalid arguments" unless x.is_a?(Int32) && y.is_a?(Int32)
  15. Mal::Type.new func.call(x, y)
  16. }
  17. end
  18. $repl_env = {
  19. "+" => num_func(->(x : Int32, y : Int32){ x + y }),
  20. "-" => num_func(->(x : Int32, y : Int32){ x - y }),
  21. "*" => num_func(->(x : Int32, y : Int32){ x * y }),
  22. "/" => num_func(->(x : Int32, y : Int32){ x / y }),
  23. } of String => Mal::Func
  24. def eval_ast(a, env)
  25. return a.map{|n| eval(n, env) as Mal::Type} if a.is_a? Mal::List
  26. return a unless a
  27. ast = a.unwrap
  28. case ast
  29. when Mal::Symbol
  30. if env.has_key? ast.str
  31. env[ast.str]
  32. else
  33. eval_error "'#{ast.str}' not found"
  34. end
  35. when Mal::List
  36. ast.each_with_object(Mal::List.new){|n, l| l << eval(n, env)}
  37. when Mal::Vector
  38. ast.each_with_object(Mal::Vector.new){|n, l| l << eval(n, env)}
  39. when Mal::HashMap
  40. ast.each{|k, v| ast[k] = eval(v, env)}
  41. else
  42. ast
  43. end
  44. end
  45. def read(str)
  46. read_str str
  47. end
  48. def eval(t, env)
  49. Mal::Type.new case ast = t.unwrap
  50. when Mal::List
  51. eval_error "empty list" if ast.empty?
  52. f = eval_ast(ast.first, env)
  53. ast.shift(1)
  54. args = eval_ast(ast, env)
  55. if f.is_a?(Mal::Func)
  56. f.call(args)
  57. else
  58. eval_error "expected function symbol as the first symbol of list"
  59. end
  60. else
  61. eval_ast(t, env)
  62. end
  63. end
  64. def print(result)
  65. pr_str(result, true)
  66. end
  67. def rep(str)
  68. print(eval(read(str), $repl_env))
  69. end
  70. while line = my_readline("user> ")
  71. begin
  72. puts rep(line)
  73. rescue e
  74. STDERR.puts e
  75. end
  76. end