~andyc/oil

9f2c1ff5eddc30e352e2a80a6185095e1277be0a — Andy Chu 2 months ago 046dc53
[mycpp] Examples compile and run with GC=1 again

- Because we use NewList when GC=1.
- Also disabled global dicts and non-empty dict literals for now.

The osh_eval.cc build still uses the old runtime.  We don't have
functions like list_contains() etc.
M build/mycpp.sh => build/mycpp.sh +10 -2
@@ 218,10 218,16 @@ compile-slice() {

  mkdir -p _bin

  # Not ready for this yet.  Need list_contains() etc.
  if test -n "${GC:-}"; then
    local -a runtime=(mycpp/{gc_heap,mylib2,my_runtime}.cc)
  else
    local -a runtime=(mycpp/{gc_heap,mylib}.cc)
  fi

  # Note: can't use globs here because we have _test.cc
  time compile _bin/$name$suffix _build/cpp/${name}.cc \
    mycpp/gc_heap.cc \
    mycpp/mylib.cc \
    "${runtime[@]}" \
    cpp/core_pyos.cc \
    cpp/core_pyutil.cc \
    cpp/frontend_flag_spec.cc \


@@ 321,6 327,8 @@ osh-eval() {

  #if false; then
  if true; then
    #export GC=1  # read by mycpp_main

    # relies on splitting
    mycpp \
      --header-out $h \

M mycpp/cppgen_pass.py => mycpp/cppgen_pass.py +11 -1
@@ 3,6 3,7 @@ cppgen.py - AST pass to that prints C++ code
"""
import io
import json  # for "C escaping"
import os
import sys

from typing import overload, Union, Optional, Any, Dict


@@ 280,6 281,9 @@ class Generate(ExpressionVisitor[T], StatementVisitor[None]):

      self.imported_names = set()  # For module::Foo() vs. self.foo

      # for NewList vs. Alloc<List>, etc.
      self.gc = bool(os.getenv('GC'))

    def log(self, msg, *args):
      ind_str = self.indent * '  '
      log(ind_str + msg, *args)


@@ 1000,7 1004,13 @@ class Generate(ExpressionVisitor[T], StatementVisitor[None]):
        else:
            # Lists are MUTABLE so we can't pull them to the top level.
            # C++ wart: Use initializer_list.  
            self.write('Alloc<%s>(std::initializer_list<%s>' % (c_type, item_c_type))
            if self.gc:
              self.write('NewList<%s>(std::initializer_list<%s>' %
                  (item_c_type, item_c_type))
            else:
              self.write('Alloc<%s>(std::initializer_list<%s>' %
                  (c_type, item_c_type))

            self._WriteListElements(o)
            self.write(')')


M mycpp/examples/containers.py => mycpp/examples/containers.py +5 -2
@@ 14,7 14,7 @@ gstr = 'foo'  # type: str
glist_int = [1, 2]  # type: List[int]
glist_str = ['spam', 'eggs']  # type: List[str]

gdict = {'a': 42, 'b': 43}  # type: Dict[str, int]
#gdict = {'a': 42, 'b': 43}  # type: Dict[str, int]


def ListDemo():


@@ 27,6 27,9 @@ def ListDemo():
  intlist.append(2)
  intlist.append(3)

  local_list = [1, 2]
  log("local_list = %d", len(local_list))

  # turned into intlist->set(1, 42)
  intlist[1] = 42



@@ 111,7 114,7 @@ def DictDemo():
  # type: () -> None

  # regression
  nonempty = {'a': 'b'}  # type: Dict[str, str]
  #nonempty = {'a': 'b'}  # type: Dict[str, str]

  d = {}  # type: Dict[str, int]
  d['foo'] = 42

M mycpp/examples/loops.py => mycpp/examples/loops.py +1 -1
@@ 71,7 71,7 @@ def TestDict():

CATS = ['big', 'small', 'hairless']

EMPTY_DICT = {}  # type: Dict[int, int]
#EMPTY_DICT = {}  # type: Dict[int, int]

def run_tests():
  # type: () -> None

M mycpp/gc_heap.h => mycpp/gc_heap.h +3 -17
@@ 760,26 760,12 @@ class List : public gc_heap::Obj {
    assert(slab_ == nullptr);
  }

  // Literal ['foo', 'bar']
  List(std::initializer_list<T> init) : List() {
    auto self = this;
    StackRoots _roots({&self});

    int n = init.size();
    self->reserve(n);

    int i = 0;
    for (auto item : init) {
      self->set(i, item);
      ++i;
    }
    self->len_ = n;
  }

  // TODO: Move to NewList() because constructors can't move itself like
  // self->set().
  // list_repeat ['foo'] * 3
  List(T item, int times) : List() {
    auto self = this;
    StackRoots _roots({&self});  // TODO: What about item!  Could be moved!
    StackRoots _roots({&self});

    self->reserve(times);
    self->len_ = times;

M mycpp/my_runtime.cc => mycpp/my_runtime.cc +1 -1
@@ 405,7 405,7 @@ List<Str*>* Str::split(Str* sep) {
  int length = len(this);
  if (length == 0) {
    // weird case consistent with Python: ''.split(':') == ['']
    return Alloc<List<Str*>>(std::initializer_list<Str*>{kEmptyString});
    return NewList<Str*>(std::initializer_list<Str*>{kEmptyString});
  }

  auto result = Alloc<List<Str*>>();

M mycpp/mycpp_main.py => mycpp/mycpp_main.py +2 -0
@@ 247,6 247,8 @@ using gc_heap::StackRoots;
#include "mylib2.h"

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

  if to_header:

M mycpp/setup.sh => mycpp/setup.sh +3 -3
@@ 52,7 52,7 @@ build-examples() {
  ### Build all mycpp/examples

  # TODO: examples/parse expr.asdl needs NewStr instead of new Str()
  # export GC=1
  export GC=1

  export MYPY_REPO



@@ 67,7 67,7 @@ test-examples() {
  ### Test all mycpp/examples

  # This works!
  # export GC=1
  export GC=1

  cd $THIS_DIR
  ./run.sh test-all


@@ 77,7 77,7 @@ benchmark-examples() {
  ### Benchmark all mycpp/examples

  # 'files' has a different result?
  # export GC=1
  export GC=1

  cd $THIS_DIR
  ./run.sh benchmark-all