Esempio n. 1
0
def main(argv):
  # TODO: Put these in the shell script
  mypy_options = [
     '--py2', '--strict', '--no-implicit-optional', '--no-strict-optional',
     # for consistency?
     '--follow-imports=silent',
     #'--verbose',
  ]

  o = Options()
  opts, argv = o.parse_args(argv)
     
  paths = argv[1:]  # e.g. asdl/typed_arith_parse.py

  if 0:
    print(opts)
    print(paths)
    return

  # e.g. asdl/typed_arith_parse.py -> 'typed_arith_parse'
  mod_names = [os.path.basename(p) for p in paths]
  mod_names = [os.path.splitext(name)[0] for name in mod_names]

  # Ditto
  to_header = opts.to_header
  #if to_header:
  if 0:
    to_header = [os.path.basename(p) for p in to_header]
    to_header = [os.path.splitext(name)[0] for name in to_header]

  #log('to_header %s', to_header)

  sources, options = get_mypy_config(paths, mypy_options)
  if 0:
    for source in sources:
      log('source %s', source)
  #log('options %s', options)

  #result = emitmodule.parse_and_typecheck(sources, options)
  import time
  start_time = time.time()
  result = mypy_build(sources=sources, options=options)
  #log('elapsed 1: %f', time.time() - start_time)

  if result.errors:
    log('')
    log('-'* 80)
    for e in result.errors:
      log(e)
    log('-'* 80)
    log('')

  # Important functions in mypyc/build.py:
  #
  # generate_c (251 lines)
  #   parse_and_typecheck
  #   compile_modules_to_c

  # mypyc/emitmodule.py (487 lines)
  # def compile_modules_to_c(result: BuildResult, module_names: List[str],
  # class ModuleGenerator:
  #   # This generates a whole bunch of textual code!

  # literals, modules, errors = genops.build_ir(file_nodes, result.graph,
  # result.types)

  # TODO: Debug what comes out of here.
  #build.dump_graph(result.graph)
  #return

  # no-op
  for name in result.graph:
    state = result.graph[name]

  # GLOBAL Constant pass over all modules.  We want to collect duplicate
  # strings together.  And have globally unique IDs str0, str1, ... strN.
  const_lookup = {}
  const_code = []
  pass1 = const_pass.Collect(result.types, const_lookup, const_code)

  to_compile = list(ModulesToCompile(result, mod_names))

  # HACK: Why do I get oil.asdl.tdop in addition to asdl.tdop?
  names = set(name for name, _ in to_compile)

  filtered = []
  seen = set()
  for name, module in to_compile:
    if name.startswith('oil.'):
      name = name[4:]

    if name not in seen:  # remove dupe
      filtered.append((name, module))
      seen.add(name)

  to_compile = filtered

  import pickle
  if 1:
    for name, module in to_compile:
      log('to_compile %s', name)

      # can't pickle but now I see deserialize() nodes and stuff
      #s = pickle.dumps(module)
      #log('%d pickle', len(s))

  # Print the tree for debugging
  if 0:
    for name, module in to_compile:
      builder = debug_pass.Print(result.types)
      builder.visit_mypy_file(module)
    return

  f = sys.stdout

  gc = bool(os.getenv('GC'))
  header_name = 'gc_heap' if gc else 'mylib'
  #header_name = 'mylib'

  # TODO: Add --cc-out?  But there is a preamble and postamble.
  f.write("""\
// BEGIN mycpp output

#include "%s.h"

using gc_heap::Alloc;
using gc_heap::kZeroMask;
using gc_heap::StackRoots;
""" % header_name)

  if gc:
    f.write("""\
#include "my_runtime.h"
#include "mylib2.h"

using gc_heap::NewStr;
using gc_heap::NewList;
using gc_heap::NewDict;
""")

  if to_header:
    f.write('#include "%s"\n' % os.path.basename(opts.header_out))
    f.write('\n')

  # Collect constants and then emit code.
  for name, module in to_compile:
    pass1.visit_mypy_file(module)

  # Instead of top-level code, should we generate a function and call it from
  # main?
  for line in const_code:
    f.write('%s\n' % line)
  f.write('\n')

  # Note: doesn't take into account module names!
  virtual = pass_state.Virtual()

  if opts.header_out:
    header_f = open(opts.header_out, 'w')  # Not closed
    guard = 'RUNTIME_H'
    header_f.write("""\
// %s: translated from Python by mycpp

#ifndef %s
#define %s

#include "%s.h"
""" % (os.path.basename(opts.header_out), guard, guard, header_name))

  log('\tFORWARD DECL')

  # Forward declarations first.
  # class Foo; class Bar;
  for name, module in to_compile:
    log('forward decl name %s', name)
    if name in to_header:
      out_f = header_f
    else:
      out_f = f
    p2 = cppgen_pass.Generate(result.types, const_lookup, out_f,
                              virtual=virtual, forward_decl=True)

    p2.visit_mypy_file(module)

  # After seeing class and method names in the first pass, figure out which
  # ones are virtual.  We use this info in the second pass.
  virtual.Calculate()
  #log('V %s', virtual.virtuals)

  local_vars = {}  # FuncDef node -> (name, c_type) list

  # Node -> fmt_name, plus a hack for the counter
  # TODO: This could be a class with 2 members
  fmt_ids = {'_counter': 0}

  log('\tDECL')

  # First generate ALL C++ declarations / "headers".
  # class Foo { void method(); }; class Bar { void method(); };
  for name, module in to_compile:
    log('decl name %s', name)
    if name in to_header:
      out_f = header_f
    else:
      out_f = f
    p3 = cppgen_pass.Generate(result.types, const_lookup, out_f,
                              local_vars=local_vars, fmt_ids=fmt_ids,
                              virtual=virtual, decl=True)

    p3.visit_mypy_file(module)

  if opts.header_out:
    header_f.write("""\
#endif  // %s
""" % guard)

  log('\tDEFINITION')

  # Now the definitions / implementations.
  # void Foo:method() { ... }
  # void Bar:method() { ... }
  for name, module in to_compile:
    p4 = cppgen_pass.Generate(result.types, const_lookup, f,
                              local_vars=local_vars, fmt_ids=fmt_ids)
    p4.visit_mypy_file(module)
Esempio n. 2
0
def main(argv):
    # TODO: Put these in the shell script
    mypy_options = [
        '--py2',
        '--strict',
        '--no-implicit-optional',
        '--no-strict-optional',
        # for consistency?
        '--follow-imports=silent',
        #'--verbose',
    ]

    o = Options()
    opts, argv = o.parse_args(argv)
    #print(opts)

    paths = argv[1:]  # e.g. asdl/typed_arith_parse.py

    # convert to 'typed_arith_parse'
    mod_names = [os.path.basename(p) for p in paths]
    mod_names = [os.path.splitext(name)[0] for name in mod_names]

    sources, options = get_mypy_config(paths, mypy_options)
    for source in sources:
        log('source %s', source)
    #log('options %s', options)

    #result = emitmodule.parse_and_typecheck(sources, options)
    import time
    start_time = time.time()
    result = mypy_build(sources=sources, options=options)
    log('elapsed 1: %f', time.time() - start_time)

    if result.errors:
        log('')
        log('-' * 80)
        for e in result.errors:
            log(e)
        log('-' * 80)
        log('')

    # Important functions in mypyc/build.py:
    #
    # generate_c (251 lines)
    #   parse_and_typecheck
    #   compile_modules_to_c

    # mypyc/emitmodule.py (487 lines)
    # def compile_modules_to_c(result: BuildResult, module_names: List[str],
    # class ModuleGenerator:
    #   # This generates a whole bunch of textual code!

    # literals, modules, errors = genops.build_ir(file_nodes, result.graph,
    # result.types)

    # TODO: Debug what comes out of here.
    #build.dump_graph(result.graph)
    #return

    # no-op
    for name in result.graph:
        state = result.graph[name]

    # GLOBAL Constant pass over all modules.  We want to collect duplicate
    # strings together.  And have globally unique IDs str0, str1, ... strN.
    const_lookup = {}
    const_code = []
    pass1 = const_pass.Collect(result.types, const_lookup, const_code)

    to_compile = list(ModulesToCompile(result, mod_names))

    # HACK: Why do I get oil.asdl.tdop in addition to asdl.tdop?
    names = set(name for name, _ in to_compile)
    filtered = []
    for name, module in to_compile:
        if name.startswith('oil.') and name[4:] in names:
            continue
        filtered.append((name, module))
    to_compile = filtered

    import pickle
    if 1:
        for name, module in to_compile:
            log('to_compile %s', name)

            # can't pickle but now I see deserialize() nodes and stuff
            #s = pickle.dumps(module)
            #log('%d pickle', len(s))

    # Print the tree for debugging
    if 0:
        for name, module in to_compile:
            builder = debug_pass.Print(result.types)
            builder.visit_mypy_file(module)
        return

    for name, module in to_compile:
        pass1.visit_mypy_file(module)

    # Collect constants and then emit code.
    f = sys.stdout

    # Instead of top-level code, should we generate a function and call it from
    # main?
    for line in const_code:
        f.write('%s\n' % line)
    f.write('\n')

    # Note: doesn't take into account module names!
    virtual = pass_state.Virtual()

    # Forward declarations first.
    # class Foo; class Bar;
    for name, module in to_compile:
        p2 = cppgen_pass.Generate(result.types,
                                  const_lookup,
                                  f,
                                  virtual=virtual,
                                  forward_decl=True)

        p2.visit_mypy_file(module)

    # After seeing class and method names in the first pass, figure out which
    # ones are virtual.  We use this info in the second pass.
    virtual.Calculate()
    #log('V %s', virtual.virtuals)

    local_vars = {}  # FuncDef node -> (name, c_type) list

    # Node -> fmt_name, plus a hack for the counter
    # TODO: This could be a class with 2 members
    fmt_ids = {'_counter': 0}

    # First generate ALL C++ declarations / "headers".
    # class Foo { void method(); }; class Bar { void method(); };
    for name, module in to_compile:
        p3 = cppgen_pass.Generate(result.types,
                                  const_lookup,
                                  f,
                                  local_vars=local_vars,
                                  fmt_ids=fmt_ids,
                                  virtual=virtual,
                                  decl=True)

        p3.visit_mypy_file(module)

    # Now the definitions / implementations.
    # void Foo:method() { ... }
    # void Bar:method() { ... }
    for name, module in to_compile:
        p4 = cppgen_pass.Generate(result.types,
                                  const_lookup,
                                  f,
                                  local_vars=local_vars,
                                  fmt_ids=fmt_ids)
        p4.visit_mypy_file(module)