Implement default string arguments.
Implement default string arguments.
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_);