| 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 | 
 |