interpreter.fs 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. \ interpreter.fs AST Interpreter, RosettaCode Compiler Task 20170504
  2. \ Copyright 2017, Eric Bavier <bavier@member.fsf.org>
  3. \ This is Free Software licensed under the GPLv3, or any later
  4. CREATE BUF 0 , \ single-character look-ahead buffer
  5. : PEEK BUF @ 0= IF KEY BUF ! THEN BUF @ ;
  6. : GETC PEEK 0 BUF ! ;
  7. : SPACE? DUP BL = SWAP 9 14 WITHIN OR ;
  8. : >SPACE BEGIN PEEK SPACE? WHILE GETC DROP REPEAT ;
  9. : DIGIT? 48 58 WITHIN ;
  10. : GETINT >SPACE 0
  11. BEGIN PEEK DIGIT?
  12. WHILE GETC [CHAR] 0 - SWAP 10 * + REPEAT ;
  13. : GETNAM >SPACE PAD 1+
  14. BEGIN PEEK SPACE? INVERT
  15. WHILE GETC OVER C! CHAR+
  16. REPEAT PAD TUCK - 1- PAD C! ;
  17. : GETSTR ( -- c-addr u)
  18. HERE >R 0 >SPACE GETC DROP \ skip leading "
  19. BEGIN GETC DUP [CHAR] " <> WHILE C, 1+ REPEAT
  20. DROP R> SWAP ;
  21. : \TYPE BEGIN DUP 0> WHILE \ TODO: Do escapes in GETSTR
  22. OVER C@ [CHAR] \ = IF
  23. 1- >R CHAR+ R>
  24. OVER C@ [CHAR] n = IF CR ELSE
  25. OVER C@ [CHAR] \ = IF [CHAR] \ EMIT THEN THEN
  26. ELSE OVER C@ EMIT THEN 1- >R CHAR+ R> REPEAT
  27. DROP DROP ;
  28. : . S>D SWAP OVER DABS <# #S ROT SIGN #> TYPE ;
  29. : CONS ( v l -- l) HERE >R SWAP , , R> ;
  30. : HEAD ( l -- v) @ ;
  31. : TAIL ( l -- l) CELL+ @ ;
  32. CREATE GLOBALS 0 ,
  33. : DECLARE ( c-addr -- a-addr) HERE TUCK
  34. OVER C@ CHAR+ DUP ALLOT CMOVE HERE SWAP 0 ,
  35. GLOBALS @ CONS GLOBALS ! ;
  36. : LOOKUP ( c-addr -- a-addr) DUP COUNT GLOBALS @ >R
  37. BEGIN R@ 0<>
  38. WHILE R@ HEAD COUNT 2OVER COMPARE 0=
  39. IF 2DROP DROP R> HEAD DUP C@ CHAR+ + EXIT
  40. THEN R> TAIL >R
  41. REPEAT
  42. 2DROP RDROP DECLARE ;
  43. DEFER GETAST
  44. : >Identifier GETNAM LOOKUP 0 ;
  45. : >Integer GETINT 0 ;
  46. : >String GETSTR ;
  47. : >; 0 0 ;
  48. : NODE ( xt left right -- addr) HERE >R , , , R> ;
  49. CREATE BUF' 12 ALLOT
  50. : PREPEND ( c-addr c -- c-addr) BUF' 1+ C!
  51. COUNT DUP 1+ BUF' C! BUF' 2 + SWAP CMOVE BUF' ;
  52. : HANDLER ( c-addr -- xt) [CHAR] $ PREPEND FIND
  53. 0= IF ." No handler for AST node '" COUNT TYPE ." '" THEN ;
  54. : READER ( c-addr -- xt t | f)
  55. [CHAR] > PREPEND FIND DUP 0= IF NIP THEN ;
  56. : READ ( c-addr -- left right) READER
  57. IF EXECUTE ELSE GETAST GETAST THEN ;
  58. : (GETAST) GETNAM DUP HANDLER SWAP READ NODE ;
  59. ' (GETAST) IS GETAST
  60. : INTERP DUP 2@ ROT [ 2 CELLS ]L + @ EXECUTE ;
  61. : $; DROP DROP ;
  62. : $Identifier ( l r -- a-addr) DROP @ ;
  63. : $Integer ( l r -- n) DROP ;
  64. : $String ( l r -- c-addr u) ( noop) ;
  65. : $Prtc ( l r --) DROP INTERP EMIT ;
  66. : $Prti ( l r --) DROP INTERP . ;
  67. : $Prts ( l r --) DROP INTERP \TYPE ;
  68. : $Not ( l r --) DROP INTERP 0= ;
  69. : $Negate ( l r --) DROP INTERP NEGATE ;
  70. : $Sequence ( l r --) SWAP INTERP INTERP ;
  71. : $Assign ( l r --) SWAP CELL+ @ >R INTERP R> ! ;
  72. : $While ( l r --)
  73. >R BEGIN DUP INTERP WHILE R@ INTERP REPEAT RDROP DROP ;
  74. : $If ( l r --) SWAP INTERP 0<> IF CELL+ THEN @ INTERP ;
  75. : $Subtract ( l r -- n) >R INTERP R> INTERP - ;
  76. : $Add >R INTERP R> INTERP + ;
  77. : $Mod >R INTERP R> INTERP MOD ;
  78. : $Multiply >R INTERP R> INTERP * ;
  79. : $Divide >R INTERP S>D R> INTERP SM/REM SWAP DROP ;
  80. : $Less >R INTERP R> INTERP < ;
  81. : $LessEqual >R INTERP R> INTERP <= ;
  82. : $Greater >R INTERP R> INTERP > ;
  83. : $GreaterEqual >R INTERP R> INTERP >= ;
  84. : $Equal >R INTERP R> INTERP = ;
  85. : $NotEqual >R INTERP R> INTERP <> ;
  86. : $And >R INTERP IF R> INTERP 0<> ELSE RDROP 0 THEN ;
  87. : $Or >R INTERP IF RDROP -1 ELSE R> INTERP 0<> THEN ;
  88. :NONAME DEFERS 'COLD GETAST INTERP BYE ; IS 'COLD