| 1 | Yaks Syntax
|
| 2 | ===========
|
| 3 |
|
| 4 | ## CST-Like IR
|
| 5 |
|
| 6 | (class ParseHay vm._Callable # we have limited infix . for readability
|
| 7 | # WASM also has this?
|
| 8 | (var fd_state process.FdState)
|
| 9 | (var parse_ctx parse_lib.ParseContext)
|
| 10 |
|
| 11 | (func _init [this.fd_state, this.parse_ctx, this.errfmt]
|
| 12 | )
|
| 13 |
|
| 14 | (func _Call [path Str] value_t
|
| 15 | (var call_loc loc.Missing)
|
| 16 |
|
| 17 | # https://stackoverflow.com/questions/16493079/how-to-implement-a-try-catch-block-in-scheme
|
| 18 |
|
| 19 | (try # extra level of indent is annoying
|
| 20 | (var f (this.fd_state.Open path))
|
| 21 | (except [IOError_OSError] [e]
|
| 22 | (var msg (posix.sterror e.errno))
|
| 23 | (throw error.Expr (fmt "Couldn't open "%r: %s" path msg) call_loc))
|
| 24 | (except ...
|
| 25 | )
|
| 26 | )
|
| 27 | )
|
| 28 | )
|
| 29 |
|
| 30 | (class ctx_Try []
|
| 31 | (var mutable_opts MutableOpts)
|
| 32 |
|
| 33 | (func _init [this.fd_state, this.parse_ctx, this.errfmt]
|
| 34 | (mutableOpts.Push option_i.errexit True)
|
| 35 | )
|
| 36 | (func _destroy []
|
| 37 | (this.mutable_ops.Pop option_i.errexit)
|
| 38 | )
|
| 39 | )
|
| 40 |
|
| 41 | OK this is actually not bad. And it saves us from reusing YSH syntax. Hm.
|
| 42 | think we just need the infix dot sugar in the reader?
|
| 43 |
|
| 44 | Note that the bootstrap compiler won't have `class try with`.
|
| 45 |
|
| 46 | - It will only have `func data enum`, `global var setvar`, `for while`, `if switch`.
|
| 47 | - Globals are always constants, and incur no startup time.
|
| 48 |
|
| 49 | ## Abandoned YSH-like syntax -- too much work
|
| 50 |
|
| 51 | Example of better syntax which we already support:
|
| 52 |
|
| 53 | func f(a List[Int], b Dict[Str, Int]) {
|
| 54 | case (node->tag()) {
|
| 55 | (command_e.Simple) {
|
| 56 | }
|
| 57 | (command_e.ShAssignment) {
|
| 58 | }
|
| 59 | }
|
| 60 |
|
| 61 | # We would need to add something like this?
|
| 62 | with (dev.ctx_Tracer(this.tracer, 'source', cmd_val.argv)) {
|
| 63 | var source_argv = arg_r.Rest() # C++ needs type inference here?
|
| 64 | }
|
| 65 | return (x)
|
| 66 | }
|
| 67 |
|
| 68 | Example of class support:
|
| 69 |
|
| 70 | class ParseHay : vm._Callable {
|
| 71 | var fd_state: process.FdState
|
| 72 | var parse_ctx: parse_lib.ParseContext
|
| 73 | var errfmt: ui.ErrorFormatter
|
| 74 |
|
| 75 | # auto-assign members, infer types
|
| 76 | func init(this.fd_state, this.parse_ctx, this.errfmt) {
|
| 77 | }
|
| 78 |
|
| 79 | func _Call(path Str) -> value_t {
|
| 80 | var call_loc = loc.Missing
|
| 81 | try {
|
| 82 | var f = this.fd_state.Open(path)
|
| 83 | } except (IOError, OSError) as e { # can paper over IOError
|
| 84 | var msg = posix.strerror(e.errno)
|
| 85 | throw error.Expr("Couldn't open %r: %s" % (path, msg), call_loc)
|
| 86 | }
|
| 87 | }
|
| 88 | }
|
| 89 |
|
| 90 | class ctx_Try {
|
| 91 | var mutable_opts: MutableOpts
|
| 92 |
|
| 93 | # would we have 'fn' that gets rid of :: ? Perhaps
|
| 94 | func _init(this.mutable_opts) {
|
| 95 | :: mutable_opts.Push(option_i.errexit, true)
|
| 96 | }
|
| 97 |
|
| 98 | func _destroy() {
|
| 99 | this.mutable_opts.Pop(option_i.errexit)
|
| 100 | }
|
| 101 | }
|
| 102 |
|
| 103 | - static stuff which I added in ysh/grammar.pgen2, now yaks/old/tea.pgen2
|
| 104 | - virtual override abstract - this isn't horrible
|
| 105 |
|
| 106 | Problem: this would break INTERPRETER flow, unless you generate Python! which
|
| 107 | is possible, though possibly ugly.
|
| 108 |
|
| 109 | This is another reason not to use it.
|
| 110 |
|