Re-added parameter support.
authorDavid Anderson <dvander@alliedmods.net>
Mon Nov 19 01:13:44 2012 -0800 (2012-11-19)
changeset 2205df4a112967d
parent 219 99e534728b76
child 221 0c588a96837c
Re-added parameter support.
src/compiler/AST.h
src/compiler/BytecodeEmitter.cpp
src/compiler/BytecodeEmitter.h
src/compiler/HIR.cpp
src/compiler/NameBinding.cpp
src/compiler/Parser.cpp
src/compiler/SemanticAnalysis.cpp
src/compiler/SemanticAnalysis.h
src/compiler/Symbols.h
tests/basic/passarray.out
tests/basic/passarray.sp
tests/prototype/passarray.jc
     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 -