| 1 | # Data types used at runtime
 | 
| 2 | 
 | 
| 3 | module runtime
 | 
| 4 | {
 | 
| 5 |   # import from frontend/syntax.asdl
 | 
| 6 |   use frontend syntax {
 | 
| 7 |     loc Token
 | 
| 8 |     expr word command
 | 
| 9 |     CompoundWord DoubleQuoted
 | 
| 10 |     ArgList re redir_loc proc_sig 
 | 
| 11 |     LiteralBlock Func
 | 
| 12 |   }
 | 
| 13 | 
 | 
| 14 |   use core value {
 | 
| 15 |     value
 | 
| 16 |   }
 | 
| 17 | 
 | 
| 18 |   # Evaluating SimpleCommand results in either an argv array or an assignment.
 | 
| 19 |   # in 'local foo', rval is None.
 | 
| 20 |   AssignArg = (str var_name, value? rval, bool plus_eq, CompoundWord blame_word)
 | 
| 21 | 
 | 
| 22 |   # note: could import 'builtin' from synthetic option_asdl
 | 
| 23 |   cmd_value =
 | 
| 24 |     Argv(List[str] argv, List[CompoundWord] arg_locs,
 | 
| 25 |          ArgList? typed_args,
 | 
| 26 |          # Evaluated args, similar to typed_args.py Reader
 | 
| 27 |          List[value]? pos_args, Dict[str, value]? named_args,
 | 
| 28 |          # block_arg comes from either p (; ; myblock) or p { echo b }
 | 
| 29 |          value? block_arg)
 | 
| 30 | 
 | 
| 31 |   | Assign(int builtin_id,
 | 
| 32 |            List[str] argv, List[CompoundWord] arg_locs,
 | 
| 33 |            List[AssignArg] pairs)
 | 
| 34 | 
 | 
| 35 |   # - Single or double quoted parts get neither split or globbed.
 | 
| 36 |   # - Bare words like echo or *.py are globbed, but NOT split with IFS.
 | 
| 37 |   # - Unquoted Substitutions are split and globbed.
 | 
| 38 |   Piece = (str s, bool quoted, bool do_split)
 | 
| 39 | 
 | 
| 40 |   # A parse-time word_part from syntax.asdl is evaluated to a runtime
 | 
| 41 |   # part_value.
 | 
| 42 |   part_value = 
 | 
| 43 |     String %Piece
 | 
| 44 | 
 | 
| 45 |     # "$@" or "${a[@]}" # never globbed or split (though other shells
 | 
| 46 |     # split them)
 | 
| 47 |   | Array(List[str] strs)
 | 
| 48 |     # only produced when EXTGLOB_FS flag is passed
 | 
| 49 |   | ExtGlob(List[part_value] part_vals)
 | 
| 50 | 
 | 
| 51 |   coerced = Int | Float | Neither
 | 
| 52 | 
 | 
| 53 |   # evaluation state for BracedVarSub 
 | 
| 54 |   VarSubState = (bool join_array, bool is_type_query, bool has_test_op)
 | 
| 55 | 
 | 
| 56 |   # A Cell is a wrapper for a value.
 | 
| 57 |   # TODO: add location for declaration for 'assigning const' error
 | 
| 58 | 
 | 
| 59 |   # Invariant: if exported or nameref is set, the val should be Str or Undef.
 | 
| 60 |   # This is enforced in mem.SetValue but isn't expressed in the schema.
 | 
| 61 |   Cell = (bool exported, bool readonly, bool nameref, value val)
 | 
| 62 | 
 | 
| 63 |   # Where scopes are used
 | 
| 64 |   # Shopt: to respect shopt -u dynamic_scope.
 | 
| 65 |   #   Dynamic -> LocalOrGlobal for reading
 | 
| 66 |   #   Dynamic -> LocalOnly for writing.
 | 
| 67 |   # Dynamic:
 | 
| 68 |   #   GetValue: Shell Style
 | 
| 69 |   #   SetValue: Shell Style
 | 
| 70 |   # LocalOrGlobal:
 | 
| 71 |   #   GetValue: Oil style
 | 
| 72 |   #   SetValue: N/A
 | 
| 73 |   # LocalOnly:
 | 
| 74 |   #   GetValue: N/A, we can always READ globals
 | 
| 75 |   #   SetValue: setvar, parameter bindings, for loop iterator vars
 | 
| 76 |   # GlobalOnly:
 | 
| 77 |   #   GetValue: N/A
 | 
| 78 |   #   SetValue: internal use in COMPREPLY, and Oil's 'setglobal' keyword
 | 
| 79 | 
 | 
| 80 |   scope = Shopt | Dynamic | LocalOrGlobal | LocalOnly | GlobalOnly
 | 
| 81 | 
 | 
| 82 |   # What is valid in arrays or assoc arrays a[i] or A[i] in shell.
 | 
| 83 |   # Used for ${a[i]=x}.
 | 
| 84 |   a_index = Str(str s) | Int(int i)
 | 
| 85 | 
 | 
| 86 |   # For the place in ${a[0]=a}
 | 
| 87 |   # Transformed into sh_lvalue_t
 | 
| 88 |   VTestPlace = (str? name, a_index? index)
 | 
| 89 | 
 | 
| 90 |   redirect_arg =
 | 
| 91 |     Path(str filename)
 | 
| 92 |   | CopyFd(int target_fd)
 | 
| 93 |   | MoveFd(int target_fd)  # 3>&1-
 | 
| 94 |   | CloseFd
 | 
| 95 |   | HereDoc(str body)  # call this String and combine with Path?
 | 
| 96 | 
 | 
| 97 |   # Evaluated version of syntax.Redir
 | 
| 98 |   RedirValue = (id op_id, loc op_loc, redir_loc loc, redirect_arg arg)
 | 
| 99 | 
 | 
| 100 |   # An exit status with location info.  For process sub.
 | 
| 101 |   StatusArray = (
 | 
| 102 |     List[int]? codes,  # init to null, rarely allocated
 | 
| 103 |     List[loc]? locs    # init to null, rarely allocated
 | 
| 104 |   )
 | 
| 105 | 
 | 
| 106 |   CommandStatus = (
 | 
| 107 |     # set for atoms
 | 
| 108 |     bool check_errexit,
 | 
| 109 | 
 | 
| 110 |     # By default, don't show the code on errexit.  Sometimes we want to.
 | 
| 111 |     bool show_code
 | 
| 112 | 
 | 
| 113 |     # Should we use 'int simple_status' for atoms like atoms like ls  ((  [[ ?
 | 
| 114 | 
 | 
| 115 |     # for pipeline
 | 
| 116 |     bool pipe_negated,
 | 
| 117 |     List[int]? pipe_status,  # init to null, rarely allocated
 | 
| 118 |     List[loc]? pipe_locs,    # init to null, rarely allocated
 | 
| 119 |   )
 | 
| 120 | 
 | 
| 121 |   wait_status =
 | 
| 122 |     Proc(int code)
 | 
| 123 |   | Pipeline(List[int] codes)
 | 
| 124 |     # because the 'wait' builtin is interruptible
 | 
| 125 |   | Cancelled(int sig_num)
 | 
| 126 | 
 | 
| 127 |   flow = Nothing | Break | Raise
 | 
| 128 | 
 | 
| 129 |   # For word splitting (in frontend/consts.py and osh/split.py)
 | 
| 130 |   span = Black | Delim | Backslash
 | 
| 131 | 
 | 
| 132 |   emit = Part | Delim | Empty | Escape | Nothing
 | 
| 133 |          generate [integers]
 | 
| 134 |   state = Invalid | Start | DE_White1 | DE_Gray | DE_White2 | Black | Backslash | Done
 | 
| 135 |           generate [integers]
 | 
| 136 | 
 | 
| 137 |   # Edges are characters.  DE_ is the delimiter prefix.  DE_White is for
 | 
| 138 |   # whitespace; DE_Gray is for other IFS chars; Black is for significant
 | 
| 139 |   # characters.  Sentinel is the end of the string.
 | 
| 140 |   char_kind = DE_White | DE_Gray | Black | Backslash | Sentinel
 | 
| 141 |               generate [integers]
 | 
| 142 | 
 | 
| 143 |   # core/process.py
 | 
| 144 |   # A Job is a Process or Pipeline.
 | 
| 145 |   # - Processes usually go from Running to Stopped, unless unless Ctrl-Z stops
 | 
| 146 |   #   them.
 | 
| 147 |   # - Pipelines go Running to Done.  They are never stopped; only the processes
 | 
| 148 |   #   inside them are stopped.
 | 
| 149 |   job_state = Running | Done | Stopped
 | 
| 150 | 
 | 
| 151 |   # Flag arguments can be any of these types.
 | 
| 152 |   flag_type = Bool | Int | Float | Str
 | 
| 153 | 
 | 
| 154 |   # For dev.Tracer
 | 
| 155 |   trace =
 | 
| 156 |     External(List[str] argv) # sync, needs argv (command.Simple or 'command')
 | 
| 157 |   | CommandSub               # sync
 | 
| 158 |   | ForkWait                 # sync
 | 
| 159 |   | Fork                     # async, needs argv, & fork
 | 
| 160 |   | PipelinePart             # async
 | 
| 161 |   | ProcessSub               # async (other processes can be started)
 | 
| 162 |   | HereDoc                  # async (multiple here docs per process)
 | 
| 163 | 
 | 
| 164 |   # tools/ysh_ify.py
 | 
| 165 |   word_style = Expr | Unquoted | DQ | SQ
 | 
| 166 | 
 | 
| 167 |   # Hay "first word" namespace
 | 
| 168 |   HayNode = (Dict[str, HayNode] children)
 | 
| 169 | 
 | 
| 170 |   comp_action = Other | FileSystem | BashFunc
 | 
| 171 | }
 | 
| 172 | 
 | 
| 173 | # vim: sw=2
 |