Skip to content

Commit

Permalink
[rename] Move functions from osh/word_.py -> frontend/location.py
Browse files Browse the repository at this point in the history
Part of "codebase spring cleaning"

We want to get rid of all the span IDs
  • Loading branch information
Andy C committed May 13, 2023
1 parent 9196fdc commit 8934fef
Show file tree
Hide file tree
Showing 8 changed files with 234 additions and 237 deletions.
7 changes: 4 additions & 3 deletions core/completion.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
from core import ui
from core import util
from frontend import consts
from frontend import location
from frontend import reader
from mycpp import mylib
from mycpp.mylib import print_stderr, log
Expand Down Expand Up @@ -1030,7 +1031,7 @@ def Matches(self, comp):
debug_f.writeln("Didn't get a string from redir arg")
return

span_id = word_.LeftMostSpanForWord(arg_word)
span_id = location.OfWordLeft(arg_word)
span = arena.GetToken(span_id)

self.comp_ui_state.display_pos = span.col
Expand Down Expand Up @@ -1119,7 +1120,7 @@ def Matches(self, comp):
# echo $(gr and
# echo `gr

span_id = word_.LeftMostSpanForWord(trail.words[0])
span_id = location.OfWordLeft(trail.words[0])
span = arena.GetToken(span_id)
self.comp_ui_state.display_pos = span.col
self.debug_f.writeln('** DISPLAY_POS = %d' % self.comp_ui_state.display_pos)
Expand All @@ -1136,7 +1137,7 @@ def Matches(self, comp):
base_opts, user_spec = self.comp_lookup.GetFallback()

# Display since the beginning
span_id = word_.LeftMostSpanForWord(trail.words[-1])
span_id = location.OfWordLeft(trail.words[-1])
span = arena.GetToken(span_id)
self.comp_ui_state.display_pos = span.col
if mylib.PYTHON:
Expand Down
200 changes: 193 additions & 7 deletions frontend/location.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,23 @@
location.py - Library to get source location info from nodes.
This makes syntax errors nicer.
TODO: Move some of osh/word_ here.
"""
from __future__ import print_function

from _devbuild.gen.syntax_asdl import (
loc, loc_t, loc_e,
CompoundWord, SimpleVarSub, Token,
command, command_e, command_t,
word, word_e, word_t,
word_part, word_part_e, word_part_t,
CompoundWord, SimpleVarSub, Token,
ShArrayLiteral, SingleQuoted, DoubleQuoted, CommandSub, BracedVarSub,
BraceGroup,
arith_expr_e, arith_expr_t,
)
from _devbuild.gen.runtime_asdl import lvalue
from asdl import runtime
from mycpp.mylib import log
from mycpp.mylib import tagswitch
from osh import word_

from typing import cast, TYPE_CHECKING

Expand Down Expand Up @@ -55,14 +55,14 @@ def GetSpanId(loc_):
elif case(loc_e.WordPart):
loc_ = cast(loc.WordPart, UP_location)
if loc_.p:
return word_.LeftMostSpanForPart(loc_.p)
return OfWordPartLeft(loc_.p)
else:
return runtime.NO_SPID

elif case(loc_e.Word):
loc_ = cast(loc.Word, UP_location)
if loc_.w:
return word_.LeftMostSpanForWord(loc_.w)
return OfWordLeft(loc_.w)
else:
return runtime.NO_SPID

Expand All @@ -75,7 +75,6 @@ def GetSpanId(loc_):
def LocForCommand(node):
# type: (command_t) -> loc_t
"""
like word_.LeftMostSpanForWord
"""
UP_node = node # type: command_t
tag = node.tag()
Expand Down Expand Up @@ -144,3 +143,190 @@ def LocForArithExpr(node):
return loc.Word(w)

return loc.Missing


def OfWordPartLeft(part):
# type: (word_part_t) -> int
UP_part = part
with tagswitch(part) as case:
if case(word_part_e.ShArrayLiteral):
part = cast(ShArrayLiteral, UP_part)
return part.left.span_id # ( location

elif case(word_part_e.AssocArrayLiteral):
part = cast(word_part.AssocArrayLiteral, UP_part)
return part.left.span_id # ( location

elif case(word_part_e.Literal):
tok = cast(Token, UP_part)
return tok.span_id

elif case(word_part_e.EscapedLiteral):
part = cast(word_part.EscapedLiteral, UP_part)
return part.token.span_id

elif case(word_part_e.SingleQuoted):
part = cast(SingleQuoted, UP_part)
return part.left.span_id # single quote location

elif case(word_part_e.DoubleQuoted):
part = cast(DoubleQuoted, UP_part)
return part.left.span_id # double quote location

elif case(word_part_e.SimpleVarSub):
part = cast(SimpleVarSub, UP_part)
return part.left.span_id

elif case(word_part_e.BracedVarSub):
part = cast(BracedVarSub, UP_part)
return part.left.span_id

elif case(word_part_e.CommandSub):
part = cast(CommandSub, UP_part)
return part.left_token.span_id

elif case(word_part_e.TildeSub):
part = cast(word_part.TildeSub, UP_part)
return part.token.span_id

elif case(word_part_e.ArithSub):
part = cast(word_part.ArithSub, UP_part)
# begin, end
return part.spids[0]

elif case(word_part_e.ExtGlob):
part = cast(word_part.ExtGlob, UP_part)
# This is the smae as part.op.span_id, but we want to be consistent with
# left/right. Not sure I want to add a right token just for the spid.
return part.spids[0]
#return part.op.span_id # e.g. @( is the left-most token

elif case(word_part_e.BracedTuple):
return runtime.NO_SPID

elif case(word_part_e.Splice):
part = cast(word_part.Splice, UP_part)
return part.name.span_id

elif case(word_part_e.FuncCall):
part = cast(word_part.FuncCall, UP_part)
return part.name.span_id # @f(x) or $f(x)

elif case(word_part_e.ExprSub):
part = cast(word_part.ExprSub, UP_part)
return part.left.span_id # $[

else:
raise AssertionError(part.tag())


def _OfWordPartRight(part):
# type: (word_part_t) -> int
UP_part = part
with tagswitch(part) as case:
if case(word_part_e.ShArrayLiteral):
part = cast(ShArrayLiteral, UP_part)
# TODO: Return )
return OfWordLeft(part.words[0]) # Hm this is a=(1 2 3)

elif case(word_part_e.Literal):
# Just use the token
tok = cast(Token, UP_part)
return tok.span_id

elif case(word_part_e.EscapedLiteral):
part = cast(word_part.EscapedLiteral, UP_part)
return part.token.span_id

elif case(word_part_e.SingleQuoted):
part = cast(SingleQuoted, UP_part)
return part.right.span_id # right '

elif case(word_part_e.DoubleQuoted):
part = cast(DoubleQuoted, UP_part)
return part.right.span_id # right "

elif case(word_part_e.SimpleVarSub):
part = cast(SimpleVarSub, UP_part)
# left and right are the same for $myvar
return part.left.span_id

elif case(word_part_e.BracedVarSub):
part = cast(BracedVarSub, UP_part)
spid = part.right.span_id
assert spid != runtime.NO_SPID
return spid

elif case(word_part_e.CommandSub):
part = cast(CommandSub, UP_part)
return part.right.span_id

elif case(word_part_e.TildeSub):
return runtime.NO_SPID

elif case(word_part_e.ArithSub):
part = cast(word_part.ArithSub, UP_part)
return part.spids[1]

elif case(word_part_e.ExtGlob):
part = cast(word_part.ExtGlob, UP_part)
return part.spids[1]

# TODO: Do Splice and FuncCall need it?
else:
raise AssertionError(part.tag())


def OfWordLeft(w):
# type: (word_t) -> int
UP_w = w
with tagswitch(w) as case:
if case(word_e.Compound):
w = cast(CompoundWord, UP_w)
if len(w.parts):
return OfWordPartLeft(w.parts[0])
else:
# This is possible for empty brace sub alternative {a,b,}
return runtime.NO_SPID

elif case(word_e.Token):
tok = cast(Token, UP_w)
return tok.span_id

elif case(word_e.BracedTree):
w = cast(word.BracedTree, UP_w)
# This should always have one part?
return OfWordPartLeft(w.parts[0])

elif case(word_e.String):
w = cast(word.String, UP_w)
return w.span_id # See _StringWordEmitter in osh/builtin_bracket.py

else:
raise AssertionError(w.tag())

raise AssertionError('for -Wreturn-type in C++')


def OfWordRight(w):
# type: (word_t) -> int
"""Needed for here doc delimiters."""
UP_w = w
with tagswitch(w) as case:
if case(word_e.Compound):
w = cast(CompoundWord, UP_w)
if len(w.parts) == 0:
# TODO: Use Empty instead
raise AssertionError("Compound shouldn't be empty")
else:
end = w.parts[-1]
return _OfWordPartRight(end)

elif case(word_e.Token):
tok = cast(Token, UP_w)
return tok.span_id

else:
raise AssertionError(w.tag())

raise AssertionError('for -Wreturn-type in C++')
3 changes: 1 addition & 2 deletions osh/cmd_eval.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@
from oil_lang import objects
from osh import braces
from osh import sh_expr_eval
from osh import word_
from osh import word_eval
from mycpp import mylib
from mycpp.mylib import log, switch, tagswitch
Expand Down Expand Up @@ -668,7 +667,7 @@ def _Dispatch(self, node, cmd_st):
# Note that for '> $LINENO' the span_id is set in _EvalRedirect.
# TODO: Can we avoid setting this so many times? See issue #567.
if len(node.words):
span_id = word_.LeftMostSpanForWord(node.words[0])
span_id = location.OfWordLeft(node.words[0])
# Special case for __cat < file: leave it at the redirect.
if span_id != runtime.NO_SPID:
self.mem.SetCurrentSpanId(span_id)
Expand Down

0 comments on commit 8934fef

Please sign in to comment.