text: #!/usr/bin/env python
  """
  word_compile.py
  
  This is called the "compile" stage because it happens after parsing, but it
  doesn't depend on any values at runtime.
  """
  
  from core import util
  from osh import string_ops
  
  from core.meta import Id
  from core.meta import runtime_asdl
  
  var_flags_e = runtime_asdl.var_flags_e
  
  
  _ONE_CHAR = {
      '0': '\0',
      'a': '\a',
      'b': '\b',
      'e': '\x1b',
      'E': '\x1b',
      'f': '\f',
      'n': '\n',
      'r': '\r',
      't': '\t',
      'v': '\v',
      '\\': '\\',
      "'": "'",  # for $'' only, not echo -e
      '"': '"',  # not sure why this is escaped within $''
  }
  
  
  # TODO: Strict mode syntax errors:
  #
  # \x is a syntax error -- needs two digits (It's like this in C)
  # \0777 is a syntax error -- we shouldn't do modulus
  # \d could be a syntax error -- it is better written as \\d
  
  def EvalCStringToken(id_, value):
    """
    This function is shared between echo -e and $''.
  
    $'' could use it at compile time, much like brace expansion in braces.py.
    """
    if id_ == Id.Char_Literals:
      return value
  
    elif id_ == Id.Char_BadBackslash:
      if 1:  # TODO: error in strict mode
        # Either \A or trailing \ (A is not a valid backslash escape)
        util.warn('Invalid backslash escape')
      return value
  
    elif id_ == Id.Char_OneChar:
      c = value[1]
      return _ONE_CHAR[c]
  
    elif id_ == Id.Char_Stop:  # \c returns a special sentinel
      return None
  
    elif id_ in (Id.Char_Octal3, Id.Char_Octal4):
      if id_ == Id.Char_Octal3:  # $'\377'
        s = value[1:]
      else:                      # echo -e '\0377'
        s = value[2:]
  
      i = int(s, 8)
      if i >= 256:
        i = i % 256
        # NOTE: This is for strict mode
        #raise AssertionError('Out of range')
      return chr(i)
  
    elif id_ == Id.Char_Hex:
      s = value[2:]
      i = int(s, 16)
      return chr(i)
  
    elif id_ in (Id.Char_Unicode4, Id.Char_Unicode8):
      s = value[2:]
      i = int(s, 16)
      #util.log('i = %d', i)
      return string_ops.Utf8Encode(i)
  
    else:
      raise AssertionError
  
  
  #
  # Assignment
  #
  
  def ParseAssignFlags(flag_args):
    """
    Args:
      flag_args looks like ['-r', '-x'] or ['-rx'], etc.
  
    Returns:
      A list of var_flags_e
  
    NOTE: Any errors should be caught at PARSE TIME, not compile time.
    """
    flags = []
    for arg in flag_args:
      assert arg[0] == '-', arg
      for char in arg[1:]:
        if char == 'x':
          flags.append(var_flags_e.Exported)
        elif char == 'r':
          flags.append(var_flags_e.ReadOnly)
        elif char == 'A':
          flags.append(var_flags_e.AssocArray)
        elif char == 'g':  # useful for 'declare -Ag'
          flags.append(var_flags_e.Global)
        else:
          # TODO: Throw an error?
          pass
    return flags
  
  