1 | # Runtime value
|
2 |
|
3 | module value
|
4 | {
|
5 | # import from frontend/syntax.asdl
|
6 | use frontend syntax {
|
7 | loc Token
|
8 | expr command
|
9 | DoubleQuoted
|
10 | re proc_sig
|
11 | LiteralBlock Func
|
12 | NameType
|
13 | EggexFlag
|
14 | }
|
15 |
|
16 | use core runtime {
|
17 | Cell
|
18 | }
|
19 |
|
20 | IntBox = (int i)
|
21 |
|
22 | ProcDefaults = (
|
23 | List[value]? for_word, # all of them are value.Str
|
24 | List[value]? for_typed,
|
25 | Dict[str, value]? for_named,
|
26 | value? for_block,
|
27 | )
|
28 |
|
29 | LeftName = (str name, loc blame_loc)
|
30 |
|
31 | # for setvar, and value.Place
|
32 | y_lvalue =
|
33 | # e.g. read (&x)
|
34 | Local %LeftName
|
35 | # e.g. &a[0][1].key -- we evaluate a[0][1] first
|
36 | | Container(value obj, value index)
|
37 |
|
38 | # An sh_lvalue is for things mutation that happen with dynamic scope
|
39 | #
|
40 | # - sh_expr_eval uses this for unset / printf -v
|
41 | # - word_eval uses this for ${a[0]=}
|
42 | # - expr_eval / cmd_eval use this for setvar a[i] = 42
|
43 | sh_lvalue =
|
44 | Var %LeftName
|
45 | | Indexed(str name, int index, loc blame_loc)
|
46 | | Keyed(str name, str key, loc blame_loc)
|
47 |
|
48 | eggex_ops =
|
49 | # for BASH_REMATCH or ~ with a string
|
50 | No
|
51 | # These lists are indexed by group number, and will have None entries
|
52 | | Yes(List[value?] convert_funcs, List[Token?] convert_toks,
|
53 | List[str?] capture_names)
|
54 |
|
55 | RegexMatch = (str s, List[int] indices, eggex_ops ops)
|
56 |
|
57 | regex_match =
|
58 | No
|
59 | | Yes %RegexMatch
|
60 |
|
61 | # Commands, words, and expressions from syntax.asdl are evaluated to a VALUE.
|
62 | # value_t instances are stored in state.Mem().
|
63 | value =
|
64 | # Methods on state.Mem return value.Undef, but it's not visible in YSH.
|
65 | #
|
66 | # A var bound to Undef is different than no binding because of dynamic
|
67 | # scope. Undef can shadow values lower on the stack.
|
68 | Undef
|
69 |
|
70 | | Str(str s)
|
71 |
|
72 | # "holes" in the array are represented by None
|
73 | # TODO: Use Dict[int, str] representation
|
74 | | BashArray(List[str] strs)
|
75 | | BashAssoc(Dict[str, str] d)
|
76 |
|
77 | # DATA model for YSH follows JSON. Note: YSH doesn't have 'undefined' and
|
78 | # 'null' like JavaScript, just 'null'.
|
79 | | Null
|
80 | | Bool(bool b)
|
81 | | Int(BigInt i)
|
82 | #| Int(int i)
|
83 | | Float(float f)
|
84 | | List(List[value] items)
|
85 | | Dict(Dict[str, value] d)
|
86 |
|
87 | # CODE types
|
88 | # unevaluated: Eggex, Expr, Template, Command/Block
|
89 | # callable, in separate namespaces: Func, BoundFunc, Proc
|
90 |
|
91 | # expr is spliced
|
92 | # / d+; ignorecase / -> '[[:digit:]]+' REG_ICASE
|
93 | | Eggex(re spliced, str canonical_flags,
|
94 | List[value?] convert_funcs, List[Token?] convert_toks,
|
95 | # str? is because some groups are not named
|
96 | str? as_ere, List[str?] capture_names)
|
97 |
|
98 | # The indices list has 2 * (num_group + 1) entries. Group 0 is the whole
|
99 | # match, and each group has both a start and end index.
|
100 | # It's flat to reduce allocations. The group() start() end() funcs/methods
|
101 | # provide a nice interface.
|
102 | | Match %RegexMatch
|
103 |
|
104 | # ^[42 + a[i]]
|
105 | | Expr(expr e)
|
106 |
|
107 | # ^(echo 1; echo 2) and cd { echo 1; echo 2 }
|
108 | | Command(command c)
|
109 |
|
110 | # for Hay to get the backing lines
|
111 | # TODO: Consolidate value.Command and value.LiteralBlock. All Command
|
112 | # instance should have backing lines.
|
113 |
|
114 | # TODO: ASDL doesn't support shared variant across module
|
115 | # This would be more efficient
|
116 | # | LiteralBlock %LiteralBlock
|
117 | | Block(LiteralBlock block)
|
118 |
|
119 | # A place has an additional stack frame where the value is evaluated.
|
120 | # The frame MUST be lower on the stack at the time of use.
|
121 | | Place(y_lvalue lval, Dict[str, Cell] frame)
|
122 |
|
123 | # for Flags/flag and Flags/arg?
|
124 | # for json read/write ?
|
125 | # Possibly unify Hay and modules/namespaces
|
126 | | Module(Dict[str, value] defs)
|
127 |
|
128 | # The ability to use operating system functions. Right now some functions
|
129 | # leak, like glob().
|
130 | | IO(any cmd_ev, any prompt_ev)
|
131 |
|
132 | # Do we need this?
|
133 | # _guts->heapId() can be used to detect object cycles.
|
134 | # It's considered impure; it depends on VM implementation details. The =
|
135 | # operator and 'pp value' also print the heap ID.
|
136 | | Guts(any vm)
|
137 |
|
138 | # callable is vm._Callable.
|
139 | # TODO: ASDL needs some kind of "extern" to declare vm._Callable and
|
140 | # cmd_eval.CommandEvaluator. I think it would just generate a forward
|
141 | # declaration.
|
142 | | BuiltinFunc(any callable)
|
143 | | BoundFunc(value me, value func)
|
144 |
|
145 | # command.ShFunction and command.Proc evaluate to value.Proc
|
146 | # They each have name, name_tok, and body.
|
147 | #
|
148 | # YSH procs disable dynamic scope, have default args to evaluate, and
|
149 | # different @ARGV.
|
150 |
|
151 | | Proc(str name, Token name_tok, proc_sig sig, command body,
|
152 | ProcDefaults? defaults, bool sh_compat)
|
153 |
|
154 | # module may be a frame where defined
|
155 | | Func(str name, Func parsed,
|
156 | List[value] pos_defaults, Dict[str, value] named_defaults,
|
157 | Dict[str, Cell]? module_)
|
158 |
|
159 | # a[3:5] a[:10] a[3:] a[:] # both ends are optional
|
160 | | Slice(IntBox? lower, IntBox? upper)
|
161 |
|
162 | # for i in (1:n) { echo $i } # both ends are required
|
163 | | Range(int lower, int upper)
|
164 | }
|
165 |
|
166 | # vim: sw=2
|
167 |
|