Added runtime support for default arguments.
Added runtime support for default arguments.
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] =