Allow returning arrays from functions.
Allow returning arrays from functions.
1.1 --- a/src/AST.h Sun Sep 16 21:59:26 2012 -0700
1.2 +++ b/src/AST.h Sun Sep 16 22:49:54 2012 -0700
1.3 @@ -779,8 +779,9 @@
1.4 class FunctionSignature
1.5 {
1.6 public:
1.7 - FunctionSignature(BoundName *returnType, ParameterList *parameters)
1.8 + FunctionSignature(BoundName *returnType, ExpressionList *returnDimensions, ParameterList *parameters)
1.9 : returnType_(returnType),
1.10 + returnDimensions_(returnDimensions),
1.11 parameters_(parameters)
1.12 {
1.13 }
1.14 @@ -788,12 +789,16 @@
1.15 BoundName *returnType() const {
1.16 return returnType_;
1.17 }
1.18 + ExpressionList *returnDimensions() const {
1.19 + return returnDimensions_;
1.20 + }
1.21 ParameterList *parameters() const {
1.22 return parameters_;
1.23 }
1.24
1.25 private:
1.26 BoundName *returnType_;
1.27 + ExpressionList *returnDimensions_;
1.28 ParameterList *parameters_;
1.29 };
1.30
2.1 --- a/src/Handles.h Sun Sep 16 21:59:26 2012 -0700
2.2 +++ b/src/Handles.h Sun Sep 16 22:49:54 2012 -0700
2.3 @@ -129,6 +129,11 @@
2.4 return thing_;
2.5 }
2.6
2.7 + Local &operator =(const Local &other) {
2.8 + thing_ = other.thing_;
2.9 + return *this;
2.10 + }
2.11 +
2.12 private:
2.13 // Disallow heap allocation.
2.14 void *operator new(size_t size);
2.15 @@ -136,7 +141,6 @@
2.16
2.17 // Disallow copy construction.
2.18 Local(const Local<T> &other);
2.19 - Local &operator =(const Local &other);
2.20 };
2.21
2.22 // A ScopedRoot is a special kind of handle for storing references on the
3.1 --- a/src/Parser.cpp Sun Sep 16 21:59:26 2012 -0700
3.2 +++ b/src/Parser.cpp Sun Sep 16 22:49:54 2012 -0700
3.3 @@ -1257,18 +1257,42 @@
3.4
3.5 token = TOK_STOCK;
3.6 } else {
3.7 - if (matchName(returnTag.ref(), TOK_LABEL) && !returnTag)
3.8 + if (peek(TOK_LABEL)) {
3.9 + if (matchName(returnTag.ref(), TOK_LABEL) && !returnTag)
3.10 + return NULL;
3.11 + } else if (peek(TOK_NAME)) {
3.12 + // Peek for a type that has no :
3.13 + returnTag = expectName();
3.14 + if (!returnTag)
3.15 + return NULL;
3.16 + }
3.17 + }
3.18 +
3.19 + Local<String> name(zone_);
3.20 + ExpressionList *returnDimensions = NULL;
3.21 +
3.22 + bool allowArrayReturns = token != TOK_NATIVE &&
3.23 + token != TOK_PUBLIC &&
3.24 + token != TOK_FORWARD;
3.25 +
3.26 + if (allowArrayReturns && peek(TOK_LBRACKET)) {
3.27 + if ((returnDimensions = dimensions()) == NULL)
3.28 return NULL;
3.29 + if ((name = expectName()) == NULL)
3.30 + return NULL;
3.31 + } else if (peek(TOK_NAME)) {
3.32 + if ((name = expectName()) == NULL)
3.33 + return NULL;
3.34 + } else {
3.35 + // We predicted |type name|, but just got |name| instead.
3.36 + name = returnTag;
3.37 + returnTag = NULL;
3.38 }
3.39
3.40 BoundName *returnType = NULL;
3.41 if (returnTag)
3.42 returnType = bindType(returnTag);
3.43
3.44 - Local<String> name(zone_, expectName());
3.45 - if (!name)
3.46 - return NULL;
3.47 -
3.48 SourcePosition pos = scanner_.begin();
3.49
3.50 // The function name goes into the outer (global) scope.
3.51 @@ -1392,7 +1416,7 @@
3.52
3.53 scope_ = scope_->enclosing();
3.54
3.55 - FunctionSignature signature(returnType, parameters);
3.56 + FunctionSignature signature(returnType, returnDimensions, parameters);
3.57 if (token == TOK_TYPEDEF)
3.58 return new (pool_) FunctionTypeStatement(pos, type, signature);
3.59
3.60 @@ -1560,6 +1584,17 @@
3.61 {
3.62 }
3.63
3.64 + void dump(const FunctionSignature &sig) {
3.65 + prefix();
3.66 + fprintf(fp_, "%s", sig.returnType()
3.67 + ? sig.returnType()->name()->chars()
3.68 + : "_");
3.69 + if (sig.returnDimensions()) {
3.70 + for (size_t i = 0; i < sig.returnDimensions()->length(); i++)
3.71 + fprintf(fp_, "[]");
3.72 + }
3.73 + fprintf(fp_, "()\n");
3.74 + }
3.75 void visit(NameProxy *name) {
3.76 prefix();
3.77 fprintf(fp_, "[ NameProxy (%s)%s\n", name->name()->chars(),
3.78 @@ -1577,11 +1612,15 @@
3.79 void visit(FunctionTypeStatement *node) {
3.80 prefix();
3.81 fprintf(fp_, "[ FunctionTypeStatement (%s)\n", node->decl()->name()->chars());
3.82 + indent();
3.83 + dump(node->signature());
3.84 + unindent();
3.85 }
3.86 void visit(FunctionStatement *node) {
3.87 prefix();
3.88 fprintf(fp_, "[ FunctionStatement (%s)\n", node->fun()->name()->chars());
3.89 indent();
3.90 + dump(node->signature());
3.91 if (node->body())
3.92 node->body()->accept(this);
3.93 unindent();
4.1 --- a/src/SemanticAnalysis.cpp Sun Sep 16 21:59:26 2012 -0700
4.2 +++ b/src/SemanticAnalysis.cpp Sun Sep 16 22:49:54 2012 -0700
4.3 @@ -1027,35 +1027,14 @@
4.4 if (!type)
4.5 return false;
4.6 } else if (parameter->dimensions()) {
4.7 - // :TODO: factor in type dimcount
4.8 - if (parameter->dimensions()->length() > MAX_ARRAY_DEPTH) {
4.9 - cc_.reportError(parameter->variable()->pos(), Message_MaximumArrayDepth);
4.10 + type = buildArrayType(type, parameter->dimensions(), parameter->isConst());
4.11 + if (!type)
4.12 return false;
4.13 - }
4.14
4.15 - if (kind == TOK_NATIVE && parameter->dimensions()->length() > 1) {
4.16 + if (kind == TOK_NATIVE && type->levels() > 1) {
4.17 cc_.reportError(parameter->variable()->pos(), Message_MultiArrayInNative);
4.18 return false;
4.19 }
4.20 -
4.21 - for (size_t i = parameter->dimensions()->length() - 1;
4.22 - i < parameter->dimensions()->length();
4.23 - i--)
4.24 - {
4.25 - int size = Type::DYNAMIC_ARRAY_SIZE;
4.26 - if (Expression *expr = parameter->dimensions()->at(i)) {
4.27 - BoxedPrimitive box;
4.28 - if (!EvaluateForConstant(expr, &box) || box.type() != PrimitiveType_Int32) {
4.29 - cc_.reportError(expr->pos(), Message_ArraySizeMustBeConstant);
4.30 - return false;
4.31 - }
4.32 - size = box.toInt();
4.33 - }
4.34 -
4.35 - type = zone_->types()->newArray(type, size, parameter->isConst());
4.36 - if (!type)
4.37 - return false;
4.38 - }
4.39 }
4.40
4.41 if (IsScalarString(type)) {
4.42 @@ -1122,6 +1101,51 @@
4.43 node->decl()->setType(funtype);
4.44 }
4.45
4.46 +Type *
4.47 +SemanticAnalysis::buildArrayType(Handle<Type> type, ExpressionList *dimensions, bool isConst)
4.48 +{
4.49 + Local<Type> arrayType(zone_, type);
4.50 +
4.51 + unsigned dimcount = dimensions->length();
4.52 + if (type->isArray())
4.53 + dimcount += type->levels();
4.54 +
4.55 + if (dimcount > MAX_ARRAY_DEPTH) {
4.56 + cc_.reportError(dimensions->at(dimensions->length() - 1)->pos(),
4.57 + Message_MaximumArrayDepth);
4.58 + return false;
4.59 + }
4.60 +
4.61 + // Note: constness is sort of bogus. Fix this sometime.
4.62 + for (size_t i = dimensions->length() - 1; i < dimensions->length(); i--) {
4.63 + Expression *expr = dimensions->at(i);
4.64 + if (!expr) {
4.65 + arrayType = zone_->types()->newArray(arrayType, Type::DYNAMIC_ARRAY_SIZE, isConst);
4.66 + if (!arrayType)
4.67 + return NULL;
4.68 +
4.69 + continue;
4.70 + }
4.71 +
4.72 + BoxedPrimitive box;
4.73 + if (!EvaluateForConstant(expr, &box) || box.type() != PrimitiveType_Int32) {
4.74 + cc_.reportError(expr->pos(), Message_ArraySizeMustBeConstant);
4.75 + return NULL;
4.76 + }
4.77 +
4.78 + if (box.toInt() <= 0) {
4.79 + cc_.reportError(expr->pos(), Message_BadArraySize);
4.80 + return NULL;
4.81 + }
4.82 +
4.83 + arrayType = zone_->types()->newArray(arrayType, box.toInt(), isConst);
4.84 + if (!arrayType)
4.85 + return NULL;
4.86 + }
4.87 +
4.88 + return arrayType;
4.89 +}
4.90 +
4.91 bool
4.92 SemanticAnalysis::preanalyze(FunctionStatement *node)
4.93 {
4.94 @@ -1150,6 +1174,17 @@
4.95 if (!returnType)
4.96 return false;
4.97
4.98 + if (sig.returnDimensions()) {
4.99 + returnType = buildArrayType(returnType, sig.returnDimensions(), false);
4.100 + if (!returnType)
4.101 + return false;
4.102 + }
4.103 +
4.104 + if (IsScalarString(returnType)) {
4.105 + cc_.reportError(node->pos(), Message_CannotDeclareStringCell);
4.106 + return false;
4.107 + }
4.108 +
4.109 Local<Type> funtype(zone_);
4.110 if (node->fun()->isNative())
4.111 funtype = zone_->types()->newNative(returnType, args, defaults, node->fun()->isNativeVariadic());
5.1 --- a/src/SemanticAnalysis.h Sun Sep 16 21:59:26 2012 -0700
5.2 +++ b/src/SemanticAnalysis.h Sun Sep 16 22:49:54 2012 -0700
5.3 @@ -182,6 +182,9 @@
5.4 unsigned dimcount,
5.5 unsigned level);
5.6
5.7 + // Builds an array type used for parameters, returns, or field entries.
5.8 + Type *buildArrayType(Handle<Type> type, ExpressionList *dimensions, bool isConst);
5.9 +
5.10 Box *evaluateDefaultParameter(Handle<Type> type, Parameter *parameter);
5.11 bool checkArgumentCount(Handle<Type> type, unsigned actual);
5.12 bool buildFunctionArgs(AstNode *node, TokenKind kind, const FunctionSignature &sig,