Re-added parameter support.
Re-added parameter support.
1.1 --- a/src/compiler/AST.h Sun Nov 18 22:18:23 2012 -0800
1.2 +++ b/src/compiler/AST.h Mon Nov 19 01:13:44 2012 -0800
1.3 @@ -205,17 +205,19 @@
1.4 Expression *initializer_;
1.5 VariableSymbol *sym_;
1.6 SourcePosition pos_;
1.7 + ExpressionList *dims_;
1.8
1.9 public:
1.10 Parameter(Handle<String> name, Expression *type, bool reference, bool isConst,
1.11 - Expression *initializer, const SourcePosition &pos)
1.12 + ExpressionList *dims, Expression *initializer, const SourcePosition &pos)
1.13 : name_(name),
1.14 type_(type),
1.15 reference_(reference),
1.16 const_(isConst),
1.17 initializer_(initializer),
1.18 sym_(NULL),
1.19 - pos_(pos)
1.20 + pos_(pos),
1.21 + dims_(dims)
1.22 {
1.23 }
1.24
1.25 @@ -231,6 +233,9 @@
1.26 bool isConst() const {
1.27 return const_;
1.28 }
1.29 + ExpressionList *dims() const {
1.30 + return dims_;
1.31 + }
1.32 Expression *initializer() const {
1.33 return initializer_;
1.34 }
2.1 --- a/src/compiler/BytecodeEmitter.cpp Sun Nov 18 22:18:23 2012 -0800
2.2 +++ b/src/compiler/BytecodeEmitter.cpp Mon Nov 19 01:13:44 2012 -0800
2.3 @@ -216,6 +216,7 @@
2.4 void
2.5 BytecodeEmitter::getlocal(VariableSymbol *var)
2.6 {
2.7 + assert(var->storage() == VariableSymbol::Local);
2.8 ensure(OP_GETLOCAL_LENGTH);
2.9 writeOp(OP_GETLOCAL);
2.10 writeUint32(var->slot());
2.11 @@ -226,6 +227,7 @@
2.12 void
2.13 BytecodeEmitter::setlocal(VariableSymbol *var)
2.14 {
2.15 + assert(var->storage() == VariableSymbol::Local);
2.16 ensure(OP_SETLOCAL_LENGTH);
2.17 writeOp(OP_SETLOCAL);
2.18 writeUint32(var->slot());
2.19 @@ -233,6 +235,28 @@
2.20 markOop(1);
2.21 }
2.22
2.23 +void
2.24 +BytecodeEmitter::getarg(VariableSymbol *var)
2.25 +{
2.26 + assert(var->storage() == VariableSymbol::Arg);
2.27 + ensure(OP_GETARG_LENGTH);
2.28 + writeOp(OP_GETARG);
2.29 + writeUint32(var->slot());
2.30 + if (var->type()->isTraceable())
2.31 + markOop(1);
2.32 +}
2.33 +
2.34 +void
2.35 +BytecodeEmitter::setarg(VariableSymbol *var)
2.36 +{
2.37 + assert(var->storage() == VariableSymbol::Arg);
2.38 + ensure(OP_SETARG_LENGTH);
2.39 + writeOp(OP_SETARG);
2.40 + writeUint32(var->slot());
2.41 + if (var->type()->isTraceable())
2.42 + markOop(1);
2.43 +}
2.44 +
2.45 bool
2.46 BytecodeEmitter::allocate(VariableSymbol *sym)
2.47 {
3.1 --- a/src/compiler/BytecodeEmitter.h Sun Nov 18 22:18:23 2012 -0800
3.2 +++ b/src/compiler/BytecodeEmitter.h Mon Nov 19 01:13:44 2012 -0800
3.3 @@ -333,24 +333,8 @@
3.4 }
3.5 void getlocal(VariableSymbol *var);
3.6 void setlocal(VariableSymbol *var);
3.7 -#if 0
3.8 - void getarg(Variable *var) {
3.9 - ensure(OP_GETARG_LENGTH);
3.10 - writeOp(OP_GETARG);
3.11 - writeUint32(var->slot());
3.12 -
3.13 - if (var->type()->isTraceable())
3.14 - markOop(1);
3.15 - }
3.16 - void setarg(Variable *var) {
3.17 - ensure(OP_SETARG_LENGTH);
3.18 - writeOp(OP_SETARG);
3.19 - writeUint32(var->slot());
3.20 -
3.21 - if (var->type()->isTraceable())
3.22 - markOop(1);
3.23 - }
3.24 -#endif
3.25 + void getarg(VariableSymbol *var);
3.26 + void setarg(VariableSymbol *var);
3.27
3.28 void j(Opcode op, Label *label) {
3.29 // Since jumps can skip around the stream, do not try to do anything
4.1 --- a/src/compiler/HIR.cpp Sun Nov 18 22:18:23 2012 -0800
4.2 +++ b/src/compiler/HIR.cpp Mon Nov 19 01:13:44 2012 -0800
4.3 @@ -115,8 +115,14 @@
4.4 void
4.5 HLocal::bind(HIRVisitor *visitor, BytecodeEmitter &emitter_)
4.6 {
4.7 - if (sym_->type()->isReference())
4.8 - __ getlocal(sym_);
4.9 + if (sym_->type()->isReference()) {
4.10 + if (sym_->storage() == VariableSymbol::Local)
4.11 + __ getlocal(sym_);
4.12 + else if (sym_->storage() == VariableSymbol::Arg)
4.13 + __ getarg(sym_);
4.14 + else
4.15 + assert(false);
4.16 + }
4.17 }
4.18
4.19 void
4.20 @@ -140,10 +146,16 @@
4.21 void
4.22 HLocal::store(BytecodeEmitter &emitter_)
4.23 {
4.24 - if (sym_->type()->isReference())
4.25 + if (sym_->type()->isReference()) {
4.26 __ setref(sym_->type()->contained_ref());
4.27 - else
4.28 - __ setlocal(sym_);
4.29 + } else {
4.30 + if (sym_->storage() == VariableSymbol::Local)
4.31 + __ setlocal(sym_);
4.32 + else if (sym_->storage() == VariableSymbol::Arg)
4.33 + __ setarg(sym_);
4.34 + else
4.35 + assert(false);
4.36 + }
4.37 }
4.38
4.39 void
4.40 @@ -151,8 +163,12 @@
4.41 {
4.42 if (sym_->type()->isReference())
4.43 __ getref(sym_->type());
4.44 + else if (sym_->storage() == VariableSymbol::Local)
4.45 + __ getlocal(sym_);
4.46 + else if (sym_->storage() == VariableSymbol::Arg)
4.47 + __ getarg(sym_);
4.48 else
4.49 - __ getlocal(sym_);
4.50 + assert(false);
4.51 }
4.52
4.53 void
4.54 @@ -206,7 +222,8 @@
4.55 void
4.56 HIRTranslator::visitGlobal(HGlobal *global)
4.57 {
4.58 - __ getglobal(global->sym());
4.59 + global->bind(this, emitter_);
4.60 + global->load(emitter_);
4.61 }
4.62
4.63 static inline Opcode
5.1 --- a/src/compiler/NameBinding.cpp Sun Nov 18 22:18:23 2012 -0800
5.2 +++ b/src/compiler/NameBinding.cpp Mon Nov 19 01:13:44 2012 -0800
5.3 @@ -802,7 +802,24 @@
5.4 Parameter *param = sig.parameters()->at(i);
5.5 if ((type = bindType(param->type())) == NULL)
5.6 return false;
5.7 +
5.8 + if (type->isArray() || param->dims()) {
5.9 + int dims[MAX_ARRAY_DEPTH];
5.10 + int levels = evaluateDimensions(param->pos(), type, param->dims(), dims);
5.11 + if (levels < 0)
5.12 + return false;
5.13 +
5.14 + // If we got extra dimensions, we need to build a new type.
5.15 + // Unlike variables, we do not infer anything about array
5.16 + // sizes from its default initializer.
5.17 + if (param->dims()) {
5.18 + if ((type = buildArrayType(type, dims, param->dims()->length())) == NULL)
5.19 + return false;
5.20 + }
5.21 + }
5.22 +
5.23 params->set(zone_, i, type);
5.24 + param->sym()->setType(type);
5.25 }
5.26
5.27 fun->setParameterTypes(params);
6.1 --- a/src/compiler/Parser.cpp Sun Nov 18 22:18:23 2012 -0800
6.2 +++ b/src/compiler/Parser.cpp Mon Nov 19 01:13:44 2012 -0800
6.3 @@ -1279,13 +1279,19 @@
6.4 break;
6.5 }
6.6
6.7 + ExpressionList *dims = NULL;
6.8 + if (peek(TOK_LBRACKET)) {
6.9 + if ((dims = dimensions()) == NULL)
6.10 + return NULL;
6.11 + }
6.12 +
6.13 Expression *expr = NULL;
6.14 if (match(TOK_ASSIGN)) {
6.15 if ((expr = expression()) == NULL)
6.16 return NULL;
6.17 }
6.18
6.19 - Parameter *parameter = new (pool_) Parameter(name, type, ref, isConst, expr, begin);
6.20 + Parameter *parameter = new (pool_) Parameter(name, type, ref, isConst, dims, expr, begin);
6.21 if (!parameters->append(parameter))
6.22 return NULL;
6.23
7.1 --- a/src/compiler/SemanticAnalysis.cpp Sun Nov 18 22:18:23 2012 -0800
7.2 +++ b/src/compiler/SemanticAnalysis.cpp Mon Nov 19 01:13:44 2012 -0800
7.3 @@ -160,6 +160,12 @@
7.4 __ setFirstLine(stmt->pos().line);
7.5
7.6 AutoEnterScope argScope(&scope_, stmt->argScope());
7.7 +
7.8 + for (size_t i = 0; i < stmt->signature().parameters()->length(); i++) {
7.9 + Parameter *param = stmt->signature().parameters()->at(i);
7.10 + param->sym()->allocate(VariableSymbol::Arg, i);
7.11 + }
7.12 +
7.13 AutoEnterScope varScope(&scope_, stmt->varScope());
7.14
7.15 stmt->body()->accept(this);
7.16 @@ -205,7 +211,8 @@
7.17 return;
7.18
7.19 discharge(hir);
7.20 - __ pop();
7.21 + if (!hir->type()->isVoid())
7.22 + __ pop();
7.23 }
7.24
7.25 void
7.26 @@ -428,6 +435,11 @@
7.27 hir_ = new (pool_) HGlobal(sym);
7.28 return;
7.29
7.30 + case Scope::FUNCTION:
7.31 + assert(var->storage() == VariableSymbol::Arg);
7.32 + hir_ = new (pool_) HLocal(var);
7.33 + return;
7.34 +
7.35 default:
7.36 assert(in->kind() == Scope::BLOCK);
7.37 assert(var->storage() == VariableSymbol::Local);
7.38 @@ -631,6 +643,87 @@
7.39 return left->type();
7.40 }
7.41
7.42 +bool
7.43 +SemanticAnalysis::typeCheckArray(const SourcePosition &pos,
7.44 + Handle<Type> argGiven,
7.45 + Handle<Type> argActual,
7.46 + CoercionKind kind)
7.47 +{
7.48 + if (!argGiven->isArray()) {
7.49 + cc_.reportError(pos, Message_ExpectedArray);
7.50 + return false;
7.51 + }
7.52 +
7.53 + Local<ArrayType> actual(zone_, ArrayType::cast(argActual));
7.54 + Local<ArrayType> given(zone_, ArrayType::cast(argGiven));
7.55 +
7.56 + if (actual->levels() != given->levels()) {
7.57 + cc_.reportError(pos, Message_ArrayDimensionsMismatch);
7.58 + return false;
7.59 + }
7.60 +
7.61 + unsigned level = 1;
7.62 + while (true) {
7.63 + if (actual->isFixedLength()) {
7.64 + if (kind == Coerce_Return || kind == Coerce_Assign) {
7.65 + if (!given->isFixedLength()) {
7.66 + cc_.reportError(pos, Message_ArrayDimensionSizeMismatch, level);
7.67 + return false;
7.68 + }
7.69 +
7.70 + if (actual->isCharArray()) {
7.71 + // String assignment can have a truncated |given|.
7.72 + if (given->fixedLength() > actual->fixedLength()) {
7.73 + cc_.reportError(pos, Message_ArrayAssignmentTooBig);
7.74 + return false;
7.75 + }
7.76 + } else {
7.77 + if (given->fixedLength() != actual->fixedLength()) {
7.78 + cc_.reportError(pos, Message_ArrayDimensionSizeMismatch, level);
7.79 + return false;
7.80 + }
7.81 + }
7.82 + }
7.83 + } else if (given->isFixedLength()) {
7.84 + // We do not allow assignments in the form:
7.85 + // [][] = [][Y]
7.86 + //
7.87 + // Otherwise, the following code could break the size guarantees
7.88 + // of the right-hand side:
7.89 + //
7.90 + // new x[][5];
7.91 + // new y[][];
7.92 + // new z[3];
7.93 + //
7.94 + //
7.95 + // y = x;
7.96 + // y[0] = z;
7.97 + //
7.98 + // Now |x[0]| contains a 3-length array.
7.99 + if (level > 1) {
7.100 + cc_.reportError(pos, Message_ArrayDimensionSizeMismatch, level);
7.101 + return false;
7.102 + }
7.103 + }
7.104 +
7.105 + if (!given->contained()->isArray() || !actual->contained()->isArray())
7.106 + break;
7.107 +
7.108 + given = ArrayType::cast(given->contained());
7.109 + actual = ArrayType::cast(actual->contained());
7.110 + }
7.111 +
7.112 + // These arrays must contain the same innermost type.
7.113 + if (given->contained() != actual->contained()) {
7.114 + cc_.reportError(pos, Message_TypeMismatch,
7.115 + GetTypeName(actual->contained()),
7.116 + GetTypeName(given->contained()));
7.117 + return false;
7.118 + }
7.119 +
7.120 + return true;
7.121 +}
7.122 +
7.123 HIR *
7.124 SemanticAnalysis::coerce(HIR *hir, Handle<Type> to, CoercionKind kind)
7.125 {
7.126 @@ -641,7 +734,11 @@
7.127 if (from->isInt32() && to->isBool())
7.128 return new (pool_) HConvert(to, OP_CVT_I2B, hir);
7.129
7.130 - assert(from == to);
7.131 + if (to->isArray()) {
7.132 + if (!typeCheckArray(SourcePosition(), from, to, kind))
7.133 + return NULL;
7.134 + return hir;
7.135 + }
7.136
7.137 return hir;
7.138 }
8.1 --- a/src/compiler/SemanticAnalysis.h Sun Nov 18 22:18:23 2012 -0800
8.2 +++ b/src/compiler/SemanticAnalysis.h Mon Nov 19 01:13:44 2012 -0800
8.3 @@ -103,6 +103,11 @@
8.4 HLValue *lvalue(Expression *expr);
8.5 void discharge(HIR *hir);
8.6
8.7 + bool typeCheckArray(const SourcePosition &pos,
8.8 + Handle<Type> argGiven,
8.9 + Handle<Type> argActual,
8.10 + CoercionKind kind);
8.11 +
8.12 private:
8.13 // Used to target break/catch statements.
8.14 class LoopScope
9.1 --- a/src/compiler/Symbols.h Sun Nov 18 22:18:23 2012 -0800
9.2 +++ b/src/compiler/Symbols.h Mon Nov 19 01:13:44 2012 -0800
9.3 @@ -113,6 +113,7 @@
9.4 enum Storage {
9.5 Unknown,
9.6 Local,
9.7 + Arg,
9.8 Heap
9.9 };
9.10
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/tests/basic/passarray.out Mon Nov 19 01:13:44 2012 -0800
10.3 @@ -0,0 +1,1 @@
10.4 +037
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
11.2 +++ b/tests/basic/passarray.sp Mon Nov 19 01:13:44 2012 -0800
11.3 @@ -0,0 +1,23 @@
11.4 +native PrintNum(num);
11.5 +
11.6 +f(a[])
11.7 +{
11.8 + return a[3];
11.9 +}
11.10 +
11.11 +g(a[])
11.12 +{
11.13 + a[3] = 7;
11.14 +}
11.15 +
11.16 +public main()
11.17 +{
11.18 + new b[5];
11.19 + b[2] = 3;
11.20 + PrintNum(f(b));
11.21 + b[3] = 3;
11.22 + PrintNum(f(b));
11.23 + g(b);
11.24 + PrintNum(b[3]);
11.25 +}
11.26 +
12.1 --- a/tests/prototype/passarray.jc Sun Nov 18 22:18:23 2012 -0800
12.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
12.3 @@ -1,12 +0,0 @@
12.4 -f(a[])
12.5 -{
12.6 - return a[3];
12.7 -}
12.8 -
12.9 -public main()
12.10 -{
12.11 - new b[5];
12.12 - b[2] = 3;
12.13 - return f(b);
12.14 -}
12.15 -