-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathrepl.dg
118 lines (98 loc) · 4.24 KB
/
repl.dg
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import '/re'
import '/sys'
import '/time'
import '/types'
import '/asyncio'
import '/builtins'
import 'BUILTINS'
import 'Name'
import 'LeftBind'
import 'Expression'
import 'Compiler'
import 'add_module_builtins'
import 'parse'
import 'compilefd'
import 'compileast'
except
_err => import 'readline'
_err :: ImportError =>
Readline = subclass object where __init__, input = (*: _ **: _ ~> None), builtins.input
_err is None =>
Readline = subclass readline.History readline.Completer readline.Readline where
# Matches any number of valid dg identifiers separated by dots.
# (No whitespace!)
completion_regex = re.compile r"\w+'*(?:\.\w+'*)*\.?"
# This attribute must be set to the global namespace.
# Otherwise, variables defined from within the REPL will not be completed.
completion_ns = dict!
# Display only the attribute name when listing possible completions.
# The rest (i.e. the object itself) is irrelevant and is always the same.
display_completions = cmps ~>
(super Readline self).display_completions $
list $ map (x -> last $ x.split '.') cmps
# Complete a variable or an attribute name (i.e. `VAR.VAR....[VAR]`.)
# This method simulates `rlcompleter`. (It can even evaluate arbitrary
# code via `__getattr__`, too. WARNING, I guess.)
complete_word = word ~>
path, dot, word = word.rpartition '.'
sorted $ map (path + dot +) $
# Hide private attributes unless an underscore was typed.
filter (w -> w.startswith word and (word or not (w.startswith '_'))) $ if
not path => set Compiler.prefix | set BUILTINS | set @completion_ns
otherwise => except
err => dir $ eval path @completion_ns
err :: Exception => []
compilerepl = source globals: () -> except
e =>
tree = parse source '<input>'
expr = next $ dropwhile (x -> x :: Expression and not x.closed) $
iterate (x -> last x.args) tree
# Tap `Return` twice to override any of these checks.
done = source.endswith '\n' or not
# There may be an indented block in the next line if
# 1. the last operator has no right-hand side;
expr :: LeftBind and not expr.op.norhs or
# 2. the last expression is accessing a built-in, which
# doesn't make sense (unlike a call to that built-in;)
expr :: Name and not expr.closed and expr.value in Compiler.prefix or
# 3. the last line of the code is indented.
(last $ source.rsplit '\n' 1).startswith ' '
if done => compileast tree globals, (tree :: Expression and tree.op == '=')
otherwise => None, False
# Open strings or blocks may be continued, too. (Tapping `Return` won't help.)
e :: SyntaxError and (head e.args).startswith 'unexpected EOF' => None, False
runcode = code ->
md = sys.modules !! '__main__' = types.ModuleType '__main__'
md.__file__ = code.co_filename
add_module_builtins md
eval code md.__dict__
runrepl = fd ->
sys.stdin = fd
sys.ps1 = getattr sys 'ps1' '>>> '
sys.ps2 = getattr sys 'ps2' '... '
module = sys.modules !! '__main__' = types.ModuleType '__main__'
add_module_builtins module
rdl = Readline sys.stdin sys.stdout
rdl.completion_ns = module.__dict__
coroutine = getattr types 'CoroutineType' None
while True => except
e => x, assignment = next $ dropwhile (not <- fst) $
map (x -> compilerepl x module.__dict__) $
iterate (x -> x + '\n' + rdl.input sys.ps2) $ rdl.input sys.ps1
e :: EOFError => raise SystemExit
e :: SystemExit => raise e
e :: KeyboardInterrupt => print '' file: sys.stderr
e :: BaseException => sys.excepthook (type e) e e.__traceback__, time.sleep 0.1
e is None => except
e =>
v = eval x module.__dict__
not assignment =>
coroutine and v :: coroutine =>
v = asyncio.get_event_loop!.run_until_complete v
sys.displayhook v
hasattr builtins '_' => module._ = builtins._
e :: SystemExit => raise e
e :: BaseException => sys.excepthook (type e) e e.__traceback__
runfile = fd -> if
fd.isatty! => runrepl fd
otherwise => runcode $ compilefd fd $ getattr fd 'name' '<input>'