Add support for SP1-style fixed array initializers.
1 /* vim: set ts=4 sw=4 tw=99 et:
3 * Copyright (C) 2012 David Anderson
5 * This file is part of JITCraft.
7 * JITCraft is free software: you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License as published by the Free
9 * Software Foundation, either version 3 of the License, or (at your option)
12 * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
13 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along with
17 * JITCraft. If not, see http://www.gnu.org/licenses/.
20 #include "SemanticAnalysis.h"
23 #include "TypeManager.h"
25 #include "NameBinding.h"
34 IsPrimitiveType(Type *type, PrimitiveType primitive)
39 if (!type->isPrimitive())
42 return primitive == type->primitive();
46 EvaluateBinaryOperation(TokenKind kind, const BoxedPrimitive &left, const BoxedPrimitive &right,
51 *out = BoxedPrimitive::Int(left.toInt() + right.toInt());
55 *out = BoxedPrimitive::Int(left.toInt() << right.toInt());
64 EvaluateUnaryOperation(TokenKind kind, const BoxedPrimitive &inner, BoxedPrimitive *out)
68 *out = BoxedPrimitive::Int(-inner.toInt());
77 EvaluateForConstant(Expression *expression, BoxedPrimitive *out)
79 switch (expression->kind()) {
80 case AstNode::kBinaryExpression:
84 BinaryExpression *b = expression->toBinaryExpression();
85 if (!EvaluateForConstant(b->left(), &left) ||
86 !EvaluateForConstant(b->right(), &right))
90 return EvaluateBinaryOperation(b->token(), left, right, out);
93 case AstNode::kUnaryExpression:
96 UnaryExpression *u = expression->toUnaryExpression();
97 if (!EvaluateForConstant(u->expression(), &inner))
99 return EvaluateUnaryOperation(u->token(), inner, out);
102 case AstNode::kNameProxy:
104 NameProxy *proxy = expression->toNameProxy();
105 if (proxy->binding()->kind() != BoundName::CONSTANT)
108 NamedConstant *c = proxy->binding()->toNamedConstant();
109 if (!IsPrimitiveType(c->type(), PrimitiveType_Int32))
116 case AstNode::kBooleanLiteral:
117 *out = BoxedPrimitive::Int(expression->toBooleanLiteral()->token() == TOK_TRUE ? 1 : 0);
120 case AstNode::kIntegerLiteral:
121 *out = BoxedPrimitive::Int(expression->toIntegerLiteral()->value());
129 SemanticAnalysis::SemanticAnalysis(Zone *zone, CompileContext &cc, ParseTree *tree)
139 SemanticAnalysis::analyze()
144 scope_ = tree_->scope();
146 for (size_t i = 0; i < tree_->statements()->length(); i++) {
147 Statement *statement = tree_->statements()->at(i);
148 if (statement->isFunctionStatement()) {
149 FunctionStatement *funstmt = statement->toFunctionStatement();
150 if (!preanalyze(funstmt))
152 } else if (statement->isEnumStatement()) {
153 EnumStatement *enumstmt = statement->toEnumStatement();
155 // We pre-fill global enum types, since they may occur in function
156 // signatures. This should probably be somewhere else...
157 enumstmt->accept(this);
158 } else if (statement->isStructureStatement()) {
159 StructureStatement *node = statement->toStructureStatement();
161 if (!node->decl()->type())
163 } else if (statement->isFunctionTypeStatement()) {
164 FunctionTypeStatement *node = statement->toFunctionTypeStatement();
166 if (!node->decl()->type())
171 for (size_t i = 0; i < tree_->statements()->length(); i++) {
172 Statement *statement = tree_->statements()->at(i);
174 // We can't double-process these. Maybe put this check somewhere else.
175 if (statement->isEnumStatement())
178 statement->accept(this);
181 if (!determineLiveFunctions())
184 return !cc_.failures();
188 SemanticAnalysis::determineLiveFunctions()
190 Vector<NamedFunction *> worklist;
193 for (size_t i = 0; i < tree_->statements()->length(); i++) {
194 Statement *statement = tree_->statements()->at(i);
195 if (!statement->isFunctionStatement())
198 FunctionStatement *stmt = statement->toFunctionStatement();
199 NamedFunction *fun = stmt->fun();
203 for (size_t i = 0; i < fun->usedGlobals()->length(); i++) {
204 NamedFunction *name = fun->usedGlobals()->at(i)->toNamedFunction();
206 // Names in these lists are always unused, however, we mark them
207 // as used while inserting into the work queue, to avoid double-
212 if (!worklist.append(name))
219 while (!worklist.empty()) {
220 NamedFunction *fun = worklist.popCopy();
222 for (size_t i = 0; i < fun->usedGlobals()->length(); i++) {
223 NamedFunction *name = fun->usedGlobals()->at(i)->toNamedFunction();
226 if (!worklist.append(name))
236 SemanticAnalysis::bindType(const SourcePosition &pos, BoundName *name)
239 return zone_->types()->getPrimitive(PrimitiveType_Int32);
241 if (name->kind() == BoundName::UNBOUND) {
242 cc_.reportError(pos, Message_TypeNotFound, name->name()->chars());
246 if (name->kind() != BoundName::TYPE) {
247 cc_.reportError(pos, Message_IdentifierIsNotAType, name->name()->chars());
258 SemanticAnalysis::visitAndApplyType(Expression *expression)
260 expression->accept(this);
261 return expression->type();
265 SemanticAnalysis::visitForLoad(Expression *expression)
267 Local<Type> type(zone_, visitAndApplyType(expression));
271 if (type->isReference()) {
272 expression->setType(type->contained());
273 } else if (expression->isCallExpression()) {
274 if (type->isVoid()) {
275 CallExpression *call = expression->toCallExpression();
276 cc_.reportError(call->callee()->pos(), Message_FunctionDoesNotReturnValue);
281 return expression->type();
284 // :TODO: this leaks an interior pointer.
286 ke::GetTypeName(Type *type)
290 if (type->isFunction())
294 if (type->isEnum() || type->isStruct())
295 return type->name()->chars();
296 if (type->isReference())
297 type = type->contained();
298 switch (type->primitive()) {
299 case PrimitiveType_Bool:
301 case PrimitiveType_Char:
303 case PrimitiveType_Int32:
305 case PrimitiveType_Float:
313 SemanticAnalysis::unaryTypeError(AstNode *node, TokenKind token, Handle<Type> type)
315 const char *op = TokenNames[token];
316 const char *name = GetTypeName(type);
318 cc_.reportError(node->pos(), Message_UnaryTypeError, op, name);
322 SemanticAnalysis::binaryTypeError(AstNode *node, TokenKind token, Handle<Type> left, Handle<Type> right)
324 const char *op = TokenNames[token];
325 const char *leftName = GetTypeName(left);
326 const char *rightName = GetTypeName(right);
328 cc_.reportError(node->pos(), Message_BinaryTypeError, op, leftName, rightName);
332 SemanticAnalysis::typeCheckBinary(AstNode *node, TokenKind token, Handle<Type> left, Handle<Type> right)
334 if ((token >= TOK_PLUS && token <= TOK_SLASH) ||
335 (token >= TOK_ASSIGN_ADD && token <= TOK_ASSIGN_DIV))
337 // If either side is a float, the other side must be a float or int.
338 if (left->isFloat() || right->isFloat()) {
339 Type *floatType = left->isFloat() ? left : right;
340 Type *other = left->isFloat() ? right : left;
341 if (other->isFloat() || other->isInt32())
346 if (token == TOK_OR || token == TOK_AND) {
347 if (!canTest(node, left) || !canTest(node, right))
349 return zone_->types()->getPrimitive(PrimitiveType_Bool);
352 if (token >= TOK_EQUALS && token <= TOK_GE) {
353 if ((left->isFloat() || left->isInt32()) &&
354 (right->isFloat() || right->isInt32()))
356 return zone_->types()->getPrimitive(PrimitiveType_Bool);
358 binaryTypeError(node, token, left, right);
362 if (!left->isInt32() || !right->isInt32()) {
363 binaryTypeError(node, token, left, right);
371 SemanticAnalysis::canTest(AstNode *node, Handle<Type> type)
373 if (!type->isPrimitive() && !type->isEnum()) {
374 cc_.reportError(node->pos(), Message_ArrayIsNotBoolean);
381 SemanticAnalysis::visitForLValue(Expression *expression)
383 if (expression->isIndexExpression()) {
384 Type *type = visitAndApplyType(expression);
388 // if (type->isConst()) {
389 // cc_.reportError(expression->pos(), Message_ReferenceIsConstant);
396 if (expression->isFieldExpression()) {
397 Type *type = visitAndApplyType(expression);
401 // if (expression->toFieldExpression()->left()->type()->isConst()) {
402 // cc_.reportError(expression->pos(), Message_ReferenceIsConstant);
409 if (!expression->isNameProxy()) {
410 cc_.reportError(expression->pos(), Message_ExpectedLValue);
414 NameProxy *proxy = expression->toNameProxy();
415 if (!proxy->binding()->kind() == BoundName::VARIABLE) {
416 cc_.reportError(expression->pos(), Message_ExpectedLValue);
420 Variable *var = proxy->binding()->toVariable();
424 if (var->type()->isReference()) {
425 if (var->type()->isConst()) {
426 cc_.reportError(expression->pos(), Message_ReferenceIsConstant);
429 return var->type()->contained();
434 SemanticAnalysis::ControlStatus
435 SemanticAnalysis::visitForControl(Statement *statement)
437 ControlScope scope(&control_);
438 statement->accept(this);
439 return scope.status();
443 SemanticAnalysis::visit(NameProxy *name)
445 BoundName *binding = name->binding();
447 if (binding->scope()->kind() == Scope::GLOBAL) {
448 if (!function_ || function_->isPublic()) {
449 // Whatever we're referencing must be kept alive no matter what.
450 // As such, we simply mark it used, and don't do anything special.
452 } else if (!binding->used() && binding->kind() == BoundName::FUNCTION) {
453 // Otherwise, we're inside a normal stock or function. Since we
454 // don't really know if we've been used yet, we shouldn't
455 // prematurely references as alive. Instead, we keep a list of
456 // which names have been used, so we can mark them later if needed.
458 // Note that we skip this step if the binding is already in the
460 if (!function_->addUsedGlobal(binding))
465 name->setType(binding->type());
469 SemanticAnalysis::visit(Assignment *node)
471 Local<Type> exprType(zone_, visitForLoad(node->expression()));
475 Local<Type> type(zone_, visitForLValue(node->lvalue()));
479 if (node->token() != TOK_ASSIGN) {
480 if (!typeCheckBinary(node, node->token(), type, exprType))
484 if (!typeCheckAssignment(node->pos(), exprType, type, true))
491 SemanticAnalysis::visit(IncDecExpression *node)
493 Local<Type> type(zone_, visitForLValue(node->expression()));
497 assert(!type->isReference());
499 if (!type->isInt32() && !type->isFloat()) {
500 unaryTypeError(node, node->token(), type);
508 SemanticAnalysis::visit(UnaryExpression *node)
510 Local<Type> type(zone_, visitForLoad(node->expression()));
514 switch (node->token())
517 if (!canTest(node->expression(), type))
519 type = zone_->types()->getPrimitive(PrimitiveType_Int32);
526 if (!type->isFloat() && !type->isInt32()) {
527 unaryTypeError(node, node->token(), type);
535 Local<Type> to(zone_, bindType(node->pos(), node->type()));
539 if ((!type->isFloat() && !type->isInt32OrEnum()) ||
540 (!to->isFloat() && !to->isInt32OrEnum()))
542 unaryTypeError(node, node->token(), type);
551 assert(node->token() == TOK_TILDE);
552 if (!type->isInt32()) {
553 unaryTypeError(node, node->token(), type);
562 SemanticAnalysis::visit(TernaryExpression *node)
564 Local<Type> type(zone_, visitForLoad(node->condition()));
568 if (!canTest(node->condition(), type))
571 Local<Type> left(zone_, visitForLoad(node->left()));
572 Local<Type> right(zone_, visitForLoad(node->right()));
577 binaryTypeError(node, TOK_QMARK, left, right);
583 SemanticAnalysis::visit(BinaryExpression *node)
585 Local<Type> left(zone_, visitForLoad(node->left()));
586 Local<Type> right(zone_, visitForLoad(node->right()));
590 Local<Type> result(zone_, typeCheckBinary(node, node->token(), left, right));
594 node->setType(result);
598 SemanticAnalysis::visit(ReturnStatement *node)
600 // Set this early, so if we error we don't get more errors.
601 control_->returns(Returns_Always);
603 if (!node->expression()) {
604 if (!function_->type()->returnType()->isVoid())
605 cc_.reportError(node->pos(), Message_NotAllPathsReturnValue);
609 Local<Type> type(zone_, visitForLoad(node->expression()));
613 Local<Type> returnType(zone_, function_->type()->returnType());
614 if (!typeCheckAssignment(node->pos(), type, returnType, true))
619 SemanticAnalysis::visit(ForStatement *node)
621 LoopScope loop(&loop_);
624 scope_ = node->scope();
626 if (node->initialization())
627 node->initialization()->accept(this);
629 if (node->condition()) {
630 Local<Type> type(zone_, visitForLoad(node->condition()));
631 if (!type || !canTest(node->condition(), type)) {
637 node->update()->accept(this);
639 ControlStatus status = visitForControl(node->body());
641 // If there is a condition, we treat this like a while loop. Otherwise,
642 // join point is only reachable if the loop contains a break. The
643 // termination status doesn't tell us anything yet.
644 if (node->condition() || loop.breaks())
645 control_->merge(status, ControlStatus(false, Returns_Never));
647 control_->terminate(status.returns());
650 scope_ = scope_->enclosing();
654 SemanticAnalysis::visit(WhileStatement *node)
656 LoopScope loop(&loop_);
658 Local<Type> type(zone_, visitForLoad(node->condition()));
659 if (!type || !canTest(node->condition(), type)) {
663 ControlStatus status = visitForControl(node->body());
665 // Detect loops that will always have a fork in the control-flow graph.
666 // This will be a |while| loop, or a |do-while| loop whose body does
669 // For now, we treat these as an |if| regardless of the direction the
670 // branch can take. That means the control-flow is always conditional.
671 if (node->token() == TOK_WHILE ||
672 !status.terminates() ||
675 control_->merge(status, ControlStatus(false, Returns_Never));
677 // At this point, we've got a do-while loop with a |return| or
678 // |continue|, meaning that the rest of the block is unreachable.
679 control_->terminate(status.returns());
684 SemanticAnalysis::visit(BlockStatement *node)
687 scope_ = node->scope();
688 for (size_t i = 0; i < node->statements()->length(); i++) {
689 Statement *statement = node->statements()->at(i);
690 statement->accept(this);
693 scope_ = scope_->enclosing();
697 IsScalarString(Type *type)
699 if (type->isPrimitive() && type->primitive() == PrimitiveType_Char)
701 if (type->isReference())
702 return IsScalarString(type->contained());
706 static const int INFER_ARRAY_SIZE = 0;
707 static const int EVAL_ARRAY_SIZE = -1;
708 static const int DYNAMIC_ARRAY_SIZE = -2;
711 SemanticAnalysis::evaluateDimensions(ExpressionList *exprs, int dims[MAX_ARRAY_DEPTH])
713 for (size_t i = 0; i < exprs->length(); i++) {
714 Expression *expr = exprs->at(i);
716 dims[i] = INFER_ARRAY_SIZE;
721 if (EvaluateForConstant(expr, &box) && box.type() == PrimitiveType_Int32) {
722 int size = box.toInt();
724 cc_.reportError(expr->pos(), Message_BadArraySize);
732 Local<Type> exprType(zone_, visitForLoad(expr));
736 if (!IsPrimitiveType(exprType, PrimitiveType_Int32)) {
737 cc_.reportError(expr->pos(), Message_ArrayDimensionNotInteger);
741 dims[i] = EVAL_ARRAY_SIZE;
748 SemanticAnalysis::inferFixedArrayLiteral(ArrayLiteral *literal, Handle<Type> contained,
749 int dims[MAX_ARRAY_DEPTH],
750 unsigned dimcount, unsigned level)
752 if (dims[level] == EVAL_ARRAY_SIZE) {
753 cc_.reportError(literal->pos(), Message_CannotInitializeEvalArray);
757 if (dims[level] == INFER_ARRAY_SIZE) {
758 // Strings always become dynamic arrays.
759 if (level != dimcount - 1 || !IsPrimitiveType(contained, PrimitiveType_Char))
760 dims[level] = literal->expressions()->length();
761 } else if (dims[level] == DYNAMIC_ARRAY_SIZE) {
762 cc_.reportError(literal->pos(), Message_CannotInitializeEvalArray);
765 if (literal->expressions()->length() != unsigned(dims[level])) {
766 cc_.reportError(literal->pos(), Message_ArrayDimensionSizeMismatch, level + 1);
771 if (level == dimcount - 2 && IsPrimitiveType(contained, PrimitiveType_Char)) {
772 for (size_t i = 0; i < literal->expressions()->length(); i++) {
773 Expression *expr = literal->expressions()->at(i);
774 if (!expr->isStringLiteral()) {
775 cc_.reportError(expr->pos(), Message_ExpectedStringLiteral);
779 StringLiteral *lit = expr->toStringLiteral();
780 if (dims[level + 1] > 0 &&
781 unsigned(dims[level]) < lit->string()->length())
783 cc_.reportError(lit->pos(), Message_ArrayDimensionSizeMismatch, level + 2);
786 if (!visitAndApplyType(lit))
789 } else if (level == dimcount - 1) {
790 Local<Type> type(zone_);
791 for (size_t i = 0; i < literal->expressions()->length(); i++) {
792 Expression *expr = literal->expressions()->at(i);
793 if (expr->isArrayLiteral()) {
794 cc_.reportError(expr->pos(), Message_ArrayDimensionsMismatch);
798 if ((type = visitAndApplyType(expr)) == NULL)
801 if (!typeCheckAssignment(expr->pos(), type, contained, true))
805 for (size_t i = 0; i < literal->expressions()->length(); i++) {
806 Expression *expr = literal->expressions()->at(i);
807 if (!expr->isArrayLiteral()) {
808 cc_.reportError(expr->pos(), Message_ArrayDimensionsMismatch);
812 assert(expr->toArrayLiteral()->isFixed());
814 if (!inferFixedArrayLiteral(expr->toArrayLiteral(),
829 SemanticAnalysis::visit(VariableDeclaration *node)
831 Local<Type> type(zone_, bindType(node->pos(), node->type()));
835 if (node->postDimensions() || type->isArray()) {
836 // The type could be an array type, so sum the type and postDimensions
838 unsigned dimcount = node->postDimensions()->length();
840 dimcount += type->levels();
841 if (dimcount > MAX_ARRAY_DEPTH) {
842 cc_.reportError(node->pos(), Message_MaximumArrayDepth);
846 // Take an initial guess at the array dimension sizes.
847 int dims[MAX_ARRAY_DEPTH];
848 if (!evaluateDimensions(node->postDimensions(), dims))
851 // Now add in the type's array dimensions.
852 Local<Type> contained(zone_, type);
853 for (size_t i = node->postDimensions()->length(); i < dimcount; i++) {
854 if (type->isFixedLength())
855 dims[i] = type->fixedLength();
857 dims[i] = DYNAMIC_ARRAY_SIZE;
858 contained = contained->contained();
861 Expression *initializer = node->initialization();
863 initializer->isArrayLiteral() &&
864 initializer->toArrayLiteral()->isFixed())
866 // Fixed array initializers are special; we use them to infer any
867 // missing information in the original array. We do not evaluate
868 // the array initializer as an expression.
869 if (!inferFixedArrayLiteral(initializer->toArrayLiteral(),
880 // We now have enough information to build the actual array type.
881 // Start from the original dimcount, not the one computed for
883 for (size_t i = node->postDimensions()->length() - 1;
884 i < node->postDimensions()->length();
887 int size = dims[i] > 0
889 : Type::DYNAMIC_ARRAY_SIZE;
891 type = zone_->types()->newArray(type, size, false);
896 // Finally, if we had a non-fixed initializer, make sure it type
899 Local<Type> right(zone_, visitForLoad(initializer));
903 if (!typeCheckAssignment(node->pos(), right, type, true))
907 if (node->initialization()) {
908 Local<Type> right(zone_, visitForLoad(node->initialization()));
911 if (!typeCheckAssignment(node->pos(), right, type, true))
915 if (type->isPrimitive() && type->primitive() == PrimitiveType_Char) {
916 cc_.reportError(node->pos(), Message_CannotDeclareStringCell);
921 // If this variable is stack allocated, we could use the LIFO heap
922 // to allocate it. If that's the case, make sure to reserve a slot
923 // so we can unwind the LIFO heap at the end of this scope.
924 if (!node->variable()->needsHeapAllocation()) {
925 if (type->isArray() || type->isStruct())
926 scope_->setUsesLifoHeap();
929 node->variable()->setType(type);
933 SemanticAnalysis::visit(IntegerLiteral *node)
935 node->setType(zone_->types()->getPrimitive(PrimitiveType_Int32));
939 SemanticAnalysis::visit(BooleanLiteral *node)
941 node->setType(zone_->types()->getPrimitive(PrimitiveType_Bool));
945 SemanticAnalysis::visit(ExpressionStatement *node)
947 visitAndApplyType(node->expression());
951 SemanticAnalysis::evaluateDefaultParameter(Handle<Type> type, Parameter *parameter)
953 Local<Type> given(zone_, visitForLoad(parameter->initializer()));
956 if (EvaluateForConstant(parameter->initializer(), &prim)) {
957 if (!typeCheckAssignment(parameter->initializer()->pos(), given, type, false))
960 if (prim.type() == PrimitiveType_Int32)
961 return Box::New(zone_, given, prim.toInt());
962 return Box::New(zone_, given, prim.toFloat());
963 } else if (parameter->initializer()->isStringLiteral()) {
964 StringLiteral *literal = parameter->initializer()->toStringLiteral();
966 if (!typeCheckAssignment(parameter->initializer()->pos(), given, type, false))
969 Local<ArrayMap> map(zone_, ArrayMap::Attach(zone_, given));
973 Local<Array> array(zone_,
974 Array::NewString(zone_,
976 literal->string()->raw(),
977 literal->string()->length(),
982 return Box::NewObj(zone_, given, array, Heap::Tenure_Old);
985 cc_.reportError(parameter->initializer()->pos(), Message_MustBeConstant);
990 SemanticAnalysis::buildFunctionArgs(AstNode *node, TokenKind kind, const FunctionSignature &sig,
991 FixedArray **argsp, FixedArray **defaultsp)
993 Local<FixedArray> args(zone_, FixedArray::New(zone_, sig.parameters()->length(), Heap::Tenure_Old));
997 Local<FixedArray> defaults(zone_);
999 // Apply types to arguments.
1000 for (size_t i = 0; i < sig.parameters()->length(); i++) {
1001 Parameter *parameter = sig.parameters()->at(i);
1003 Local<Type> type(zone_, bindType(parameter->variable()->pos(), parameter->type()));
1007 if (parameter->reference()) {
1008 if (parameter->dimensions()) {
1009 cc_.reportError(parameter->variable()->pos(), Message_ArrayCantBeReference);
1013 if (type->isStruct()) {
1014 cc_.reportError(parameter->variable()->pos(), Message_StructCantBeReference);
1018 type = zone_->types()->getReference(type, parameter->isConst());
1021 } else if (parameter->dimensions()) {
1022 // :TODO: factor in type dimcount
1023 if (parameter->dimensions()->length() > MAX_ARRAY_DEPTH) {
1024 cc_.reportError(parameter->variable()->pos(), Message_MaximumArrayDepth);
1028 if (kind == TOK_NATIVE && parameter->dimensions()->length() > 1) {
1029 cc_.reportError(parameter->variable()->pos(), Message_MultiArrayInNative);
1033 for (size_t i = parameter->dimensions()->length() - 1;
1034 i < parameter->dimensions()->length();
1037 int size = Type::DYNAMIC_ARRAY_SIZE;
1038 if (Expression *expr = parameter->dimensions()->at(i)) {
1040 if (!EvaluateForConstant(expr, &box) || box.type() != PrimitiveType_Int32) {
1041 cc_.reportError(expr->pos(), Message_ArraySizeMustBeConstant);
1047 type = zone_->types()->newArray(type, size, parameter->isConst());
1053 if (IsScalarString(type)) {
1054 cc_.reportError(node->pos(), Message_CannotDeclareStringCell);
1058 args->set(zone_, i, type);
1059 parameter->variable()->setType(type);
1061 if (parameter->initializer()) {
1063 defaults = FixedArray::New(zone_, sig.parameters()->length(), Heap::Tenure_Old);
1068 Local<Box> box(zone_, evaluateDefaultParameter(type, parameter));
1072 defaults->set(zone_, i, box);
1077 *defaultsp = defaults;
1083 SemanticAnalysis::visit(FunctionTypeStatement *node)
1085 if (node->decl()->type())
1088 Local<FixedArray> args(zone_);
1089 Local<FixedArray> defaults(zone_);
1091 const FunctionSignature &sig= node->signature();
1092 if (!buildFunctionArgs(node,
1096 defaults.address()))
1101 Local<Type> returnType(zone_);
1102 if (sig.returnType())
1103 returnType = bindType(node->pos(), sig.returnType());
1105 returnType = zone_->types()->getPrimitive(PrimitiveType_Int32);
1110 Local<Type> funtype(zone_, zone_->types()->newFunction(returnType, args, defaults));
1114 node->decl()->setType(funtype);
1118 SemanticAnalysis::preanalyze(FunctionStatement *node)
1120 Local<FixedArray> args(zone_);
1121 Local<FixedArray> defaults(zone_);
1123 const FunctionSignature &sig = node->signature();
1124 if (!buildFunctionArgs(node,
1125 node->fun()->token(),
1128 defaults.address()))
1133 Local<Type> returnType(zone_);
1134 if (sig.returnType() ||
1135 node->hasExplicitReturn() ||
1136 node->fun()->isNative())
1138 returnType = bindType(node->pos(), sig.returnType());
1140 returnType = zone_->types()->getVoid();
1145 Local<Type> funtype(zone_);
1146 if (node->fun()->isNative())
1147 funtype = zone_->types()->newNative(returnType, args, defaults, node->fun()->isNativeVariadic());
1149 funtype = zone_->types()->newFunction(returnType, args, defaults);
1153 // If the function already has a type, it was forward declared before, and
1154 // now this is our chance to type check the second declaration.
1155 if (node->fun()->type()) {
1156 Local<Type> forward(zone_, node->fun()->type());
1157 if (!Type::Compare(funtype, forward)) {
1158 cc_.reportError(node->pos(), Message_ForwardDeclareMismatches);
1161 node->fun()->setForwardType(forward);
1164 node->fun()->setType(funtype);
1170 SemanticAnalysis::visit(FunctionStatement *node)
1172 function_ = node->fun();
1173 scope_ = node->scope();
1175 ControlScope control(&control_);
1177 node->body()->accept(this);
1179 ControlStatus status = control.status();
1180 if (status.returns() == Returns_Sometimes) {
1181 cc_.reportError(node->pos(), Message_NotAllPathsReturnValue);
1182 } else if (status.returns() == Returns_Never) {
1183 if (!function_->type()->returnType()->isVoid())
1184 cc_.reportError(node->pos(), Message_MissingReturnValue);
1193 SemanticAnalysis::typeMismatch(const SourcePosition &pos, Handle<Type> actual, Handle<Type> given)
1195 cc_.reportError(pos, Message_TypeMismatch,
1196 GetTypeName(actual),
1197 GetTypeName(given));
1201 SemanticAnalysis::typeCheckArrayAssignment(const SourcePosition &pos, Handle<Type> argGiven,
1202 Handle<Type> argActual, bool forAssign)
1204 Local<Type> actual(zone_, argActual);
1205 Local<Type> given(zone_, argGiven);
1207 if (!given->isArray()) {
1208 cc_.reportError(pos, Message_ExpectedArray);
1211 if (given->levels() != actual->levels()) {
1212 cc_.reportError(pos, Message_ArrayDimensionsMismatch);
1217 while (given->isArray()) {
1218 if (actual->isFixedLength()) {
1220 if (!given->isFixedLength()) {
1221 cc_.reportError(pos, Message_ArrayDimensionSizeMismatch, level);
1225 if (actual->isCharArray()) {
1226 // String assignment can have a truncated |given|.
1227 if (given->fixedLength() > actual->fixedLength()) {
1228 cc_.reportError(pos, Message_ArrayAssignmentTooBig);
1232 if (given->fixedLength() != actual->fixedLength()) {
1233 cc_.reportError(pos, Message_ArrayDimensionSizeMismatch, level);
1238 } else if (given->isFixedLength()) {
1239 // We do not allow assignments in the form:
1242 // Otherwise, the following code could break the size guarantees
1243 // of the right-hand side:
1252 // Now |x[0]| contains a 4-length array.
1254 cc_.reportError(pos, Message_ArrayDimensionSizeMismatch, level);
1258 given = given->contained();
1259 actual = actual->contained();
1263 return typeCheckAssignment(pos, given, actual, forAssign);
1267 SemanticAnalysis::typeCheckAssignment(const SourcePosition &pos, Handle<Type> argGiven,
1268 Handle<Type> argActual, bool forAssign)
1270 Local<Type> actual(zone_, argActual);
1271 Local<Type> given(zone_, argGiven);
1273 if (actual->isArray())
1274 return typeCheckArrayAssignment(pos, given, actual, forAssign);
1276 if (given->isArray()) {
1277 cc_.reportError(pos, Message_CannotAssignArrayToScalar);
1281 // The given type may not have been dereferenced.
1282 if (given->isReference())
1283 given = given->contained();
1284 if (actual->isReference())
1285 actual = actual->contained();
1287 // We coerce unchecked to a few things.
1288 if (actual->isUnchecked() || given->isUnchecked()) {
1289 Type *check = actual->isUnchecked() ? given : actual;
1290 if (check->isUnchecked() ||
1298 typeMismatch(pos, actual, given);
1302 if (given->isFunction() && actual->isFunction()) {
1303 if (!Type::Compare(given, actual)) {
1304 typeMismatch(pos, actual, given);
1310 if (actual->isEnum()) {
1311 if (!given->isEnum() || actual != given) {
1312 typeMismatch(pos, actual, given);
1318 if (actual->isStruct()) {
1319 if (!given->isStruct() || actual != given) {
1320 typeMismatch(pos, actual, given);
1326 if (given->isEnum() || given->isFunction() || given->isStruct()) {
1327 typeMismatch(pos, actual, given);
1331 // This coercion is trivial.
1332 if (given->isBool() && actual->isInt32())
1335 if (given->primitive() != actual->primitive()) {
1336 typeMismatch(pos, actual, given);
1344 SemanticAnalysis::typeCheckParameter(AstNode *node, Handle<Type> given, Handle<Type> actual)
1346 return typeCheckAssignment(node->pos(), given, actual, false);
1350 SemanticAnalysis::checkArgumentCount(Handle<Type> type, unsigned actual)
1352 if (type->parameters()->length() == actual)
1355 if (actual > type->parameters()->length()) {
1356 if (!type->isNative() || !type->isNativeVariadic())
1361 if (!type->defaults())
1364 // Missing arguments. See if there's a default argument for each missing
1366 for (unsigned i = actual; i < type->parameters()->length(); i++) {
1367 if (!type->defaults()->at(i))
1375 SemanticAnalysis::visit(CallExpression *node)
1377 Local<Type> type(zone_, visitForLoad(node->callee()));
1381 if (!type->isFunction()) {
1382 cc_.reportError(node->pos(), Message_CalleeNotFunction);
1386 if (!checkArgumentCount(type, node->arguments()->length())) {
1387 cc_.reportError(node->pos(), Message_ArgumentCountMismatch);
1391 // NamedFunction *fun = node->callee()->toNameProxy()->binding()->toNamedFunction();
1392 // if (fun->isForward()) {
1393 // cc_.reportError(node->pos(), Message_ForwardNotImplemented, fun->name()->chars());
1397 for (unsigned i = 0; i < node->arguments()->length(); i++) {
1398 // Note: we don't compute references unless the callee needs a
1400 Expression *expression = node->arguments()->at(i);
1401 Local<Type> given(zone_, visitAndApplyType(expression));
1405 // Since we skip a load, check for a call expression that returns void.
1406 if (given->isVoid()) {
1407 assert(expression->isCallExpression());
1408 CallExpression *call = expression->toCallExpression();
1409 cc_.reportError(call->callee()->pos(), Message_FunctionDoesNotReturnValue);
1413 bool mustComputeReference;
1414 if (i >= type->parameters()->length()) {
1415 // Special handling for natives. Arguments past the formal must
1416 // always have references computed. However, arrays are already
1417 // references for natives.
1418 assert(type->isNative() && type->isNativeVariadic());
1419 mustComputeReference = !given->isReference() && !given->isArray();
1421 Local<Type> actual(zone_, type->parameterAt(i));
1423 if (expression->isIndexExpression() && actual->isArray()) {
1424 // We special case the ability to pass x[y] into x[], which
1425 // creates an array slice. We only do this if we know the
1426 // assignment would otherwise not type-check.
1427 IndexExpression *index = expression->toIndexExpression();
1428 if (index->left()->type()->levels() == actual->levels())
1429 given = index->left()->type();
1432 if (!typeCheckParameter(expression, given, actual))
1434 mustComputeReference = actual->isReference() && !given->isReference();
1437 // If the actual is a reference, and the given is not, we'll need to
1438 // compute a reference, which may be allocated on the stack.
1439 if (mustComputeReference)
1440 scope_->setUsesLifoHeap();
1443 node->setType(type->returnType());
1447 SemanticAnalysis::ControlScope::inherit(const ControlStatus &other)
1449 if (other.returns() < status().returns())
1452 if (other.terminates())
1453 terminate(other.returns());
1455 returns(other.returns());
1459 SemanticAnalysis::ControlScope::merge(const ControlStatus &left, const ControlStatus &right)
1461 // If both sides terminate in a return, we consider this a return as well.
1462 if (left.returns() == Returns_Always && right.returns() == Returns_Always) {
1463 terminate(Returns_Always);
1467 ReturnStatus status = (left.returns() == Returns_Never && right.returns() == Returns_Never)
1469 : Returns_Sometimes;
1471 if (left.terminates() && right.terminates())
1478 SemanticAnalysis::visit(IfStatement *node)
1480 Local<Type> type(zone_, visitForLoad(node->condition()));
1484 if (!canTest(node, type))
1487 ControlStatus trueBranch = visitForControl(node->ifTrue());
1488 ControlStatus falseBranch = ControlStatus(false, Returns_Never);
1490 if (node->ifFalse())
1491 falseBranch = visitForControl(node->ifFalse());
1493 control_->merge(trueBranch, falseBranch);
1497 SemanticAnalysis::visit(IndexExpression *node)
1499 Local<Type> left(zone_, visitForLoad(node->left()));
1500 Local<Type> right(zone_, visitForLoad(node->right()));
1502 if (!left || !right)
1505 if (!right->isInt32() && !right->isEnum()) {
1506 cc_.reportError(node->right()->pos(), Message_IndexMustBeInteger);
1509 if (!left->isArray()) {
1510 cc_.reportError(node->left()->pos(), Message_IndexBaseMustBeArray);
1514 // Note: char arrays are automatically up-casted to return an int32.
1515 if (left->isCharArray())
1516 node->setType(zone_->types()->getPrimitive(PrimitiveType_Int32));
1518 node->setType(left->contained());
1522 SemanticAnalysis::visit(FieldExpression *node)
1524 Local<Type> left(zone_, visitForLoad(node->left()));
1528 if (!left->isStruct()) {
1529 cc_.reportError(node->pos(), Message_PropertyNotFound, node->field()->chars(),
1534 Local<String> field(zone_, node->field());
1537 Local<Descriptor> desc(zone_, left->lookupField(field, &offset));
1539 cc_.reportError(node->pos(), Message_PropertyNotFound, node->field()->chars(),
1544 node->setFieldIndex(offset);
1545 node->setType(desc->type());
1549 SemanticAnalysis::visit(EnumStatement *node)
1551 Local<String> name(zone_, node->name());
1552 Local<Type> type(zone_);
1554 type = zone_->types()->newEnum(name);
1556 type = zone_->types()->getPrimitive(PrimitiveType_Int32);
1562 node->decl()->setType(type);
1565 for (size_t i = 0; i < node->entries()->length(); i++) {
1566 EnumStatement::Entry &entry = node->entries()->at(i);
1568 BoxedPrimitive box = BoxedPrimitive::Int(value);
1570 entry.expr->accept(this);
1571 if (!EvaluateForConstant(entry.expr, &box) || box.type() != PrimitiveType_Int32) {
1572 cc_.reportError(entry.expr->pos(), Message_EnumFieldNotConstant);
1576 assert(box.type() == PrimitiveType_Int32);
1577 value = box.toInt();
1580 entry.name->set(type, box);
1586 SortCaseIntValues(const void *p1, const void *p2)
1588 CaseValue *v1 = (CaseValue *)p1;
1589 CaseValue *v2 = (CaseValue *)p2;
1591 return v1->box.toInt() - v2->box.toInt();
1595 SemanticAnalysis::visit(SwitchStatement *node)
1597 Local<Type> caseType(zone_, visitForLoad(node->expression()));
1601 if (!caseType->isEnum() && !caseType->isInt32()) {
1602 cc_.reportError(node->pos(), Message_CaseMustBeInteger);
1606 PoolList<CaseValue> *values = new (zone_->pool()) PoolList<CaseValue>();
1607 ControlStatus status = ControlStatus(false, Returns_Never);
1609 Local<Type> check(zone_);
1610 for (size_t i = 0; i < node->cases()->length(); i++) {
1611 Case *c = node->cases()->at(i);
1613 check = visitForLoad(c->expression());
1617 if (!typeCheckAssignment(c->expression()->pos(), check, caseType, false))
1621 if (!EvaluateForConstant(c->expression(), &v.box)) {
1622 cc_.reportError(c->expression()->pos(), Message_CaseMustBeConstant);
1625 if (!values->append(v))
1629 for (size_t j = 0; j < c->others()->length(); j++) {
1630 Expression *expr = c->others()->at(j);
1631 check = visitForLoad(expr);
1635 if (!typeCheckAssignment(expr->pos(), check, caseType, false))
1639 if (!EvaluateForConstant(expr, &v.box)) {
1640 cc_.reportError(expr->pos(), Message_CaseMustBeConstant);
1643 if (!values->append(v))
1648 ControlStatus latest = visitForControl(c->statement());
1651 control_->merge(status, latest);
1656 if (node->defaultCase()) {
1657 ControlStatus latest = visitForControl(node->defaultCase());
1659 if (node->cases()->length()) {
1660 // If we had any other cases, we must merge.
1661 control_->merge(status, latest);
1663 // Otherwise, control-flow always flows through here.
1664 control_->inherit(latest);
1666 } else if (node->cases()->length()) {
1667 control_->merge(status, ControlStatus(false, Returns_Never));
1670 if (values->length() > 1) {
1671 qsort(values->buffer(), values->length(), sizeof(CaseValue), SortCaseIntValues);
1673 for (size_t i = 1; i < values->length(); i++) {
1674 CaseValue &prev = values->at(i - 1);
1675 CaseValue &cur = values->at(i);
1676 if (prev.box.toInt() == cur.box.toInt()) {
1677 cc_.reportError(node->cases()->at(cur.statement)->expression()->pos(), Message_CaseHasSameValue);
1683 node->setCaseValueList(values);
1687 SemanticAnalysis::visit(StructureStatement *node)
1689 // If this node already has a type, it was pre-analyzed, so skip it.
1690 if (node->decl()->type())
1693 FieldList *fields = node->fields();
1694 Local<FixedArray> desctable(zone_, FixedArray::New(zone_, fields->length(), Heap::Tenure_Old));
1698 Vector<unsigned> composedList;
1699 StructureBufferBuilder builder;
1701 Local<Type> type(zone_);
1702 Local<String> name(zone_);
1703 Local<Descriptor> desc(zone_);
1704 for (size_t i = 0; i < fields->length(); i++) {
1705 StructureStatement::Field *field = fields->at(i);
1707 type = bindType(field->pos(), field->type());
1711 if (type->isPrimitive() && type->primitive() == PrimitiveType_Char) {
1712 cc_.reportError(field->pos(), Message_CannotDeclareStringCell);
1717 if (!builder.add(type, &offset))
1720 name = field->name();
1721 desc = Descriptor::New(zone_, name, type, offset);
1725 desctable->set(zone_, i, desc);
1727 if (type->isStruct() || type->isArray()) {
1728 if (!composedList.append(i))
1733 Local<FixedArray> composed(zone_);
1734 if (composedList.length()) {
1735 composed = FixedArray::New(zone_, composedList.length(), Heap::Tenure_Old);
1739 for (unsigned i = 0; i < composedList.length(); i++)
1740 composed->set(zone_, i, desctable->at(i));
1743 Local<StructMap> map(zone_, StructMap::New(zone_, builder, composed));
1747 name = node->decl()->name();
1748 type = zone_->types()->newStruct(name, desctable, map);
1753 node->decl()->setType(type);
1757 SemanticAnalysis::visit(StringLiteral *node)
1759 Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Char));
1763 type = Type::NewArray(zone_, type, node->string()->length() + 1, true);
1767 node->setType(type);
1771 SemanticAnalysis::visit(FloatLiteral *node)
1773 Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Float));
1777 node->setType(type);
1781 SemanticAnalysis::visit(BreakStatement *node)
1784 cc_.reportError(node->pos(), Message_BreakOutsideLoop);
1788 // Note: ignore breaks that occur in unreachable control-flow.
1789 if (!control_->status().terminates())
1792 control_->terminate(Returns_Never);
1796 SemanticAnalysis::visit(ContinueStatement *node)
1799 cc_.reportError(node->pos(), Message_ContinueOutsideLoop);
1803 // Note: ignore continues that occur in unreachable control-flow.
1804 if (!control_->status().terminates())
1805 loop_->addContinue();
1807 control_->terminate(Returns_Never);
1811 SemanticAnalysis::visit(ArrayLiteral *node)
1813 // We should never visit this.
1814 cc_.reportError(node->pos(), Message_UnexpectedArrayLiteral);