pausable.slide 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. Pause-able Parsing and Elegant Interpreters in Go: Using Goroutines as Coroutines
  2. 20 September 2016
  3. Tags: zygomys, coroutines, pause-able parsing
  4. Jason E. Aten, Ph.D.
  5. Principal Engineer, Sauce Labs
  6. [email protected]
  7. @jasonaten_
  8. https://github.com/glycerine/zygomys
  9. [[https://github.com/glycerine/zygomys/wiki.]] The wiki has details, examples, and discussion.
  10. * problem: implementating an interpreter efficiently
  11. - suppose your code is running, and deep inside a nested set of possibly mutually recursive calls...
  12. - and you run out of input.
  13. - ... do you start all over?
  14. - ... and take O(n^2) time to parse an n-line program? Ouch.
  15. - you want to save your state, and resume later, exactly where you left off...
  16. - this is exactly what happens at the interpreter prompt
  17. * generally
  18. - how to refactor your straight line code...
  19. - to pause - and - resume gracefully
  20. - to be interuptable
  21. - to be lazy
  22. * benefits of this style
  23. - more coherency: keep the readability of straight-line code
  24. - insert pause points after the fact
  25. - easier to read => means easier to maintain, refactor, and extend
  26. * context: zygomys interpreter
  27. - an interpreted scripting language
  28. - built in Go, for steering Go
  29. - reflect to invoke compiled Go code
  30. - zygomys has closures with lexical scope
  31. - for loops
  32. - higher order functions
  33. - readable math: anything inside curly braces {} is infix. example: a = 2 * 5 + 4 / 2
  34. .link https://github.com/glycerine/zygomys https://github.com/glycerine/zygomys
  35. * context II: architecture / overview of zygomys implementation
  36. - a) lexer produces tokens
  37. - b) parser produces lists and arrays of symbols <<<== focus of this talk
  38. - c) macros run at definition type
  39. - d) codegen produces s-expression byte-code
  40. - e) a virtual machine executes the byte-code
  41. * what specifically changes to make code pause-able? And more importantly, resumable?
  42. * original parseArray (only 50% shown/fits on a screen)
  43. .code orig.parser1.go
  44. * before, closeup
  45. .code before1.go
  46. * after, closeup
  47. .code after1.go
  48. * zoom out: after in full context
  49. .code after1full.go
  50. * the key was getMoreInput() call instead of returning io.EOF... simple enough, but...
  51. * that begs the question, how does getMoreInput() work...
  52. * apparently the real magic is in getMoreInput(). It must be doing the heavy lifting...
  53. * getMoreInput()
  54. .code getmore2.go
  55. * HaveStuffToSend() is easy...
  56. .code havestuff.go
  57. * what is unusual about getMoreInput()
  58. - it can be called from multiple places
  59. - callers get to retain the entire context of their call stack
  60. - getMoreInput() returns to its caller precisely once the caller can continue
  61. - and in the meantime, it does the channel work in a select{} to get more input from an asynchronous source
  62. - In my humble experience, this is rare: a co-routine pattern
  63. - Caller's code gets to pause. And then resume, right where it left off.
  64. * supporting player: a background goroutine running an infinite loop that drives parsing. It also calls getMoreInput() to start top-level parsing.
  65. .code infparse_nocomment.go
  66. * call graph
  67. .image med2.jpg
  68. * so what does the Parser API look like from the outside?
  69. * here is what the user sees:
  70. * what the Parser API looks like
  71. .code parser_api.go
  72. * conclusion
  73. - coroutine patterns are viable in Go
  74. - we can avoid O(n^2) time interpreter parsing
  75. - other uses: functional programming patterns like (lazy) generators[1]
  76. -
  77. -
  78. [1] John Hughes, Why Functional Programming Matters
  79. .link https://www.cs.kent.ac.uk/people/staff/dat/miranda/whyfp90.pdf