Exemple #1
0
def main(argv):
  try:
    action = argv[1]
  except IndexError:
    raise RuntimeError('Action required')

  if 0:
    for spec_name in sorted(flag_spec.FLAG_SPEC_AND_MORE):
      log('%s', spec_name)

  # Both kinds of specs have 'fields' attributes
  specs = {}
  specs.update(flag_spec.FLAG_SPEC)
  specs.update(flag_spec.FLAG_SPEC_AND_MORE)

  for spec_name in sorted(specs):
    spec = specs[spec_name]
    #spec.spec.PrettyPrint(f=sys.stderr)
    #log('spec.arity1 %s', spec.spec.arity1)
    #log('%s', spec_name)

    #print(dir(spec))
    #print(spec.arity0)
    #print(spec.arity1)
    #print(spec.options)
    # Every flag has a default
    #log('%s', spec.fields)

  if action == 'cpp':
    prefix = argv[2]

    with open(prefix + '.h', 'w') as header_f:
      with open(prefix + '.cc', 'w') as cc_f:
        Cpp(specs, header_f, cc_f)

  elif action == 'mypy':
    print("""
from frontend.args import _Attributes
from _devbuild.gen.runtime_asdl import (
   value, value_e, value_t, value__Bool, value__Int, value__Float, value__Str,
)
from typing import cast, Dict, Optional
""")
    for spec_name in sorted(specs):
      spec = specs[spec_name]

      #log('%s spec.fields %s', spec_name, spec.fields)
      if not spec.fields:
        continue  # skip empty specs, e.g. eval

      print("""
class %s(object):
  def __init__(self, attrs):
    # type: (Dict[str, value_t]) -> None
""" % spec_name)

      i = 0
      for field_name in sorted(spec.fields):
        typ = spec.fields[field_name]
        field_name = field_name.replace('-', '_')

        with switch(typ) as case:
          if case(flag_type_e.Bool):
            print('    self.%s = cast(value__Bool, attrs[%r]).b  # type: bool' % (
              field_name, field_name))

          elif case(flag_type_e.Str):
            tmp = 'val%d' % i
            print('    %s = attrs[%r]' % (tmp, field_name))
            print('    self.%s = None if %s.tag_() == value_e.Undef else cast(value__Str, %s).s  # type: Optional[str]' % (field_name, tmp, tmp))

          elif case(flag_type_e.Int):
            tmp = 'val%d' % i
            print('    %s = attrs[%r]' % (tmp, field_name))
            print('    self.%s = -1 if %s.tag_() == value_e.Undef else cast(value__Int, %s).i  # type: int' % (field_name, tmp, tmp))

          elif case(flag_type_e.Float):
            tmp = 'val%d' % i
            print('    %s = attrs[%r]' % (tmp, field_name))
            print('    self.%s = -1.0 if %s.tag_() == value_e.Undef else cast(value__Float, %s).f  # type: float' % (field_name, tmp, tmp))
          else:
            raise AssertionError(typ)

        i += 1

      print()

  else:
    raise RuntimeError('Invalid action %r' % action)
Exemple #2
0
    def EvalB(self, node):
        # type: (bool_expr_t) -> bool

        UP_node = node
        with tagswitch(node) as case:
            if case(bool_expr_e.WordTest):
                node = cast(bool_expr__WordTest, UP_node)
                s = self._EvalCompoundWord(node.w)
                return bool(s)

            elif case(bool_expr_e.LogicalNot):
                node = cast(bool_expr__LogicalNot, UP_node)
                b = self.EvalB(node.child)
                return not b

            elif case(bool_expr_e.LogicalAnd):
                node = cast(bool_expr__LogicalAnd, UP_node)
                # Short-circuit evaluation
                if self.EvalB(node.left):
                    return self.EvalB(node.right)
                else:
                    return False

            elif case(bool_expr_e.LogicalOr):
                node = cast(bool_expr__LogicalOr, UP_node)
                if self.EvalB(node.left):
                    return True
                else:
                    return self.EvalB(node.right)

            elif case(bool_expr_e.Unary):
                node = cast(bool_expr__Unary, UP_node)
                op_id = node.op_id
                s = self._EvalCompoundWord(node.child)

                # Now dispatch on arg type
                arg_type = consts.BoolArgType(
                    op_id)  # could be static in the LST?

                if arg_type == bool_arg_type_e.Path:
                    return bool_stat.DoUnaryOp(op_id, s)

                if arg_type == bool_arg_type_e.Str:
                    if op_id == Id.BoolUnary_z:
                        return not bool(s)
                    if op_id == Id.BoolUnary_n:
                        return bool(s)

                    raise AssertionError(op_id)  # should never happen

                if arg_type == bool_arg_type_e.Other:
                    if op_id == Id.BoolUnary_t:
                        return bool_stat.isatty(s, node.child)

                    # See whether 'set -o' options have been set
                    if op_id == Id.BoolUnary_o:
                        index = match.MatchOption(s)
                        if index == 0:
                            return False
                        else:
                            return self.exec_opts.opt0_array[index]

                    if op_id == Id.BoolUnary_v:
                        val = self.mem.GetVar(s)
                        return val.tag_() != value_e.Undef

                    e_die("%s isn't implemented",
                          ui.PrettyId(op_id))  # implicit location

                raise AssertionError(arg_type)

            elif case(bool_expr_e.Binary):
                node = cast(bool_expr__Binary, UP_node)

                op_id = node.op_id
                # Whether to glob escape
                with switch(op_id) as case2:
                    if case2(Id.BoolBinary_GlobEqual, Id.BoolBinary_GlobDEqual,
                             Id.BoolBinary_GlobNEqual):
                        quote_kind = quote_e.FnMatch
                    elif case2(Id.BoolBinary_EqualTilde):
                        quote_kind = quote_e.ERE
                    else:
                        quote_kind = quote_e.Default

                s1 = self._EvalCompoundWord(node.left)
                s2 = self._EvalCompoundWord(node.right, quote_kind=quote_kind)

                # Now dispatch on arg type
                arg_type = consts.BoolArgType(op_id)

                if arg_type == bool_arg_type_e.Path:
                    return bool_stat.DoBinaryOp(op_id, s1, s2)

                if arg_type == bool_arg_type_e.Int:
                    # NOTE: We assume they are constants like [[ 3 -eq 3 ]].
                    # Bash also allows [[ 1+2 -eq 3 ]].
                    i1 = self._StringToIntegerOrError(s1, blame_word=node.left)
                    i2 = self._StringToIntegerOrError(s2,
                                                      blame_word=node.right)

                    if op_id == Id.BoolBinary_eq:
                        return i1 == i2
                    if op_id == Id.BoolBinary_ne:
                        return i1 != i2
                    if op_id == Id.BoolBinary_gt:
                        return i1 > i2
                    if op_id == Id.BoolBinary_ge:
                        return i1 >= i2
                    if op_id == Id.BoolBinary_lt:
                        return i1 < i2
                    if op_id == Id.BoolBinary_le:
                        return i1 <= i2

                    raise AssertionError(op_id)  # should never happen

                if arg_type == bool_arg_type_e.Str:

                    if op_id in (Id.BoolBinary_GlobEqual,
                                 Id.BoolBinary_GlobDEqual):
                        #log('Matching %s against pattern %s', s1, s2)
                        return libc.fnmatch(s2, s1, self.exec_opts.extglob())

                    if op_id == Id.BoolBinary_GlobNEqual:
                        return not libc.fnmatch(s2, s1,
                                                self.exec_opts.extglob())

                    if op_id in (Id.BoolBinary_Equal, Id.BoolBinary_DEqual):
                        return s1 == s2

                    if op_id == Id.BoolBinary_NEqual:
                        return s1 != s2

                    if op_id == Id.BoolBinary_EqualTilde:
                        # TODO: This should go to --debug-file
                        #log('Matching %r against regex %r', s1, s2)
                        try:
                            matches = libc.regex_match(s2, s1)
                        except RuntimeError as e:
                            # Status 2 indicates a regex parse error.  This is fatal in OSH but
                            # not in bash, which treats [[ like a command with an exit code.
                            msg = e.message  # type: str
                            e_die("Invalid regex %r: %s",
                                  s2,
                                  msg,
                                  word=node.right,
                                  status=2)

                        if matches is None:
                            return False

                        self._SetRegexMatches(matches)
                        return True

                    if op_id == Id.Op_Less:
                        return str_cmp(s1, s2) < 0

                    if op_id == Id.Op_Great:
                        return str_cmp(s1, s2) > 0

                    raise AssertionError(op_id)  # should never happen

        raise AssertionError(node.tag_())
Exemple #3
0
def Cpp(specs, header_f, cc_f):
  counter = itertools.count()

  header_f.write("""\
// arg_types.h is generated by frontend/flag_gen.py

#ifndef ARG_TYPES_H
#define ARG_TYPES_H

#include "frontend_flag_spec.h"  // for FlagSpec_c
#include "mylib.h"

namespace value_e = runtime_asdl::value_e;
using runtime_asdl::value__Bool;
using runtime_asdl::value__Int;
using runtime_asdl::value__Float;
using runtime_asdl::value__Str;

namespace arg_types {
""")
  for spec_name in sorted(specs):
    spec = specs[spec_name]

    if not spec.fields:
      continue  # skip empty 'eval' spec

    header_f.write("""
class %s {
 public:
  %s(Dict<Str*, runtime_asdl::value_t*>* attrs) :
""" % (spec_name, spec_name))

    init_vals = []
    field_decls = []
    for field_name in sorted(spec.fields):
      typ = spec.fields[field_name]
      field_name = field_name.replace('-', '_')

      with switch(typ) as case:
        if case(flag_type_e.Bool):
          init_vals.append('static_cast<value__Bool*>(attrs->index(new Str("%s")))->b' % field_name)
          field_decls.append('bool %s;' % field_name)

        elif case(flag_type_e.Str):
          # TODO: This code is ugly and inefficient!  Generate something
          # better.  At least get rid of 'new' everywhere?
          init_vals.append('''\
attrs->index(new Str("%s"))->tag_() == value_e::Undef
      ? nullptr
      : static_cast<value__Str*>(attrs->index(new Str("%s")))->s''' % (
              field_name, field_name))

          field_decls.append('Str* %s;' % field_name)

        elif case(flag_type_e.Int):
          init_vals.append('''\
attrs->index(new Str("%s"))->tag_() == value_e::Undef
      ? -1
      : static_cast<value__Int*>(attrs->index(new Str("%s")))->i''' % (field_name, field_name))
          field_decls.append('int %s;' % field_name)

        elif case(flag_type_e.Float):
          init_vals.append('''\
attrs->index(new Str("%s"))->tag_() == value_e::Undef
      ? -1
      : static_cast<value__Float*>(attrs->index(new Str("%s")))->f''' % (field_name, field_name))
          field_decls.append('float %s;' % field_name)

        else:
          raise AssertionError(typ)

    for i, field_name in enumerate(sorted(spec.fields)):
      field_name = field_name.replace('-', '_')
      if i != 0:
        header_f.write(',\n')
      header_f.write('    %s(%s)' % (field_name, init_vals[i]))
    header_f.write(' {\n')
    header_f.write('  }\n')

    for decl in field_decls:
      header_f.write('  %s\n' % decl)

    header_f.write("""\
};
""")

  header_f.write("""
extern FlagSpec_c kFlagSpecs[];
extern FlagSpecAndMore_c kFlagSpecsAndMore[];

}  // namespace arg_types

#endif  // ARG_TYPES_H

""")

  cc_f.write("""\
// arg_types.cc is generated by frontend/flag_gen.py

#include "arg_types.h"
using runtime_asdl::flag_type_e;

namespace arg_types {

""")

  var_names = []
  for i, spec_name in enumerate(sorted(flag_spec.FLAG_SPEC)):
    spec = specs[spec_name]
    arity0_name = None
    arity1_name = None
    actions_long_name = None
    plus_name = None
    defaults_name = None

    if spec.arity0:
      arity0_name = 'arity0_%d' % i
      _WriteStrArray(cc_f, arity0_name, spec.arity0)

    if spec.arity1:
      arity1_name = 'arity1_%d' % i
      _WriteActions(cc_f, arity1_name, spec.arity1, counter)

    if spec.actions_long:
      actions_long_name = 'actions_long_%d' % i
      _WriteActions(cc_f, actions_long_name, spec.actions_long, counter)

    if spec.plus_flags:
      plus_name = 'plus_%d' % i
      _WriteStrArray(cc_f, plus_name, spec.plus_flags)

    if spec.defaults:
      defaults_name = 'defaults_%d' % i
      _WriteDefaults(cc_f, defaults_name, spec.defaults)

    var_names.append(
        (arity0_name, arity1_name, actions_long_name, plus_name,
         defaults_name)
    )

    cc_f.write('\n')

  cc_f.write('FlagSpec_c kFlagSpecs[] = {\n')

  # Now print a table
  for i, spec_name in enumerate(sorted(flag_spec.FLAG_SPEC)):
    spec = specs[spec_name]
    names = var_names[i]
    cc_f.write('    { "%s", %s, %s, %s, %s, %s },\n' % (
      spec_name,
      names[0] or 'nullptr', 
      names[1] or 'nullptr', 
      names[2] or 'nullptr', 
      names[3] or 'nullptr', 
      names[4] or 'nullptr', 
    ))

  cc_f.write("""\
    {},
};

""")

  var_names = []
  for i, spec_name in enumerate(sorted(flag_spec.FLAG_SPEC_AND_MORE)):
    spec = specs[spec_name]
    actions_short_name = None
    actions_long_name = None
    plus_name = None
    defaults_name = None

    if spec.actions_short:
      actions_short_name = 'short_%d' % i
      _WriteActions(cc_f, actions_short_name, spec.actions_short, counter)

    #if spec.actions_long:
    if spec.actions_long:
      actions_long_name = 'long_%d' % i
      _WriteActions(cc_f, actions_long_name, spec.actions_long, counter)

    if spec.plus_flags:
      plus_name = 'plus_%d' % i
      _WriteStrArray(cc_f, plus_name, spec.plus_flags)

    if spec.defaults:
      defaults_name = 'defaults_%d' % i
      _WriteDefaults(cc_f, defaults_name, spec.defaults)

    var_names.append((actions_short_name, actions_long_name, plus_name, defaults_name))

  cc_f.write('FlagSpecAndMore_c kFlagSpecsAndMore[] = {\n')
  for i, spec_name in enumerate(sorted(flag_spec.FLAG_SPEC_AND_MORE)):
    names = var_names[i]
    cc_f.write('    { "%s", %s, %s, %s, %s },\n' % (
      spec_name,
      names[0] or 'nullptr', 
      names[1] or 'nullptr', 
      names[2] or 'nullptr', 
      names[3] or 'nullptr', 
    ))

  cc_f.write("""\
    {},
};
""")

  cc_f.write("""\
}  // namespace arg_types
""")