Added runtime support for default arguments.
authorDavid Anderson <dvander@alliedmods.net>
Sun Aug 05 21:24:41 2012 -0700 (2012-08-05)
changeset 1684d0fff61d65e
parent 167 cf82769eb136
child 169 0456a16c2a63
Added runtime support for default arguments.
src/AMBuild.library
src/AST.h
src/Box.cpp
src/Box.h
src/BytecodeCompiler.cpp
src/Messages.tbl
src/ObjectVisitor.h
src/Objects.h
src/Reference.cpp
src/SemanticAnalysis.cpp
src/SemanticAnalysis.h
src/TypeManager.cpp
src/TypeManager.h
src/Types.cpp
src/Types.h
src/Zone.cpp
     1.1 --- a/src/AMBuild.library	Sun Aug 05 15:38:52 2012 -0700
     1.2 +++ b/src/AMBuild.library	Sun Aug 05 21:24:41 2012 -0700
     1.3 @@ -28,6 +28,7 @@
     1.4  files = [
     1.5  	'API.cpp',
     1.6  	'Array.cpp',
     1.7 +	'Box.cpp',
     1.8  	'BytecodeCompiler.cpp',
     1.9  	'BytecodeEmitter.cpp',
    1.10  	'CompileContext.cpp',
     2.1 --- a/src/AST.h	Sun Aug 05 15:38:52 2012 -0700
     2.2 +++ b/src/AST.h	Sun Aug 05 21:24:41 2012 -0700
     2.3 @@ -16,8 +16,8 @@
     2.4   * You should have received a copy of the GNU General Public License along with
     2.5   * SourcePawn. If not, see http://www.gnu.org/licenses/.
     2.6   */
     2.7 -#ifndef _include_jitcraft_ast_h_
     2.8 -#define _include_jitcraft_ast_h_
     2.9 +#ifndef _include_sourcepawn_ast_h_
    2.10 +#define _include_sourcepawn_ast_h_
    2.11  
    2.12  #include "PoolAllocator.h"
    2.13  #include "Token.h"
    2.14 @@ -1004,4 +1004,4 @@
    2.15  
    2.16  }
    2.17  
    2.18 -#endif // _include_jitcraft_ast_h_
    2.19 +#endif // _include_sourcepawn_ast_h_
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/src/Box.cpp	Sun Aug 05 21:24:41 2012 -0700
     3.3 @@ -0,0 +1,63 @@
     3.4 +/* vim: set ts=4 sw=4 tw=99 et:
     3.5 + *
     3.6 + * Copyright (C) 2012 David Anderson
     3.7 + *
     3.8 + * This file is part of SourcePawn.
     3.9 + *
    3.10 + * SourcePawn is free software: you can redistribute it and/or modify it under
    3.11 + * the terms of the GNU General Public License as published by the Free
    3.12 + * Software Foundation, either version 3 of the License, or (at your option)
    3.13 + * any later version.
    3.14 + * 
    3.15 + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
    3.16 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    3.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    3.18 + *
    3.19 + * You should have received a copy of the GNU General Public License along with
    3.20 + * SourcePawn. If not, see http://www.gnu.org/licenses/.
    3.21 + */
    3.22 +#include "Box.h"
    3.23 +#include "Zone.h"
    3.24 +#include "Types.h"
    3.25 +#include "Heap-inl.h"
    3.26 +
    3.27 +using namespace ke;
    3.28 +
    3.29 +Box *Box::New(Zone *zone, Handle<Type> type, int i32, Heap::Tenure tenure)
    3.30 +{
    3.31 +    Local<Box> box(zone, Box::cast(zone->allocate(MapKind_Box, sizeof(Box), tenure)));
    3.32 +    if (!box)
    3.33 +        return NULL;
    3.34 +
    3.35 +    assert(type->pod() == PrimitiveType_Int32);
    3.36 +    box->u.i32 = i32;
    3.37 +    box->type_ = type;
    3.38 +    return box;
    3.39 +}
    3.40 +
    3.41 +Box *
    3.42 +Box::New(Zone *zone, Handle<Type> type, float f, Heap::Tenure tenure)
    3.43 +{
    3.44 +    Local<Box> box(zone, Box::cast(zone->allocate(MapKind_Box, sizeof(Box), tenure)));
    3.45 +    if (!box)
    3.46 +        return NULL;
    3.47 +
    3.48 +    assert(type->pod() == PrimitiveType_Float);
    3.49 +    box->u.f = f;
    3.50 +    box->type_ = type;
    3.51 +    return box;
    3.52 +}
    3.53 +
    3.54 +Box *
    3.55 +Box::New(Zone *zone, Handle<Type> type, Object *obj, Heap::Tenure tenure)
    3.56 +{
    3.57 +    Local<Box> box(zone, Box::cast(zone->allocate(MapKind_Box, sizeof(Box), tenure)));
    3.58 +    if (!box)
    3.59 +        return NULL;
    3.60 +
    3.61 +    assert(type->isTraceable());
    3.62 +    box->u.obj = obj;
    3.63 +    box->type_ = type;
    3.64 +    return box;
    3.65 +}
    3.66 +
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/src/Box.h	Sun Aug 05 21:24:41 2012 -0700
     4.3 @@ -0,0 +1,76 @@
     4.4 +/* vim: set ts=4 sw=4 tw=99 et:
     4.5 + *
     4.6 + * Copyright (C) 2012 David Anderson
     4.7 + *
     4.8 + * This file is part of SourcePawn.
     4.9 + *
    4.10 + * SourcePawn is free software: you can redistribute it and/or modify it under
    4.11 + * the terms of the GNU General Public License as published by the Free
    4.12 + * Software Foundation, either version 3 of the License, or (at your option)
    4.13 + * any later version.
    4.14 + * 
    4.15 + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
    4.16 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    4.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    4.18 + *
    4.19 + * You should have received a copy of the GNU General Public License along with
    4.20 + * SourcePawn. If not, see http://www.gnu.org/licenses/.
    4.21 + */
    4.22 +#ifndef _include_sourcepawn_box_h_
    4.23 +#define _include_sourcepawn_box_h_
    4.24 +
    4.25 +#include "Objects.h"
    4.26 +#include "Handles.h"
    4.27 +#include "Heap.h"
    4.28 +#include "Types.h"
    4.29 +
    4.30 +namespace ke {
    4.31 +
    4.32 +class Type;
    4.33 +
    4.34 +class Box : public Object
    4.35 +{
    4.36 +    Barriered<Type> type_;
    4.37 +    union {
    4.38 +        Object *obj;
    4.39 +        float f;
    4.40 +        int i32;
    4.41 +    } u;
    4.42 +
    4.43 +  public:
    4.44 +    static Box *New(Zone *zone, Handle<Type> type, int i32, Heap::Tenure = Heap::Tenure_Default);
    4.45 +    static Box *New(Zone *zone, Handle<Type> type, float f, Heap::Tenure = Heap::Tenure_Default);
    4.46 +    static Box *New(Zone *zone, Handle<Type> type, Object *obj, Heap::Tenure = Heap::Tenure_Default);
    4.47 +
    4.48 +    Type *type() {
    4.49 +        return type_;
    4.50 +    }
    4.51 +
    4.52 +    int toInt32() {
    4.53 +        assert(type()->pod() == PrimitiveType_Int32);
    4.54 +        return u.i32;
    4.55 +    }
    4.56 +    float toFloat() {
    4.57 +        assert(type()->pod() == PrimitiveType_Float);
    4.58 +        return u.f;
    4.59 +    }
    4.60 +
    4.61 +    // Begin GC descriptor.
    4.62 +    static inline size_t offsetOfType() {
    4.63 +        return OFFSETOF(Box, type_);
    4.64 +    }
    4.65 +    static inline size_t offsetOfObj() {
    4.66 +        return OFFSETOF(Box, u.obj);
    4.67 +    }
    4.68 +    // End GC descriptor.
    4.69 +    
    4.70 +    static inline Box *cast(Object *obj) {
    4.71 +        assert(!obj || obj->is(MapKind_Box));
    4.72 +        return reinterpret_cast<Box *>(obj);
    4.73 +    }
    4.74 +};
    4.75 +
    4.76 +}
    4.77 +
    4.78 +#endif // _include_sourcepawn_box_h_
    4.79 +
     5.1 --- a/src/BytecodeCompiler.cpp	Sun Aug 05 15:38:52 2012 -0700
     5.2 +++ b/src/BytecodeCompiler.cpp	Sun Aug 05 21:24:41 2012 -0700
     5.3 @@ -25,6 +25,7 @@
     5.4  #include "Strings.h"
     5.5  #include "Zone.h"
     5.6  #include "Environments.h"
     5.7 +#include "Box.h"
     5.8  #include "Heap-inl.h"
     5.9  
    5.10  using namespace ke;
    5.11 @@ -839,9 +840,12 @@
    5.12          native = node->callee()->toNameProxy()->binding()->toNamedFunction();
    5.13      }
    5.14  
    5.15 +    Local<Type> given(zone_);
    5.16      for (size_t i = node->arguments()->length() - 1; i < node->arguments()->length(); i--) {
    5.17          Expression *arg = node->arguments()->at(i);
    5.18  
    5.19 +        given = arg->type();
    5.20 +
    5.21          // We need to compute a reference if the parameter was in the form:
    5.22          //  f(&a)
    5.23          // Note this form does not allow: f({})
    5.24 @@ -849,7 +853,6 @@
    5.25          // We also need to compute references for all variadic native
    5.26          // arguments, but arrays and references are already in the
    5.27          // appropriate form.
    5.28 -        Local<Type> given(zone_, arg->type());
    5.29          bool mustPushReference = false;
    5.30          if (i >= funType->parameters()->length()) {
    5.31              assert(funType->isNative() && funType->isNativeVariadic());
    5.32 @@ -892,14 +895,41 @@
    5.33          }
    5.34      }
    5.35  
    5.36 +    unsigned argc = node->arguments()->length();
    5.37 +
    5.38 +    // If there are missing arguments, then we're not done and have to push
    5.39 +    // default parameters.
    5.40 +    Local<Box> box(zone_);
    5.41 +    for (size_t i = node->arguments()->length(); i < funType->parameters()->length(); i++) {
    5.42 +        box = Box::cast(funType->defaults()->at(i));
    5.43 +
    5.44 +        if (box->type()->isPod()) {
    5.45 +            if (box->type()->pod() == PrimitiveType_Int32)
    5.46 +                __ int_(box->toInt32());
    5.47 +            else if (box->type()->pod() == PrimitiveType_Float)
    5.48 +                __ float_(box->toFloat());
    5.49 +            else
    5.50 +                assert(false);
    5.51 +        } else {
    5.52 +            assert(false);
    5.53 +        }
    5.54 +
    5.55 +        if (funType->parameterAt(i)->isReference()) {
    5.56 +            __ note_position(node->pos());
    5.57 +            __ slotref_lifo();
    5.58 +        }
    5.59 +
    5.60 +        argc++;
    5.61 +    }
    5.62 +
    5.63      __ note_position(node->pos());
    5.64      if (native) {
    5.65 -        __ callnative(native->slot(), node->arguments()->length());
    5.66 -        __ drop(node->arguments()->length());
    5.67 +        __ callnative(native->slot(), argc);
    5.68 +        __ drop(argc);
    5.69      } else {
    5.70          node->callee()->accept(this);
    5.71          __ call(funType);
    5.72 -        __ drop(node->arguments()->length() + 1);
    5.73 +        __ drop(argc + 1);
    5.74      }
    5.75  }
    5.76  
     6.1 --- a/src/Messages.tbl	Sun Aug 05 15:38:52 2012 -0700
     6.2 +++ b/src/Messages.tbl	Sun Aug 05 21:24:41 2012 -0700
     6.3 @@ -66,4 +66,5 @@
     6.4  MSG(IdentifierIsNotAType,           SyntaxError,            "identifier '%s' cannot be used as a type")
     6.5  MSG(TypeMismatch,                   TypeError,              "type mismatch (expected '%s', got '%s')")
     6.6  MSG(PropertyNotFound,               TypeError,              "property '%s' not found on type '%s'")
     6.7 +MSG(MustBeConstant,                 SyntaxError,            "default value must be a constant")
     6.8  
     7.1 --- a/src/ObjectVisitor.h	Sun Aug 05 15:38:52 2012 -0700
     7.2 +++ b/src/ObjectVisitor.h	Sun Aug 05 21:24:41 2012 -0700
     7.3 @@ -30,6 +30,7 @@
     7.4  #include "Strings.h"
     7.5  #include "Environments.h"
     7.6  #include "Structures.h"
     7.7 +#include "Box.h"
     7.8  
     7.9  namespace ke {
    7.10  
    7.11 @@ -50,6 +51,8 @@
    7.12          visitField(obj, Type::offsetOfParameters());
    7.13          visitField(obj, Type::offsetOfName());
    7.14          visitField(obj, Type::offsetOfFields());
    7.15 +        visitField(obj, Type::offsetOfDefaults());
    7.16 +        visitField(obj, Type::offsetOfNewMap());
    7.17          return sizeof(Type);
    7.18      }
    7.19  
    7.20 @@ -124,6 +127,13 @@
    7.21          return Array::SizeOf(array);
    7.22      }
    7.23  
    7.24 +    size_t iterateBox(Box *obj) {
    7.25 +        visitField(obj, Box::offsetOfType());
    7.26 +        if (obj->type()->isTraceable())
    7.27 +            visitField(obj, Box::offsetOfObj());
    7.28 +        return sizeof(Box);
    7.29 +    }
    7.30 +
    7.31      size_t iterateArrayMap(ArrayMap *map) {
    7.32          visitField(map, ArrayMap::offsetOfType());
    7.33          return sizeof(ArrayMap);
    7.34 @@ -204,6 +214,9 @@
    7.35            case MapKind_Array:
    7.36              return Align(iterateArray(Array::cast(obj), ArrayMap::cast(map)), kObjectAlignment);
    7.37  
    7.38 +          case MapKind_Box:
    7.39 +            return iterateBox(Box::cast(obj));
    7.40 +
    7.41            case MapKind_Struct:
    7.42              return iterateStruct(Struct::cast(obj));
    7.43  
    7.44 @@ -278,6 +291,9 @@
    7.45        case MapKind_Array:
    7.46          return Align(Array::SizeOf(Array::cast(obj)), kObjectAlignment);
    7.47  
    7.48 +      case MapKind_Box:
    7.49 +        return sizeof(Box);
    7.50 +
    7.51        case MapKind_Struct:
    7.52          return Struct::cast(obj)->objSize();
    7.53  
     8.1 --- a/src/Objects.h	Sun Aug 05 15:38:52 2012 -0700
     8.2 +++ b/src/Objects.h	Sun Aug 05 21:24:41 2012 -0700
     8.3 @@ -51,6 +51,7 @@
     8.4      MapKind_EnvironmentSlotDescriptorArray,
     8.5      MapKind_Environment,
     8.6      MapKind_Descriptor,
     8.7 +    MapKind_Box,
     8.8  
     8.9      // These do not have canonical maps.
    8.10      MapKind_Array,
     9.1 --- a/src/Reference.cpp	Sun Aug 05 15:38:52 2012 -0700
     9.2 +++ b/src/Reference.cpp	Sun Aug 05 21:24:41 2012 -0700
     9.3 @@ -1,19 +1,20 @@
     9.4 -/*
     9.5 +/* vim: set ts=4 sw=4 tw=99 et:
     9.6 + *
     9.7   * Copyright (C) 2012 David Anderson
     9.8   *
     9.9 - * This file is part of JITCraft.
    9.10 + * This file is part of SourcePawn.
    9.11   *
    9.12 - * JITCraft is free software: you can redistribute it and/or modify it under
    9.13 + * SourcePawn is free software: you can redistribute it and/or modify it under
    9.14   * the terms of the GNU General Public License as published by the Free
    9.15   * Software Foundation, either version 3 of the License, or (at your option)
    9.16   * any later version.
    9.17   * 
    9.18 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    9.19 + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
    9.20   * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    9.21   * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    9.22   *
    9.23   * You should have received a copy of the GNU General Public License along with
    9.24 - * JITCraft. If not, see http://www.gnu.org/licenses/.
    9.25 + * SourcePawn. If not, see http://www.gnu.org/licenses/.
    9.26   */
    9.27  #include "Reference.h"
    9.28  #include "Zone.h"
    10.1 --- a/src/SemanticAnalysis.cpp	Sun Aug 05 15:38:52 2012 -0700
    10.2 +++ b/src/SemanticAnalysis.cpp	Sun Aug 05 21:24:41 2012 -0700
    10.3 @@ -23,8 +23,9 @@
    10.4  #include "TypeManager.h"
    10.5  #include "Scopes.h"
    10.6  #include "NameBinding.h"
    10.7 +#include "Strings.h"
    10.8 +#include "Box.h"
    10.9  #include "Heap-inl.h"
   10.10 -#include "Strings.h"
   10.11  
   10.12  using namespace ke;
   10.13  
   10.14 @@ -111,6 +112,10 @@
   10.15          return true;
   10.16        }
   10.17  
   10.18 +      case AstNode::kBooleanLiteral:
   10.19 +        *out = BoxedPrimitive::Bool(expression->toBooleanLiteral()->token() == TOK_TRUE);
   10.20 +        return true;
   10.21 +
   10.22        case AstNode::kIntegerLiteral:
   10.23          *out = BoxedPrimitive::Int(expression->toIntegerLiteral()->value());
   10.24          return true;
   10.25 @@ -475,7 +480,7 @@
   10.26              return;
   10.27      }
   10.28  
   10.29 -    if (!typeCheckAssignment(node, exprType, type, true))
   10.30 +    if (!typeCheckAssignment(node->pos(), exprType, type, true))
   10.31          return;
   10.32  
   10.33      node->setType(type);
   10.34 @@ -605,7 +610,7 @@
   10.35          return;
   10.36  
   10.37      Local<Type> returnType(zone_, function_->type()->returnType());
   10.38 -    if (!typeCheckAssignment(node, type, returnType, true))
   10.39 +    if (!typeCheckAssignment(node->pos(), type, returnType, true))
   10.40          return;
   10.41  }
   10.42  
   10.43 @@ -800,7 +805,7 @@
   10.44              Local<Type> right(zone_, visitForLoad(node->initialization()));
   10.45              if (!right)
   10.46                  return;
   10.47 -            if (!typeCheckAssignment(node, type, right, true))
   10.48 +            if (!typeCheckAssignment(node->pos(), type, right, true))
   10.49                  return;
   10.50          }
   10.51  
   10.52 @@ -839,6 +844,25 @@
   10.53      visitAndApplyType(node->expression());
   10.54  }
   10.55  
   10.56 +Box *
   10.57 +SemanticAnalysis::evaluateDefaultParameter(Handle<Type> type, Parameter *parameter)
   10.58 +{
   10.59 +    // First see if we can get a constant expression.
   10.60 +    BoxedPrimitive prim;
   10.61 +    if (EvaluateForConstant(parameter->initializer(), &prim)) {
   10.62 +        Local<Type> given(zone_, zone_->types()->getPrimitive(prim.type()));
   10.63 +        if (!typeCheckAssignment(parameter->initializer()->pos(), given, type, false))
   10.64 +            return NULL;
   10.65 +
   10.66 +        if (prim.type() == PrimitiveType_Int32)
   10.67 +            return Box::New(zone_, type, prim.toInt());
   10.68 +        return Box::New(zone_, type, int(prim.toBool()));
   10.69 +    }
   10.70 +
   10.71 +    cc_.reportError(parameter->initializer()->pos(), Message_MustBeConstant);
   10.72 +    return NULL;
   10.73 +}
   10.74 +
   10.75  bool
   10.76  SemanticAnalysis::preanalyze(FunctionStatement *node)
   10.77  {
   10.78 @@ -846,6 +870,8 @@
   10.79      if (!args)
   10.80          return false;
   10.81  
   10.82 +    Local<FixedArray> defaults(zone_);
   10.83 +
   10.84      // Apply types to arguments.
   10.85      for (size_t i = 0; i < node->parameters()->length(); i++) {
   10.86          Parameter *parameter = node->parameters()->at(i);
   10.87 @@ -854,15 +880,29 @@
   10.88          if (!type)
   10.89              return false;
   10.90  
   10.91 +        if (parameter->initializer()) {
   10.92 +            if (!defaults) {
   10.93 +                defaults = FixedArray::New(zone_, node->parameters()->length(), Heap::Tenure_Old);
   10.94 +                if (!defaults)
   10.95 +                    return false;
   10.96 +            }
   10.97 +
   10.98 +            Local<Box> box(zone_, evaluateDefaultParameter(type, parameter));
   10.99 +            if (!box)
  10.100 +                return false;
  10.101 +
  10.102 +            defaults->set(zone_, i, box);
  10.103 +        }
  10.104 +
  10.105          if (parameter->reference()) {
  10.106              if (parameter->dimensions()) {
  10.107                  cc_.reportError(parameter->variable()->pos(), Message_ArrayCantBeReference);
  10.108 -                return NULL;
  10.109 +                return false;
  10.110              }
  10.111  
  10.112              if (type->isStruct()) {
  10.113                  cc_.reportError(parameter->variable()->pos(), Message_StructCantBeReference);
  10.114 -                return NULL;
  10.115 +                return false;
  10.116              }
  10.117  
  10.118              type = zone_->types()->getReference(type, parameter->isConst());
  10.119 @@ -886,7 +926,7 @@
  10.120                  int size = Type::UNKNOWN_SIZE;
  10.121                  if (Expression *expr = parameter->dimensions()->at(i)) {
  10.122                      BoxedPrimitive box;
  10.123 -                    if (!EvaluateForConstant(expr, &box)) {
  10.124 +                    if (!EvaluateForConstant(expr, &box) || box.type() != PrimitiveType_Int32) {
  10.125                          cc_.reportError(expr->pos(), Message_ArraySizeMustBeConstant);
  10.126                          return false;
  10.127                      }
  10.128 @@ -922,9 +962,9 @@
  10.129  
  10.130      Local<Type> funtype(zone_);
  10.131      if (node->fun()->isNative())
  10.132 -        funtype = zone_->types()->newNative(returnType, args, node->fun()->isNativeVariadic());
  10.133 +        funtype = zone_->types()->newNative(returnType, args, defaults, node->fun()->isNativeVariadic());
  10.134      else
  10.135 -        funtype = zone_->types()->newFunction(returnType, args);
  10.136 +        funtype = zone_->types()->newFunction(returnType, args, defaults);
  10.137      if (!funtype)
  10.138          return false;
  10.139      
  10.140 @@ -968,25 +1008,26 @@
  10.141  }
  10.142  
  10.143  void
  10.144 -SemanticAnalysis::typeMismatch(AstNode *node, Handle<Type> actual, Handle<Type> given)
  10.145 +SemanticAnalysis::typeMismatch(const SourcePosition &pos, Handle<Type> actual, Handle<Type> given)
  10.146  {
  10.147 -    cc_.reportError(node->pos(),Message_TypeMismatch,
  10.148 +    cc_.reportError(pos, Message_TypeMismatch,
  10.149                      GetTypeName(actual),
  10.150                      GetTypeName(given));
  10.151  }
  10.152  
  10.153  bool
  10.154 -SemanticAnalysis::typeCheckArrayAssignment(AstNode *node, Handle<Type> argGiven, Handle<Type> argActual, bool forAssign)
  10.155 +SemanticAnalysis::typeCheckArrayAssignment(const SourcePosition &pos, Handle<Type> argGiven,
  10.156 +                                           Handle<Type> argActual, bool forAssign)
  10.157  {
  10.158      Local<Type> actual(zone_, argActual);
  10.159      Local<Type> given(zone_, argGiven);
  10.160  
  10.161      if (!given->isArray()) {
  10.162 -        cc_.reportError(node->pos(), Message_ExpectedArray);
  10.163 +        cc_.reportError(pos, Message_ExpectedArray);
  10.164          return false;
  10.165      }
  10.166      if (given->levels() != actual->levels()) {
  10.167 -        cc_.reportError(node->pos(), Message_ArrayDimensionsMismatch);
  10.168 +        cc_.reportError(pos, Message_ArrayDimensionsMismatch);
  10.169          return false;
  10.170      }
  10.171  
  10.172 @@ -995,25 +1036,25 @@
  10.173          if (actual->elements() != -1) {
  10.174              if (forAssign) {
  10.175                  if (given->elements() == -1 || actual->elements() == -1) {
  10.176 -                    cc_.reportError(node->pos(), Message_ArraySizeNotKnown);
  10.177 +                    cc_.reportError(pos, Message_ArraySizeNotKnown);
  10.178                      return false;
  10.179                  }
  10.180  
  10.181                  if (actual->isCharArray()) {
  10.182                      // String assignment can have a truncated |given|.
  10.183                      if (given->elements() > actual->elements()) {
  10.184 -                        cc_.reportError(node->pos(), Message_ArrayAssignmentTooBig);
  10.185 +                        cc_.reportError(pos, Message_ArrayAssignmentTooBig);
  10.186                          return false;
  10.187                      }
  10.188                  } else {
  10.189                      if (given->elements() != actual->elements()) {
  10.190 -                        cc_.reportError(node->pos(), Message_ArrayDimensionSizeMismatch, level);
  10.191 +                        cc_.reportError(pos, Message_ArrayDimensionSizeMismatch, level);
  10.192                          return false;
  10.193                      }
  10.194                  }
  10.195              } else {
  10.196                  if (actual->elements() != -1 && given->elements() != actual->elements()) {
  10.197 -                    cc_.reportError(node->pos(), Message_ArrayDimensionSizeMismatch, level);
  10.198 +                    cc_.reportError(pos, Message_ArrayDimensionSizeMismatch, level);
  10.199                      return false;
  10.200                  }
  10.201              }
  10.202 @@ -1022,20 +1063,21 @@
  10.203          actual = actual->contained();
  10.204      }
  10.205  
  10.206 -    return typeCheckAssignment(node, given, actual, forAssign);
  10.207 +    return typeCheckAssignment(pos, given, actual, forAssign);
  10.208  }
  10.209  
  10.210  bool
  10.211 -SemanticAnalysis::typeCheckAssignment(AstNode *node, Handle<Type> argGiven, Handle<Type> argActual, bool forAssign)
  10.212 +SemanticAnalysis::typeCheckAssignment(const SourcePosition &pos, Handle<Type> argGiven,
  10.213 +                                      Handle<Type> argActual, bool forAssign)
  10.214  {
  10.215      Local<Type> actual(zone_, argActual);
  10.216      Local<Type> given(zone_, argGiven);
  10.217  
  10.218      if (actual->isArray())
  10.219 -        return typeCheckArrayAssignment(node, given, actual, forAssign);
  10.220 +        return typeCheckArrayAssignment(pos, given, actual, forAssign);
  10.221  
  10.222      if (given->isArray()) {
  10.223 -        cc_.reportError(node->pos(), Message_CannotAssignArrayToScalar);
  10.224 +        cc_.reportError(pos, Message_CannotAssignArrayToScalar);
  10.225          return false;
  10.226      }
  10.227  
  10.228 @@ -1045,9 +1087,24 @@
  10.229      if (actual->isReference())
  10.230          actual = actual->contained();
  10.231  
  10.232 +    // We coerce unchecked to a few things.
  10.233 +    if (actual->isUnchecked() || given->isUnchecked()) {
  10.234 +        Type *check = actual->isUnchecked() ? given : actual;
  10.235 +        if (check->isUnchecked() ||
  10.236 +            check->isEnum() ||
  10.237 +            check->isInt32() ||
  10.238 +            check->isBool() ||
  10.239 +            check->isFloat())
  10.240 +        {
  10.241 +            return true;
  10.242 +        }
  10.243 +        typeMismatch(pos, actual, given);
  10.244 +        return false;
  10.245 +    }
  10.246 +
  10.247      if (actual->isEnum()) {
  10.248          if (!given->isEnum() || actual != given) {
  10.249 -            typeMismatch(node, actual, given);
  10.250 +            typeMismatch(pos, actual, given);
  10.251              return false;
  10.252          }
  10.253          return true;
  10.254 @@ -1055,19 +1112,23 @@
  10.255  
  10.256      if (actual->isStruct()) {
  10.257          if (!given->isStruct() || actual != given) {
  10.258 -            typeMismatch(node, actual, given);
  10.259 +            typeMismatch(pos, actual, given);
  10.260              return false;
  10.261          }
  10.262          return true;
  10.263      }
  10.264  
  10.265      if (given->isEnum() || given->isFunction() || given->isStruct()) {
  10.266 -        typeMismatch(node, actual, given);
  10.267 +        typeMismatch(pos, actual, given);
  10.268          return false;
  10.269      }
  10.270  
  10.271 +    // This coercion is trivial.
  10.272 +    if (given->isBool() && actual->isInt32())
  10.273 +        return true;
  10.274 +
  10.275      if (given->primitive() != actual->primitive()) {
  10.276 -        typeMismatch(node, actual, given);
  10.277 +        typeMismatch(pos, actual, given);
  10.278          return false;
  10.279      }
  10.280  
  10.281 @@ -1077,7 +1138,32 @@
  10.282  bool
  10.283  SemanticAnalysis::typeCheckParameter(AstNode *node, Handle<Type> given, Handle<Type> actual)
  10.284  {
  10.285 -    return typeCheckAssignment(node, given, actual, false);
  10.286 +    return typeCheckAssignment(node->pos(), given, actual, false);
  10.287 +}
  10.288 +
  10.289 +bool
  10.290 +SemanticAnalysis::checkArgumentCount(Handle<Type> type, unsigned actual)
  10.291 +{
  10.292 +    if (type->parameters()->length() == actual)
  10.293 +        return true;
  10.294 +
  10.295 +    if (actual > type->parameters()->length()) {
  10.296 +        if (!type->isNative() || !type->isNativeVariadic())
  10.297 +            return false;
  10.298 +        return true;
  10.299 +    }
  10.300 +
  10.301 +    if (!type->defaults())
  10.302 +        return false;
  10.303 +
  10.304 +    // Missing arguments. See if there's a default argument for each missing
  10.305 +    // actual.
  10.306 +    for (unsigned i = actual; i < type->parameters()->length(); i++) {
  10.307 +        if (!type->defaults()->at(i))
  10.308 +            return false;
  10.309 +    }
  10.310 +
  10.311 +    return true;
  10.312  }
  10.313  
  10.314  void
  10.315 @@ -1091,14 +1177,10 @@
  10.316          cc_.reportError(node->pos(), Message_CalleeNotFunction);
  10.317          return;
  10.318      }
  10.319 -    if (node->arguments()->length() != type->parameters()->length()) {
  10.320 -        if (!type->isNative() ||
  10.321 -            !type->isNativeVariadic() ||
  10.322 -            node->arguments()->length() < type->parameters()->length())
  10.323 -        {
  10.324 -            cc_.reportError(node->pos(), Message_ArgumentCountMismatch);
  10.325 -            return;
  10.326 -        }
  10.327 +
  10.328 +    if (!checkArgumentCount(type, node->arguments()->length())) {
  10.329 +        cc_.reportError(node->pos(), Message_ArgumentCountMismatch);
  10.330 +        return;
  10.331      }
  10.332  
  10.333      // Currently, only calls from a NameProxy are possible.
  10.334 @@ -1261,7 +1343,7 @@
  10.335          BoxedPrimitive box = BoxedPrimitive::Int(value);
  10.336          if (entry.expr) {
  10.337              entry.expr->accept(this);
  10.338 -            if (!EvaluateForConstant(entry.expr, &box)) {
  10.339 +            if (!EvaluateForConstant(entry.expr, &box) || box.type() != PrimitiveType_Int32) {
  10.340                  cc_.reportError(entry.expr->pos(), Message_EnumFieldNotConstant);
  10.341                  return;
  10.342              }
    11.1 --- a/src/SemanticAnalysis.h	Sun Aug 05 15:38:52 2012 -0700
    11.2 +++ b/src/SemanticAnalysis.h	Sun Aug 05 21:24:41 2012 -0700
    11.3 @@ -24,6 +24,8 @@
    11.4  
    11.5  namespace ke {
    11.6  
    11.7 +class Box;
    11.8 +
    11.9  class SemanticAnalysis : public AstVisitor
   11.10  {
   11.11      Zone *zone_;
   11.12 @@ -148,7 +150,7 @@
   11.13  
   11.14    private:
   11.15      bool canTest(AstNode *node, Handle<Type> type);
   11.16 -    void typeMismatch(AstNode *node, Handle<Type> actual, Handle<Type> given);
   11.17 +    void typeMismatch(const SourcePosition &pos, Handle<Type> actual, Handle<Type> given);
   11.18      void unaryTypeError(AstNode *node, TokenKind token, Handle<Type> type);
   11.19      void binaryTypeError(AstNode *node, TokenKind token, Handle<Type> left, Handle<Type> right);
   11.20      Type *typeCheckBinary(AstNode *node, TokenKind token, Handle<Type> left, Handle<Type> right);
   11.21 @@ -161,8 +163,8 @@
   11.22      //      call(a, b)    matches expected arg type
   11.23      //      a = b         matches declared type
   11.24      //
   11.25 -    bool typeCheckArrayAssignment(AstNode *node, Handle<Type> given, Handle<Type> actual, bool forAssign);
   11.26 -    bool typeCheckAssignment(AstNode *node, Handle<Type> given, Handle<Type> actual, bool forAssign);
   11.27 +    bool typeCheckArrayAssignment(const SourcePosition &pos, Handle<Type> given, Handle<Type> actual, bool forAssign);
   11.28 +    bool typeCheckAssignment(const SourcePosition &pos, Handle<Type> given, Handle<Type> actual, bool forAssign);
   11.29      bool typeCheckParameter(AstNode *node, Handle<Type> given, Handle<Type> actual);
   11.30  
   11.31      Type *visitForLoad(Expression *expression);
   11.32 @@ -171,6 +173,9 @@
   11.33      Type *visitAndApplyType(Expression *expression);
   11.34      ControlStatus visitForControl(Statement *statement);
   11.35  
   11.36 +    Box *evaluateDefaultParameter(Handle<Type> type, Parameter *parameter);
   11.37 +    bool checkArgumentCount(Handle<Type> type, unsigned actual);
   11.38 +
   11.39      void markCallResultUsed(CallExpression *call);
   11.40  
   11.41      bool determineLiveFunctions();
    12.1 --- a/src/TypeManager.cpp	Sun Aug 05 15:38:52 2012 -0700
    12.2 +++ b/src/TypeManager.cpp	Sun Aug 05 21:24:41 2012 -0700
    12.3 @@ -82,17 +82,19 @@
    12.4  }
    12.5  
    12.6  Type *
    12.7 -TypeManager::newFunction(Handle<Type> returnType, Handle<FixedArray> args)
    12.8 +TypeManager::newFunction(Handle<Type> returnType, Handle<FixedArray> args,
    12.9 +                         Handle<FixedArray> defaults)
   12.10  {
   12.11      // :TODO: cache this.
   12.12 -    return Type::NewFunction(zone_, returnType, args);
   12.13 +    return Type::NewFunction(zone_, returnType, args, defaults);
   12.14  }
   12.15  
   12.16  Type *
   12.17 -TypeManager::newNative(Handle<Type> returnType, Handle<FixedArray> args, bool variadic)
   12.18 +TypeManager::newNative(Handle<Type> returnType, Handle<FixedArray> args,
   12.19 +                       Handle<FixedArray> defaults, bool variadic)
   12.20  {
   12.21      // :TODO: cache this.
   12.22 -    return Type::NewNative(zone_, returnType, args, variadic);
   12.23 +    return Type::NewNative(zone_, returnType, args, defaults, variadic);
   12.24  }
   12.25  
   12.26  Type *
    13.1 --- a/src/TypeManager.h	Sun Aug 05 15:38:52 2012 -0700
    13.2 +++ b/src/TypeManager.h	Sun Aug 05 21:24:41 2012 -0700
    13.3 @@ -55,8 +55,10 @@
    13.4      Type *getReference(Handle<Type> type, bool isConst);
    13.5      Type *unsafeArray(Handle<Type> contained, int elements, bool isConst);
    13.6      Type *newEnum(Handle<String> name);
    13.7 -    Type *newFunction(Handle<Type> returnType, Handle<FixedArray> args);
    13.8 -    Type *newNative(Handle<Type> returnType, Handle<FixedArray> args, bool variadic);
    13.9 +    Type *newFunction(Handle<Type> returnType, Handle<FixedArray> args,
   13.10 +                      Handle<FixedArray> deafults);
   13.11 +    Type *newNative(Handle<Type> returnType, Handle<FixedArray> args,
   13.12 +                    Handle<FixedArray> defaults, bool variadic);
   13.13      Type *newStruct(Handle<String> name, Handle<FixedArray> fields, Handle<Map> newMap);
   13.14      
   13.15      void accept(VirtualObjectVisitor *visitor);
    14.1 --- a/src/Types.cpp	Sun Aug 05 15:38:52 2012 -0700
    14.2 +++ b/src/Types.cpp	Sun Aug 05 21:24:41 2012 -0700
    14.3 @@ -36,6 +36,7 @@
    14.4      type->contained_ = NULL;
    14.5      type->returnType_ = NULL;
    14.6      type->parameters_ = NULL;
    14.7 +    type->defaults_ = NULL;
    14.8      type->fields_ = NULL;
    14.9      type->newMap_ = NULL;
   14.10      return type;
   14.11 @@ -52,6 +53,7 @@
   14.12      type->contained_ = NULL;
   14.13      type->returnType_ = NULL;
   14.14      type->parameters_ = NULL;
   14.15 +    type->defaults_ = NULL;
   14.16      type->fields_ = NULL;
   14.17      type->newMap_ = NULL;
   14.18      return type;
   14.19 @@ -69,6 +71,7 @@
   14.20      type->contained_ = NULL;
   14.21      type->returnType_ = NULL;
   14.22      type->parameters_ = NULL;
   14.23 +    type->defaults_ = NULL;
   14.24      type->fields_ = NULL;
   14.25      type->newMap_ = NULL;
   14.26      type->newMap_ = NULL;
   14.27 @@ -88,6 +91,7 @@
   14.28      type->contained_ = contained;
   14.29      type->returnType_ = NULL;
   14.30      type->parameters_ = NULL;
   14.31 +    type->defaults_ = NULL;
   14.32      type->fields_ = NULL;
   14.33      type->newMap_ = NULL;
   14.34      type->elements_ = elements;
   14.35 @@ -111,6 +115,7 @@
   14.36      type->contained_ = contained;
   14.37      type->returnType_ = NULL;
   14.38      type->parameters_ = NULL;
   14.39 +    type->defaults_ = NULL;
   14.40      type->fields_ = NULL;
   14.41      type->newMap_ = NULL;
   14.42      type->const_ = isConst;
   14.43 @@ -118,7 +123,8 @@
   14.44  }
   14.45  
   14.46  Type *
   14.47 -Type::NewFunction(Zone *zone, Handle<Type> returnType, Handle<FixedArray> parameters)
   14.48 +Type::NewFunction(Zone *zone, Handle<Type> returnType, Handle<FixedArray> parameters,
   14.49 +                  Handle<FixedArray> defaults)
   14.50  {
   14.51      Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
   14.52      if (!type)
   14.53 @@ -131,6 +137,7 @@
   14.54      type->newMap_ = NULL;
   14.55      type->returnType_ = returnType;
   14.56      type->parameters_ = parameters;
   14.57 +    type->defaults_ = defaults;
   14.58      return type;
   14.59  }
   14.60  
   14.61 @@ -146,6 +153,7 @@
   14.62      type->contained_ = NULL;
   14.63      type->returnType_ = NULL;
   14.64      type->parameters_ = NULL;
   14.65 +    type->defaults_ = NULL;
   14.66      type->fields_ = NULL;
   14.67      type->newMap_ = NULL;
   14.68      return type;
   14.69 @@ -163,13 +171,15 @@
   14.70      type->contained_ = NULL;
   14.71      type->returnType_ = NULL;
   14.72      type->parameters_ = NULL;
   14.73 +    type->defaults_ = NULL;
   14.74      type->newMap_ = newMap;
   14.75      type->fields_ = fields;
   14.76      return type;
   14.77  }
   14.78  
   14.79  Type *
   14.80 -Type::NewNative(Zone *zone, Handle<Type> returnType, Handle<FixedArray> parameters, bool variadic)
   14.81 +Type::NewNative(Zone *zone, Handle<Type> returnType, Handle<FixedArray> parameters,
   14.82 +                Handle<FixedArray> defaults, bool variadic)
   14.83  {
   14.84      Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
   14.85      if (!type)
   14.86 @@ -182,6 +192,7 @@
   14.87      type->newMap_ = NULL;
   14.88      type->returnType_ = returnType;
   14.89      type->parameters_ = parameters;
   14.90 +    type->defaults_ = defaults;
   14.91      type->variadicNative_ = variadic;
   14.92      return type;
   14.93  }
    15.1 --- a/src/Types.h	Sun Aug 05 15:38:52 2012 -0700
    15.2 +++ b/src/Types.h	Sun Aug 05 21:24:41 2012 -0700
    15.3 @@ -105,8 +105,10 @@
    15.4      static Type *NewPrimitive(Zone *zone, PrimitiveType type);
    15.5      static Type *NewArray(Zone *zone, Handle<Type> contained, int elements, bool isConst);
    15.6      static Type *NewReference(Zone *zone, Handle<Type> contained, bool isConst);
    15.7 -    static Type *NewFunction(Zone *zone, Handle<Type> returnType, Handle<FixedArray> parameters);
    15.8 -    static Type *NewNative(Zone *zone, Handle<Type> returnType, Handle<FixedArray> parameters, bool isVariadic);
    15.9 +    static Type *NewFunction(Zone *zone, Handle<Type> returnType, Handle<FixedArray> parameters,
   15.10 +                             Handle<FixedArray> defaults);
   15.11 +    static Type *NewNative(Zone *zone, Handle<Type> returnType, Handle<FixedArray> parameters,
   15.12 +                           Handle<FixedArray> defaults, bool isVariadic);
   15.13      static Type *NewEnum(Zone *zone, Handle<String> name);
   15.14      static Type *NewStruct(Zone *zone, Handle<String> name, Handle<FixedArray> fields, Handle<Map> newMap);
   15.15  
   15.16 @@ -149,8 +151,11 @@
   15.17          assert(isPrimitive());
   15.18          return primitive_;
   15.19      }
   15.20 +    bool isPod() {
   15.21 +        return isPrimitive() || isEnum() || isUnchecked();
   15.22 +    }
   15.23      PrimitiveType pod() {
   15.24 -        assert(isPrimitive() || isEnum());
   15.25 +        assert(isPod());
   15.26          return isPrimitive()
   15.27                 ? (primitive() == PrimitiveType_Bool)
   15.28                   ? PrimitiveType_Int32
   15.29 @@ -201,6 +206,10 @@
   15.30          assert(isFunction());
   15.31          return parameters_;
   15.32      }
   15.33 +    FixedArray *defaults() {
   15.34 +        assert(isFunction());
   15.35 +        return defaults_;
   15.36 +    }
   15.37      Type *parameterAt(size_t i) {
   15.38          return Type::cast(parameters()->at(i));
   15.39      }
   15.40 @@ -254,6 +263,9 @@
   15.41      static inline size_t offsetOfNewMap() {
   15.42          return OFFSETOF(Type, newMap_);
   15.43      }
   15.44 +    static inline size_t offsetOfDefaults() {
   15.45 +        return OFFSETOF(Type, defaults_);
   15.46 +    }
   15.47      // End GC Descriptor.
   15.48  
   15.49    private:
   15.50 @@ -273,6 +285,7 @@
   15.51      // Functions only.
   15.52      Barriered<Type> returnType_;
   15.53      Barriered<FixedArray> parameters_;
   15.54 +    Barriered<FixedArray> defaults_;
   15.55      bool variadicNative_;
   15.56  
   15.57      // Enums and structs only.
   15.58 @@ -288,6 +301,7 @@
   15.59      PrimitiveType type_;
   15.60      union {
   15.61          int i_;
   15.62 +        bool b_;
   15.63      };
   15.64  
   15.65    public:
   15.66 @@ -297,6 +311,12 @@
   15.67          b.i_ = i;
   15.68          return b;
   15.69      }
   15.70 +    static BoxedPrimitive Bool(bool v) {
   15.71 +        BoxedPrimitive b;
   15.72 +        b.type_ = PrimitiveType_Bool;
   15.73 +        b.b_ = v;
   15.74 +        return b;
   15.75 +    }
   15.76  
   15.77      PrimitiveType type() const {
   15.78          return type_;
   15.79 @@ -305,6 +325,10 @@
   15.80          assert(type() == PrimitiveType_Int32);
   15.81          return i_;
   15.82      }
   15.83 +    bool toBool() const {
   15.84 +        assert(type() == PrimitiveType_Bool);
   15.85 +        return b_;
   15.86 +    }
   15.87  };
   15.88  
   15.89  }
    16.1 --- a/src/Zone.cpp	Sun Aug 05 15:38:52 2012 -0700
    16.2 +++ b/src/Zone.cpp	Sun Aug 05 21:24:41 2012 -0700
    16.3 @@ -92,6 +92,8 @@
    16.4          return false;
    16.5      if ((maps_[MapKind_Descriptor] = allocateMap(MapKind_Descriptor, sizeof(Map))) == NULL)
    16.6          return false;
    16.7 +    if ((maps_[MapKind_Box] = allocateMap(MapKind_Box, sizeof(Map))) == NULL)
    16.8 +        return false;
    16.9      if ((maps_[MapKind_FreeRegion] = allocateMap(MapKind_FreeRegion, sizeof(Map))) == NULL)
   16.10          return false;
   16.11      if ((maps_[MapKind_EnvironmentSlotDescriptorArray] =