1 #!/usr/bin/env python2
2 """Frontend/builtin_def.py.
3
4 Metadata:
5
6 - Is used for lookup in cmd_eval.py
7 - Should be used for completion
8 - complete names of builtins
9 - complete flags they take
10 - handle aliases : . and source, [ and test
11 - Should be reflected in the contents of the 'help' builtin
12
13 NOTE: bash has help -d -m -s. Default is -s, like a man page.
14
15 Links on special builtins:
16 http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_14
17 """
18 from __future__ import print_function
19
20 from typing import Dict, List, Optional, Any
21
22 # Special builtins can't be redefined by functions. On the other hand, 'cd'
23 # CAN be redefined.
24 #
25 # http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_14
26 # https://www.gnu.org/software/bash/manual/html_node/Special-Builtins.html
27
28 # yapf: disable
29 _NORMAL_BUILTINS = [
30 'read', 'echo', 'printf', 'mapfile', 'readarray',
31
32 'cd', 'pushd', 'popd', 'dirs', 'pwd',
33
34 'source', # note that . alias is special
35
36 'umask', 'wait', 'jobs', 'fg', 'bg',
37
38 'shopt',
39 'complete', 'compgen', 'compopt', 'compadjust', 'compexport',
40
41 'getopts',
42
43 # introspection
44 'command', 'type', 'hash', 'help', 'history',
45
46 'alias', 'unalias',
47 'bind',
48
49 #
50 # YSH
51 #
52 'append',
53 'write', 'json', 'j8', 'pp',
54 'hay', 'haynode',
55 'module', 'use',
56 'error',
57
58 # take a block
59 # push-registers added below
60 'fork', 'forkwait',
61 'fopen',
62 'shvar',
63
64 'runproc',
65 'boolstatus',
66 ]
67 # yapf: enable
68
69
70 class _Builtin(object):
71 def __init__(self, index, name, enum_name=None, kind='normal'):
72 # type: (int, str, Optional[str], str) -> None
73 """
74 kind: normal, special, assign
75 """
76 self.index = index
77 self.name = name # e.g. : or [
78 self.enum_name = enum_name or name # e.g. builtin_num::colon
79 self.kind = kind
80
81
82 class _BuiltinDef(object):
83 """
84 NOTE: This isn't used anywhere! We're registering nothing.
85
86 We want to complete the flags to builtins. So this is a mapping from name
87 to arg spec. There might not be any flags.
88 """
89
90 def __init__(self):
91 # type: () -> None
92 self.builtins = [] # type: List[_Builtin]
93 self.index = 1 # start with 1
94
95 def Add(self, *posargs, **kwargs):
96 # type: (Any, Any) -> None
97 # NOTE: *posargs works around flake8/pyflakes bug!
98 self.builtins.append(_Builtin(self.index, *posargs, **kwargs))
99 self.index += 1
100
101
102 def _Init(b):
103 # type: (_BuiltinDef) -> None
104
105 #
106 # Special builtins
107 #
108
109 b.Add(':', enum_name='colon', kind='special')
110 b.Add('.', enum_name='dot', kind='special')
111 # Python keyword
112 b.Add('exec', enum_name='exec_', kind='special')
113 for name in ['eval', 'set', 'shift', 'times', 'trap', 'unset', 'builtin']:
114 b.Add(name, kind='special')
115
116 #
117 # Assignment builtins.
118 # Note: control flow aren't builtins in OSH: break continue return
119 #
120
121 for name in ["readonly", "local", "declare", "typeset"]:
122 b.Add(name, kind='assign')
123 b.Add('export', enum_name='export_', kind='assign') # C++ keyword conflict
124
125 b.Add('true', enum_name='true_') # C++ Keywords
126 b.Add('false', enum_name='false_')
127 b.Add('try', enum_name='try_')
128
129 for name in _NORMAL_BUILTINS:
130 b.Add(name)
131
132 # Slight variants
133 b.Add('test')
134 b.Add('[', enum_name='bracket')
135
136 b.Add('push-registers', enum_name='push_registers')
137 b.Add('is-main', enum_name='is_main')
138
139 # Implementation detail of $(<file)
140 # TODO: change to 'internal cat' (issue 1013)
141 b.Add('__cat', enum_name='cat')
142
143
144 _BUILTIN_DEF = _BuiltinDef()
145
146 _Init(_BUILTIN_DEF)
147
148 # Exposed in consts.py for completion
149 BUILTIN_NAMES = [b.name for b in _BUILTIN_DEF.builtins]
150
151
152 def All():
153 # type: () -> List[_Builtin]
154 return _BUILTIN_DEF.builtins
155
156
157 def BuiltinDict():
158 # type: () -> Dict[str, _Builtin]
159 """For the slow path in frontend/match.py."""
160 return dict((b.name, b) for b in _BUILTIN_DEF.builtins)