Skip to content

Commit 5539b90

Browse files
committed
WIP implement set
1 parent 5404221 commit 5539b90

File tree

11 files changed

+74
-32
lines changed

11 files changed

+74
-32
lines changed

src/mash/shell/ast/infix.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121

2222
class Infix(Node):
23-
def __init__(self, lhs: Node, rhs: Node, op=None):
23+
def __init__(self, lhs: Node, rhs: Node, op: str):
2424
"""An infix operator expression.
2525
2626
Parameters
@@ -164,6 +164,8 @@ class Map(Infix):
164164
165165
range 10 >>= echo The value is $ .
166166
"""
167+
def __init__(self, lhs: Node, rhs: Node):
168+
super().__init__(lhs, rhs, 'map')
167169

168170
def run(self, prev_result='', shell: BaseShell = None, lazy=False):
169171
prev = shell.run_commands(self.lhs, prev_result, run=not lazy)

src/mash/shell/ast/set_definition.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from mash.shell.ast.node import Node
44
from mash.shell.base import BaseShell
5+
from mash.shell.cmd2 import Mode
56

67

78
class SetDefinition(Node):
@@ -26,10 +27,11 @@ def __init__(self, items, condition=None):
2627

2728
def run(self, prev_result='', shell: BaseShell = None, lazy=False):
2829
items = []
29-
for item in self.items.values:
30-
results = shell.run_commands(item)
31-
for row in results:
32-
items.append(row.splitlines())
30+
with shell.use_mode(Mode.COMPILE):
31+
for item in self.items.values:
32+
results = shell.run_commands(item)
33+
for row in results:
34+
items.append(row.splitlines())
3335

3436
if lazy:
3537
return f'{{ {self.items} | {self.condition} }}'

src/mash/shell/cmd2.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
from asyncio import CancelledError
22
import cmd
3+
from contextlib import contextmanager
4+
from enum import Enum, auto
35
import logging
46
from pathlib import Path
57
import traceback
68

79
from mash import io_util
8-
import cmd
910
from mash.io_util import log, read_file, shell_ready_signal, check_output
1011
from mash.shell.errors import ShellError, ShellSyntaxError
1112
import mash.shell.function as func
@@ -15,6 +16,11 @@
1516
default_prompt = '$ '
1617

1718

19+
class Mode(Enum):
20+
REPL = auto()
21+
COMPILE = auto()
22+
23+
1824
class Cmd2(cmd.Cmd):
1925
"""Extend cmd.Cmd with various capabilities.
2026
This class is restricted to functionality that requires Cmd methods to be overrriden.
@@ -40,6 +46,7 @@ class Cmd2(cmd.Cmd):
4046
prompt = default_prompt
4147
completenames_options = []
4248
ignore_invalid_syntax = False
49+
mode = Mode.REPL
4350

4451
def onecmd(self, line: str) -> bool:
4552
"""Parse and run `line`.
@@ -199,6 +206,15 @@ def do_range(self, args: str) -> str:
199206
args = (int(a) for a in args)
200207
return '\n'.join((str(i) for i in range(*args)))
201208

209+
@contextmanager
210+
def use_mode(self, mode: Mode):
211+
initial = self.mode
212+
try:
213+
self.mode = mode
214+
yield
215+
finally:
216+
self.mode = initial
217+
202218

203219
################################################################################
204220
# Run interface

src/mash/shell/grammer/literals.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
'not': 'NOT',
1010
'and': 'AND',
1111
'or': 'OR',
12+
'in': 'IN',
1213
'math': 'MATH',
1314
}
1415
token_values = {v: k for k, v in keywords.items()}

src/mash/shell/grammer/parser.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ def parse(text, init=True):
4141
('left', 'PIPE', 'BASH'),
4242
('left', 'MATH'),
4343
('left', 'INFIX_OPERATOR'),
44+
('left', 'IN'),
4445
('left', 'EQUALS'),
4546
('left', 'OR'),
4647
('left', 'AND'),
@@ -153,10 +154,6 @@ def p_expression_full_conditional(p):
153154
# a full_conditional can be included inside a pipe
154155
p[0] = p[1]
155156

156-
# def p_expression_set(p):
157-
# 'expression : set'
158-
# p[0] = p[1]
159-
160157
def p_expression(p):
161158
"""expression : join
162159
| logic_expression
@@ -185,11 +182,10 @@ def p_logic_binary(p):
185182
p[0] = LogicExpression(p[1], p[3], p[2])
186183

187184
def p_logic_expression_infix(p):
188-
'logic_expression : terms INFIX_OPERATOR logic_expression'
189-
p[0] = BinaryExpression(p[1], p[3], p[2])
190-
191-
def p_logic_expression_infix_equals(p):
192-
'logic_expression : logic_expression EQUALS logic_expression'
185+
"""logic_expression : terms INFIX_OPERATOR logic_expression
186+
| logic_expression EQUALS logic_expression
187+
| logic_expression IN logic_expression
188+
"""
193189
p[0] = BinaryExpression(p[1], p[3], p[2])
194190

195191
def p_logic_negation(p):
@@ -201,6 +197,10 @@ def p_logic(p):
201197
'logic_expression : terms'
202198
p[0] = p[1]
203199

200+
def p_logic_set_definition(p):
201+
'logic_expression : set'
202+
p[0] = p[1]
203+
204204
def p_full_conditional(p):
205205
'full_conditional : IF conjunction THEN conjunction ELSE conjunction'
206206
_, _if, cond, _then, true, _else, false = p
@@ -283,7 +283,6 @@ def p_term_value(p):
283283
"""term : value
284284
| method
285285
| scope
286-
| set
287286
"""
288287
p[0] = p[1]
289288

src/mash/shell/grammer/tokenizer.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
'ASSIGN', # =
1616
'ASSIGN_RIGHT', # ->
1717
'EQUALS', # ==
18-
'INFIX_OPERATOR', # == < >
18+
'INFIX_OPERATOR', # >= <= < >
1919

2020
'RPAREN', # (
2121
'LPAREN', # )

src/mash/shell/shell.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
from mash.shell.cmd2 import default_prompt, run
1616
from mash.shell.grammer.literals import DEFINE_FUNCTION
1717
from mash.shell.errors import ShellError, ShellPipeError, ShellSyntaxError
18-
from mash.shell.errors import ShellSyntaxError
1918
from mash.shell.function import ShellFunction as Function
2019
from mash.shell.internals.if_statement import Abort, handle_prev_then_else_statements
2120
from mash.shell.grammer.parser import parse

src/mash/shell/with_filesystem.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from mash.filesystem.discoverable import Discoverable
1111
from mash.filesystem.view import Path, ViewError
1212
from mash.io_util import log
13+
from mash.shell.cmd2 import Mode
1314
from mash.shell.shell import build, set_completions, set_functions
1415
from mash.shell.function import LAST_RESULTS, ShellFunction as Function
1516
from mash.util import find_fuzzy_matches, hamming, has_method, is_digit, partial_simple
@@ -208,12 +209,19 @@ def default_method(self, dirname: str):
208209
if candidates:
209210
error = hamming(dirname, str(candidates[0]))
210211
if error < 0.8:
211-
self.repository.cd(candidates[0])
212-
return
212+
if self.shell.mode == Mode.REPL:
213+
self.repository.cd(candidates[0])
214+
return
215+
elif self.shell.mode == Mode.COMPILE:
216+
return self.get(candidates[0])
213217

214218
if is_digit(dirname):
215-
self.repository.cd(dirname)
216-
return
219+
if self.shell.mode == Mode.REPL:
220+
self.repository.cd(dirname)
221+
return
222+
elif self.shell.mode == Mode.COMPILE:
223+
return self.get(dirname)
224+
217225

218226
debug('No matching directory found')
219227
return dirname

test/shell/test_parse.py

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,21 @@ def test_parse_infix():
143143
assert result.key.values == ['a', 'b']
144144
assert result.value == '2'
145145

146+
def test_parse_equals():
147+
result = parse_line('x == 2')
148+
assert isinstance(result, BinaryExpression)
149+
assert result.op == '=='
150+
151+
with raises(ShellSyntaxError):
152+
result = parse_line('==')
153+
154+
def test_parse_contains():
155+
result = parse_line('x in 1 2')
156+
assert isinstance(result, BinaryExpression)
157+
assert result.op == 'in'
158+
159+
with raises(ShellSyntaxError):
160+
result = parse_line('in')
146161

147162
def test_parse_numbers():
148163
numbers = ['-1', '-0.1', '.2', '-100.']
@@ -556,23 +571,22 @@ def test_parse_math():
556571

557572
def test_parse_set():
558573
result = parse_line('{ users }')
559-
assert isinstance(result, Terms)
560-
assert isinstance(result.values[0], SetDefinition)
574+
assert isinstance(result, SetDefinition)
561575
result = parse_line('{ users }')
562-
assert isinstance(result.values[0], SetDefinition)
576+
assert isinstance(result, SetDefinition)
563577
result = parse_line('{ users.id }')
564-
assert isinstance(result.values[0], SetDefinition)
578+
assert isinstance(result, SetDefinition)
565579

566580
def test_parse_set_with_filter():
567581
result = parse_line('{ users | .id > 100 }')
568-
assert isinstance(result.values[0], SetDefinition)
582+
assert isinstance(result, SetDefinition)
569583
result = parse_line('{ users | users.id > 100 }')
570-
assert isinstance(result.values[0], SetDefinition)
584+
assert isinstance(result, SetDefinition)
571585
result = parse_line('{ users groups | x.id == y.id }')
572-
assert isinstance(result.values[0], SetDefinition)
586+
assert isinstance(result, SetDefinition)
573587
result = parse_line('x <- { users }')
574588
assert isinstance(result, Assign)
575-
assert isinstance(result.rhs.values[0], SetDefinition)
589+
assert isinstance(result.rhs, SetDefinition)
576590

577591
def test_parse_set_with_nested_filter():
578592
# TODO

test/shell/test_shell_rest_client.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,8 @@ def test_rest_client_standard_set():
121121
shell, _ = init()
122122
shell = shell.shell
123123

124-
result = catch_output('{users} >>= show $.id', shell=shell)
124+
result = catch_output(r'{users}', shell=shell)
125+
result = catch_output(r'{users} >>= show $.id', shell=shell)
125126
# TODO add assertions
126127
# assert '1001' in result
127128

test/shell/test_shell_variables.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ def test_set_definition():
274274
run_command('a <- range 3', shell=shell)
275275
run_command('b <- range 3', shell=shell)
276276
run_command('c <- { $a }', shell=shell)
277-
assert shell.env['c'] == '0\n1\n2'
277+
assert shell.env['c'] == '0 1 2'
278278

279279
# TODO
280280
run_command('c <- { a b }', shell=shell)

0 commit comments

Comments
 (0)