diff -r 627b6b94e774 -r 0784ac5cc347 jitcraft/SemanticAnalysis.cpp --- a/jitcraft/SemanticAnalysis.cpp Sat Jun 30 20:20:39 2012 -0700 +++ b/jitcraft/SemanticAnalysis.cpp Sat Jun 30 22:31:14 2012 -0700 @@ -120,8 +120,12 @@ SemanticAnalysis::visitForLoad(Expression *expression) { expression->accept(this); - if (expression->type() && expression->type()->isArray()) - expression->setType(expression->type()->contained()); + if (expression->type()) { + // :TODO: use Local + Type *type = expression->type(); + if (type->isArray() || type->isReference()) + expression->setType(type->contained()); + } return expression->type(); } @@ -163,7 +167,10 @@ } Variable *var = proxy->binding()->toVariable(); - node->setType(var->type()); + if (var->type()->isReference()) + node->setType(var->type()->contained()); + else + node->setType(var->type()); } assert(TypeCheck(node->type(), node->expression()->type())); @@ -247,6 +254,7 @@ void SemanticAnalysis::visit(VariableDeclaration *node) { + // :TODO: use locals Type *type = ZONE()->types()->getPrimitiveForTag(node->tag()); if (!type) return; @@ -308,17 +316,100 @@ node->expression()->accept(this); } +bool +SemanticAnalysis::preanalyze(FunctionStatement *node) +{ + // :TODO: use Local + + FixedArray *args = FixedArray::New(ZONE(), node->parameters()->size(), Heap::Tenure_Old); + if (!args) + return false; + + // Apply types to arguments. + for (size_t i = 0; i < node->parameters()->size(); i++) { + Parameter *parameter = node->parameters()->at(i); + + Type *type = ZONE()->types()->getPrimitiveForTag(parameter->tag()); + if (!type) + return false; + + if (parameter->reference()) { + type = ZONE()->types()->getReference(type); + if (!type) + return false; + } + + args->set(ZONE(), i, type); + parameter->variable()->setType(type); + } + + Type *returnType = ZONE()->types()->getPrimitive(PrimitiveType_Int32); + if (!returnType) + return false; + + Type *funtype = ZONE()->types()->newFunction(returnType, args); + if (!funtype) + return false; + + node->fun()->setType(funtype); + return true; +} + void SemanticAnalysis::visit(FunctionStatement *node) { scope_ = node->scope(); + + // :TODO: call this ahead of time. + if (!preanalyze(node)) + return; + node->body()->accept(this); scope_ = NULL; } +// :TODO: use handles +static inline bool +TypeCheckParameter(Type *given, Type *actual) +{ + if (actual->isReference()) { + if (given->isReference()) + given = given->contained(); + return TypeCheck(given, actual->contained()); + } + + return TypeCheck(given, actual); +} + void SemanticAnalysis::visit(CallExpression *node) { + visitForLoad(node->callee()); + + // :TODO: use locals + Type *type = node->callee()->type(); + if (!type) + return; + + assert(type->isFunction()); + assert(node->arguments()->size() == type->parameters()->length()); + + for (unsigned i = 0; i < node->arguments()->size(); i++) { + Expression *expression = node->arguments()->at(i); + expression->accept(this); + + Type *given = expression->type(); + if (!given) + return; + + Type *actual = Type::cast(type->parameters()->at(i)); + assert(TypeCheckParameter(given, actual)); + + // If the actual is a reference, and the given is not, we'll need to + // compute a reference, which may be allocated on the stack. + if (actual->isReference() && !given->isReference()) + scope_->setUsesLifoHeap(); + } } void @@ -333,6 +424,7 @@ void SemanticAnalysis::visit(IndexExpression *node) { + // :TODO: use locals Type *left = visitForRef(node->left()); Type *right = visitForLoad(node->right());