Implement default string arguments.
authorDavid Anderson <dvander@alliedmods.net>
Mon Aug 06 02:03:36 2012 -0700 (2012-08-06)
changeset 1690456a16c2a63
parent 168 4d0fff61d65e
child 170 5e4570966ece
Implement default string arguments.
src/Array.cpp
src/Array.h
src/Box.cpp
src/Box.h
src/BytecodeCompiler.cpp
src/SemanticAnalysis.cpp
     1.1 --- a/src/Array.cpp	Sun Aug 05 21:24:41 2012 -0700
     1.2 +++ b/src/Array.cpp	Mon Aug 06 02:03:36 2012 -0700
     1.3 @@ -37,6 +37,27 @@
     1.4      return map;
     1.5  }
     1.6  
     1.7 +ArrayMap *
     1.8 +ArrayMap::Attach(Zone *zone, Handle<Type> type)
     1.9 +{
    1.10 +    if (type->newMap())
    1.11 +        return ArrayMap::cast(type->newMap());
    1.12 +
    1.13 +    Local<ArrayMap> map(zone, ArrayMap::New(zone, type));
    1.14 +    if (!map)
    1.15 +        return NULL;
    1.16 +
    1.17 +    // Ensure the inner type has an ArrayMap if needed.
    1.18 +    if (type->contained()->isArray()) {
    1.19 +        Local<Type> contained(zone, type->contained());
    1.20 +        if (!ArrayMap::Attach(zone, contained))
    1.21 +            return NULL;
    1.22 +    }
    1.23 +
    1.24 +    type->setNewMap(map);
    1.25 +    return map;
    1.26 +}
    1.27 +
    1.28  static inline size_t
    1.29  SizeFor(Type *type, unsigned elements)
    1.30  {
    1.31 @@ -89,6 +110,18 @@
    1.32  }
    1.33  
    1.34  Array *
    1.35 +Array::NewString(Zone *zone, Handle<ArrayMap> map, Address buffer, size_t length, Heap::Tenure tenure)
    1.36 +{
    1.37 +    Local<Array> array(zone, Array::New(zone, map, length, tenure));
    1.38 +    if (!array)
    1.39 +        return NULL;
    1.40 +
    1.41 +    assert(array->length() >= length);
    1.42 +    memcpy(array->chars(), buffer, length);
    1.43 +    return array;
    1.44 +}
    1.45 +
    1.46 +Array *
    1.47  Array::NewExternal(Zone *zone, Handle<ArrayMap> map, uint32 nelements, void *buffer,
    1.48                     Heap::Tenure tenure)
    1.49  {
     2.1 --- a/src/Array.h	Sun Aug 05 21:24:41 2012 -0700
     2.2 +++ b/src/Array.h	Mon Aug 06 02:03:36 2012 -0700
     2.3 @@ -36,6 +36,7 @@
     2.4    public:
     2.5      static Array *New(Zone *zone, Handle<ArrayMap> map, uint32 elements,
     2.6                        Heap::Tenure = Heap::Tenure_Default);
     2.7 +    static Array *NewString(Zone *zone, Handle<ArrayMap> map, Address buffer, size_t length, Heap::Tenure = Heap::Tenure_Default);
     2.8      static Array *NewExternal(Zone *zone, Handle<ArrayMap> map, uint32 nelements,
     2.9                                void *elements, Heap::Tenure = Heap::Tenure_Default);
    2.10  
    2.11 @@ -112,6 +113,7 @@
    2.12  
    2.13    public:
    2.14      static ArrayMap *New(Zone *zone, Handle<Type> type);
    2.15 +    static ArrayMap *Attach(Zone *zone, Handle<Type> type);
    2.16  
    2.17      Type *type() {
    2.18          return type_;
     3.1 --- a/src/Box.cpp	Sun Aug 05 21:24:41 2012 -0700
     3.2 +++ b/src/Box.cpp	Mon Aug 06 02:03:36 2012 -0700
     3.3 @@ -49,7 +49,7 @@
     3.4  }
     3.5  
     3.6  Box *
     3.7 -Box::New(Zone *zone, Handle<Type> type, Object *obj, Heap::Tenure tenure)
     3.8 +Box::NewObj(Zone *zone, Handle<Type> type, Handle<Object> obj, Heap::Tenure tenure)
     3.9  {
    3.10      Local<Box> box(zone, Box::cast(zone->allocate(MapKind_Box, sizeof(Box), tenure)));
    3.11      if (!box)
     4.1 --- a/src/Box.h	Sun Aug 05 21:24:41 2012 -0700
     4.2 +++ b/src/Box.h	Mon Aug 06 02:03:36 2012 -0700
     4.3 @@ -40,7 +40,8 @@
     4.4    public:
     4.5      static Box *New(Zone *zone, Handle<Type> type, int i32, Heap::Tenure = Heap::Tenure_Default);
     4.6      static Box *New(Zone *zone, Handle<Type> type, float f, Heap::Tenure = Heap::Tenure_Default);
     4.7 -    static Box *New(Zone *zone, Handle<Type> type, Object *obj, Heap::Tenure = Heap::Tenure_Default);
     4.8 +    static Box *NewObj(Zone *zone, Handle<Type> type, Handle<Object> obj,
     4.9 +                       Heap::Tenure = Heap::Tenure_Default);
    4.10  
    4.11      Type *type() {
    4.12          return type_;
    4.13 @@ -54,6 +55,10 @@
    4.14          assert(type()->pod() == PrimitiveType_Float);
    4.15          return u.f;
    4.16      }
    4.17 +    Object *toObject() {
    4.18 +        assert(type()->isTraceable());
    4.19 +        return u.obj;
    4.20 +    }
    4.21  
    4.22      // Begin GC descriptor.
    4.23      static inline size_t offsetOfType() {
     5.1 --- a/src/BytecodeCompiler.cpp	Sun Aug 05 21:24:41 2012 -0700
     5.2 +++ b/src/BytecodeCompiler.cpp	Mon Aug 06 02:03:36 2012 -0700
     5.3 @@ -721,42 +721,23 @@
     5.4      __ float_((float)node->value());
     5.5  }
     5.6  
     5.7 -static inline ArrayMap *
     5.8 -BuildArrayMap(Zone *zone, Handle<Type> type)
     5.9 -{
    5.10 -    if (type->newMap())
    5.11 -        return ArrayMap::cast(type->newMap());
    5.12 -
    5.13 -    Local<ArrayMap> map(zone, ArrayMap::New(zone, type));
    5.14 -    if (!map)
    5.15 -        return NULL;
    5.16 -
    5.17 -    // Ensure the inner type has an array map if needed.
    5.18 -    if (type->contained()->isArray()) {
    5.19 -        Local<Type> contained(zone, type->contained());
    5.20 -        if (!BuildArrayMap(zone, contained))
    5.21 -            return NULL;
    5.22 -    }
    5.23 -
    5.24 -    type->setNewMap(map);
    5.25 -    return map;
    5.26 -}
    5.27 -
    5.28  void
    5.29  BytecodeCompiler::visit(StringLiteral *node)
    5.30  {
    5.31      Local<Type> type(zone_, node->type());
    5.32 -    Local<ArrayMap> map(zone_, BuildArrayMap(zone_, type));
    5.33 +    Local<ArrayMap> map(zone_, ArrayMap::Attach(zone_, type));
    5.34      if (!map)
    5.35          return;
    5.36  
    5.37 -    Local<Array> array(zone_, Array::New(zone_, map, node->string()->length(), Heap::Tenure_Old));
    5.38 +    Local<Array> array(zone_,
    5.39 +        Array::NewString(zone_,
    5.40 +                         map,
    5.41 +                         node->string()->raw(),
    5.42 +                         node->string()->length(),
    5.43 +                         Heap::Tenure_Old));
    5.44      if (!array)
    5.45          return;
    5.46  
    5.47 -    assert(array->length() >= node->string()->length());
    5.48 -    memcpy(array->chars(), node->string()->raw(), node->string()->length() * sizeof(char));
    5.49 -
    5.50      __ note_position(node->pos());
    5.51      __ object(array);
    5.52  }
    5.53 @@ -782,7 +763,7 @@
    5.54      
    5.55      Local<Type> type(zone_, var->type());
    5.56      if (type->isArray()) {
    5.57 -        Local<ArrayMap> map(zone_, BuildArrayMap(zone_, type));
    5.58 +        Local<ArrayMap> map(zone_, ArrayMap::Attach(zone_, type));
    5.59          __ note_position(node->pos());
    5.60          if (var->scope()->kind() == Scope::GLOBAL)
    5.61              __ newarray(map, Heap::Tenure_Old);
    5.62 @@ -900,6 +881,8 @@
    5.63      // If there are missing arguments, then we're not done and have to push
    5.64      // default parameters.
    5.65      Local<Box> box(zone_);
    5.66 +    Local<Array> array(zone_);
    5.67 +    Local<ArrayMap> map(zone_);
    5.68      for (size_t i = node->arguments()->length(); i < funType->parameters()->length(); i++) {
    5.69          box = Box::cast(funType->defaults()->at(i));
    5.70  
    5.71 @@ -910,13 +893,29 @@
    5.72                  __ float_(box->toFloat());
    5.73              else
    5.74                  assert(false);
    5.75 +
    5.76 +            if (funType->parameterAt(i)->isReference()) {
    5.77 +                __ note_position(node->pos());
    5.78 +                __ slotref_lifo();
    5.79 +            }
    5.80          } else {
    5.81 -            assert(false);
    5.82 -        }
    5.83 +            assert(box->type()->isArray());
    5.84  
    5.85 -        if (funType->parameterAt(i)->isReference()) {
    5.86 -            __ note_position(node->pos());
    5.87 -            __ slotref_lifo();
    5.88 +            array = Array::cast(box->toObject());
    5.89 +            if (funType->parameterAt(i)->isConst()) {
    5.90 +                __ object(array);
    5.91 +            } else {
    5.92 +                // We need to copy the array since it's mutable. Note that
    5.93 +                // although COPYARRAY returns its left-hand side, this may
    5.94 +                // change in the future, we do the same thing and dupe the
    5.95 +                // newly allocated array.
    5.96 +                map = ArrayMap::cast(array->map());
    5.97 +                __ newarray(map, Heap::Tenure_Stack);
    5.98 +                __ dup();
    5.99 +                __ object(array);
   5.100 +                __ copyarray();
   5.101 +                __ pop();
   5.102 +            }
   5.103          }
   5.104  
   5.105          argc++;
     6.1 --- a/src/SemanticAnalysis.cpp	Sun Aug 05 21:24:41 2012 -0700
     6.2 +++ b/src/SemanticAnalysis.cpp	Mon Aug 06 02:03:36 2012 -0700
     6.3 @@ -25,6 +25,7 @@
     6.4  #include "NameBinding.h"
     6.5  #include "Strings.h"
     6.6  #include "Box.h"
     6.7 +#include "Array.h"
     6.8  #include "Heap-inl.h"
     6.9  
    6.10  using namespace ke;
    6.11 @@ -857,6 +858,33 @@
    6.12          if (prim.type() == PrimitiveType_Int32)
    6.13              return Box::New(zone_, type, prim.toInt());
    6.14          return Box::New(zone_, type, int(prim.toBool()));
    6.15 +    } else if (parameter->initializer()->isStringLiteral()) {
    6.16 +        StringLiteral *literal = parameter->initializer()->toStringLiteral();
    6.17 +
    6.18 +        // This actually builds a mutable string, so we can use it as-is. The
    6.19 +        // bytecode compiler will copy it if needed.
    6.20 +        literal->accept(this);
    6.21 +        if (!literal->type())
    6.22 +            return NULL;
    6.23 +
    6.24 +        Local<Type> given(zone_, literal->type());
    6.25 +        if (!typeCheckAssignment(parameter->initializer()->pos(), given, type, false))
    6.26 +            return NULL;
    6.27 +
    6.28 +        Local<ArrayMap> map(zone_, ArrayMap::Attach(zone_, given));
    6.29 +        if (!map)
    6.30 +            return NULL;
    6.31 +
    6.32 +        Local<Array> array(zone_,
    6.33 +            Array::NewString(zone_,
    6.34 +                             map,
    6.35 +                             literal->string()->raw(),
    6.36 +                             literal->string()->length(),
    6.37 +                             Heap::Tenure_Old));
    6.38 +        if (!array)
    6.39 +            return NULL;
    6.40 +
    6.41 +        return Box::NewObj(zone_, given, array, Heap::Tenure_Old);
    6.42      }
    6.43  
    6.44      cc_.reportError(parameter->initializer()->pos(), Message_MustBeConstant);
    6.45 @@ -880,20 +908,6 @@
    6.46          if (!type)
    6.47              return false;
    6.48  
    6.49 -        if (parameter->initializer()) {
    6.50 -            if (!defaults) {
    6.51 -                defaults = FixedArray::New(zone_, node->parameters()->length(), Heap::Tenure_Old);
    6.52 -                if (!defaults)
    6.53 -                    return false;
    6.54 -            }
    6.55 -
    6.56 -            Local<Box> box(zone_, evaluateDefaultParameter(type, parameter));
    6.57 -            if (!box)
    6.58 -                return false;
    6.59 -
    6.60 -            defaults->set(zone_, i, box);
    6.61 -        }
    6.62 -
    6.63          if (parameter->reference()) {
    6.64              if (parameter->dimensions()) {
    6.65                  cc_.reportError(parameter->variable()->pos(), Message_ArrayCantBeReference);
    6.66 @@ -946,6 +960,20 @@
    6.67  
    6.68          args->set(zone_, i, type);
    6.69          parameter->variable()->setType(type);
    6.70 +
    6.71 +        if (parameter->initializer()) {
    6.72 +            if (!defaults) {
    6.73 +                defaults = FixedArray::New(zone_, node->parameters()->length(), Heap::Tenure_Old);
    6.74 +                if (!defaults)
    6.75 +                    return false;
    6.76 +            }
    6.77 +
    6.78 +            Local<Box> box(zone_, evaluateDefaultParameter(type, parameter));
    6.79 +            if (!box)
    6.80 +                return false;
    6.81 +
    6.82 +            defaults->set(zone_, i, box);
    6.83 +        }
    6.84      }
    6.85  
    6.86      Local<Type> returnType(zone_);