environment.go 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. package attl
  2. // Maximum amount of frames,
  3. // to prevent unlimited recursion.
  4. const FRAMES_MAX = 80
  5. type Writer interface {
  6. Write(p []byte) (n int, err error)
  7. }
  8. type Reader interface {
  9. Read(p []byte) (n int, err error)
  10. }
  11. type Frame struct {
  12. Variables Map
  13. Effect
  14. Out Writer
  15. In Reader
  16. Rescuer Value
  17. }
  18. type Environment struct {
  19. Frames []*Frame
  20. Out Writer
  21. In Reader
  22. Rescuing bool
  23. }
  24. // Looks up the value of a variable and the frame it is in
  25. func (env Environment) LookupFrame(name string) (Value, *Frame) {
  26. for i := len(env.Frames) - 1; i >= 0; i-- {
  27. frame := env.Frames[i]
  28. val, ok := frame.Variables[name]
  29. if ok {
  30. return val, frame
  31. }
  32. }
  33. return nil, nil
  34. }
  35. func (env Environment) Lookup(name string) Value {
  36. val, _ := env.LookupFrame(name)
  37. return val
  38. }
  39. func (env *Environment) Push() *Error {
  40. env.Frames = append(env.Frames, &Frame{make(Map), nil, env.Out, env.In, nil})
  41. if len(env.Frames) >= FRAMES_MAX && !env.Rescuing {
  42. return ErrorFromString("PROGRAM HAS DISAPPEARED INTO THE BLACK LAGOON - too much recursion or function calls")
  43. }
  44. return nil
  45. }
  46. func (env *Environment) Pop() {
  47. l := len(env.Frames)
  48. if l > 0 {
  49. env.Frames = env.Frames[0 : l-1]
  50. }
  51. }
  52. // Depth returns the amount of frames on the frame stack
  53. func (env *Environment) Depth() int {
  54. return len(env.Frames)
  55. }
  56. // Frame returns a frame pointer based on the level.
  57. // 0 is the top-level index. A negative level wil refer to the
  58. // outermost frame.
  59. // Returns nil if the level is somehow out of range or
  60. // if no frames have been pushed yet
  61. func (env *Environment) Frame(level int) *Frame {
  62. if len(env.Frames) < 1 {
  63. return nil
  64. }
  65. if level > 0 {
  66. l := len(env.Frames)
  67. index := l - level - 1
  68. if index < 0 || index >= l {
  69. return nil
  70. }
  71. return env.Frames[index]
  72. } else {
  73. return env.Frames[0]
  74. }
  75. }
  76. // Top returns a pointer to the top or
  77. // inner most Frame of the environment's frame stack
  78. func (env *Environment) Top() *Frame {
  79. if len(env.Frames) > 0 {
  80. index := len(env.Frames) - 1
  81. return env.Frames[index]
  82. }
  83. return nil
  84. }
  85. // Botttom returns a pointer to the bottom or// outer most Frame of the environment
  86. func (env *Environment) Bottom() *Frame {
  87. if len(env.Frames) > 0 {
  88. return env.Frames[0]
  89. }
  90. return nil
  91. }
  92. // Defines the variable in the given scope level
  93. func (env *Environment) Define(name string, val Value, level int) (Value, Effect) {
  94. frame := env.Frame(level)
  95. if frame == nil {
  96. return nil, ErrorFromString("no such frame available.")
  97. }
  98. frame.Variables[name] = val
  99. return val, nil
  100. }
  101. // Looks up the variable and sets it in the scope where it is found.
  102. // Returns an error if no such variable could be found.
  103. func (env *Environment) Set(name string, val Value) (Value, Effect) {
  104. _, frame := env.LookupFrame(name)
  105. if frame == nil {
  106. return nil, ErrorFromString("no such variable")
  107. }
  108. frame.Variables[name] = val
  109. return val, nil
  110. }
  111. func (env *Environment) Rescuer() Value {
  112. frame := env.Top()
  113. if frame == nil {
  114. return nil
  115. }
  116. return frame.Rescuer
  117. }
  118. // Prevent sets the rescue block to use for
  119. // the top frame of the environment.
  120. // It returns the previous rescuer.
  121. func (env *Environment) Prevent(block Block) (Value, Effect) {
  122. frame := env.Frame(1)
  123. if frame == nil {
  124. return env.FailString("Could not set rescuer")
  125. }
  126. old := frame.Rescuer
  127. frame.Rescuer = Rescue{block}
  128. return old, nil
  129. }
  130. //
  131. func (env *Environment) Rescue(res Value, eff Effect) (Value, Effect) {
  132. if eff == nil || eff.Flow() < FailFlow {
  133. return res, eff
  134. }
  135. // if there is no rescue installed,
  136. // just return as is.
  137. if env.Rescuer() == nil {
  138. return res, eff
  139. }
  140. // failures become normal returns
  141. // if the rescue didn't fail.
  142. val := eff.Unwrap()
  143. rres, reff := env.Rescuer().Eval(env, val, res)
  144. if reff == nil {
  145. return env.Return(rres)
  146. } else {
  147. // Here, unpack the effect and replace it with a return
  148. // to avoid recursion loops of fail in rescue
  149. return env.Return(reff.Unwrap())
  150. }
  151. }
  152. func (env *Environment) Flow() Flow {
  153. if len(env.Frames) > 0 {
  154. index := len(env.Frames) - 1
  155. return env.Frames[index].Flow()
  156. }
  157. return FailFlow
  158. }
  159. func (env *Environment) SetEffect(e Effect) Effect {
  160. frame := env.Frame(1)
  161. if frame != nil {
  162. frame.Effect = e
  163. }
  164. return e
  165. }
  166. func (env *Environment) Return(val Value) (Value, Effect) {
  167. effect := env.SetEffect(Return{val})
  168. return val, effect
  169. }
  170. func (env *Environment) Fail(err *Error) (Value, Effect) {
  171. effect := env.SetEffect(err)
  172. return nil, effect
  173. }
  174. func (env *Environment) Break(val Value) (Value, Effect) {
  175. effect := env.SetEffect(Break{val})
  176. return val, effect
  177. }
  178. func (env *Environment) FailString(msg string, args ...Value) (Value, Effect) {
  179. return env.Fail(env.ErrorFromString(msg, args...))
  180. }
  181. func (env Environment) Interpolate(s string, args ...Value) string {
  182. runes := []rune(s)
  183. res := []rune{}
  184. name := []rune{}
  185. inName := 0
  186. for i, a := range args {
  187. env.Define(Itoa(i+1), a, 0)
  188. }
  189. apply := func() {
  190. inName = 0
  191. val := env.Lookup(string(name))
  192. if val == nil {
  193. res = append(res, '!', 'n', 'i', 'l')
  194. } else {
  195. add := []rune(val.String())
  196. res = append(res, add...)
  197. }
  198. name = []rune{}
  199. }
  200. for i := 0; i < len(runes); i++ {
  201. r := runes[i]
  202. switch r {
  203. case '$':
  204. if inName == 0 {
  205. inName = 1
  206. } else if inName == 1 {
  207. if len(name) < 1 {
  208. // $$ escape
  209. res = append(res, '$')
  210. inName = 0
  211. } else { // $ at end of name
  212. apply()
  213. }
  214. }
  215. case '{':
  216. if inName > 0 {
  217. inName++
  218. } else {
  219. res = append(res, '{')
  220. }
  221. case '}':
  222. if inName > 0 {
  223. inName--
  224. if inName == 1 {
  225. apply()
  226. }
  227. } else {
  228. res = append(res, '}')
  229. }
  230. default:
  231. if inName > 0 {
  232. if IsNumber(r) || IsLetter(r) {
  233. name = append(name, r)
  234. } else {
  235. apply()
  236. res = append(res, r)
  237. }
  238. } else {
  239. res = append(res, r)
  240. }
  241. }
  242. }
  243. if len(name) > 0 {
  244. apply()
  245. }
  246. return string(res)
  247. }
  248. func (env Environment) Printi(msg string, args ...Value) (int, error) {
  249. msg = env.Interpolate(msg, args...)
  250. return env.Write(msg)
  251. }
  252. func (env Environment) Write(msg string) (int, error) {
  253. buf := []byte(msg)
  254. writer := env.Out
  255. if len(env.Frames) > 0 {
  256. writer = env.Frames[len(env.Frames)-1].Out
  257. }
  258. if writer == nil {
  259. return -1, env.ErrorFromString("no writer set in environment.")
  260. }
  261. return writer.Write(buf)
  262. }
  263. func (env Environment) ErrorFromString(msg string, args ...Value) *Error {
  264. msg = env.Interpolate(msg, args...)
  265. return ErrorFromString(msg)
  266. }
  267. // Complete is for use with liner
  268. func (env Environment) Complete(prefix String) List {
  269. res := List{}
  270. for _, frame := range env.Frames {
  271. for name, _ := range frame.Variables {
  272. if len(name) >= len(prefix) {
  273. if String(name[0:len(prefix)]) == prefix {
  274. res = append(res, String(name))
  275. }
  276. }
  277. }
  278. }
  279. if len(res) == 0 {
  280. res = append(res, prefix)
  281. }
  282. return res.SortStrings()
  283. }
  284. func (env *Environment) Overload(name string, target Value, types []Value) (Value, Effect) {
  285. val := env.Lookup(name)
  286. cov, ok := val.(Overload)
  287. if val == nil {
  288. cov = make(Overload)
  289. } else if !ok {
  290. return env.FailString("Not a overload: " + name)
  291. }
  292. signature := ""
  293. for _, arg := range types {
  294. signature += "_" + arg.String()
  295. }
  296. if _, ok := target.(String); ok {
  297. tarVal := env.Lookup(target.String())
  298. cov[signature] = tarVal
  299. } else if _, ok := target.(Word); ok {
  300. tarVal := env.Lookup(target.String())
  301. cov[signature] = tarVal
  302. } else {
  303. cov[signature] = target
  304. }
  305. env.Define(name, cov, -1)
  306. return cov, nil
  307. }