dvander@0: /* dvander@0: * Copyright (C) 2012 David Anderson dvander@0: * dvander@0: * This file is part of JITCraft. dvander@0: * dvander@0: * JITCraft is free software: you can redistribute it and/or modify it under dvander@0: * the terms of the GNU General Public License as published by the Free dvander@0: * Software Foundation, either version 3 of the License, or (at your option) dvander@0: * any later version. dvander@0: * dvander@0: * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY dvander@0: * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS dvander@0: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. dvander@0: * dvander@0: * You should have received a copy of the GNU General Public License along with dvander@0: * JITCraft. If not, see http://www.gnu.org/licenses/. dvander@0: */ dvander@0: #include "SemanticAnalysis.h" dvander@0: #include "Types.h" dvander@0: dvander@0: using namespace jc; dvander@0: dvander@0: SemanticAnalysis::SemanticAnalysis(ParseTree *tree) dvander@0: : tree_(tree) dvander@0: { dvander@0: } dvander@0: dvander@0: bool dvander@0: SemanticAnalysis::analyze() dvander@0: { dvander@0: for (size_t i = 0; i < tree_->statements()->length(); i++) { dvander@0: Statement *statement = tree_->statements()->at(i); dvander@0: statement->accept(this); dvander@0: } dvander@0: dvander@0: return true; dvander@0: } dvander@0: dvander@0: void dvander@0: SemanticAnalysis::visit(NameProxy *name) dvander@0: { dvander@0: name->setType(name->binding()->type()); dvander@0: } dvander@0: dvander@0: static inline bool dvander@0: IsPrimitiveType(Type *type, PrimitiveType primitive) dvander@0: { dvander@0: if (!type) dvander@0: return false; dvander@0: dvander@0: if (!type->isPrimitive()) dvander@0: return false; dvander@0: dvander@0: return primitive == type->primitive(); dvander@0: } dvander@0: dvander@0: void dvander@0: SemanticAnalysis::visit(Assignment *node) dvander@0: { dvander@0: node->expression()->accept(this); dvander@0: dvander@0: if (node->lvalue()->isIndexExpression()) { dvander@0: node->lvalue()->accept(this); dvander@0: dvander@0: node->setType(node->lvalue()->type()); dvander@0: } else { dvander@0: NameProxy *proxy = node->lvalue()->toNameProxy(); dvander@0: if (!proxy->binding()->kind() == BoundName::VARIABLE) { dvander@0: fprintf(stderr, "error\n"); dvander@0: return; dvander@0: } dvander@0: dvander@0: Variable *var = proxy->binding()->toVariable(); dvander@0: node->setType(var->type()); dvander@0: } dvander@0: } dvander@0: dvander@0: void dvander@0: SemanticAnalysis::visit(BinaryExpression *node) dvander@0: { dvander@0: } dvander@0: dvander@0: void dvander@0: SemanticAnalysis::visit(ReturnStatement *node) dvander@0: { dvander@0: node->expression()->accept(this); dvander@0: dvander@0: // :TODO: type check dvander@0: } dvander@0: dvander@0: void dvander@0: SemanticAnalysis::visit(ForStatement *node) dvander@0: { dvander@0: if (node->declaration()) dvander@0: node->declaration()->accept(this); dvander@0: if (node->condition()) dvander@0: node->condition()->accept(this); dvander@0: if (node->update()) dvander@0: node->update()->accept(this); dvander@0: node->body()->accept(this); dvander@0: } dvander@0: dvander@0: void dvander@0: SemanticAnalysis::visit(BlockStatement *node) dvander@0: { dvander@0: for (size_t i = 0; i < node->statements()->length(); i++) { dvander@0: Statement *statement = node->statements()->at(i); dvander@0: statement->accept(this); dvander@0: } dvander@0: } dvander@0: dvander@0: void dvander@0: SemanticAnalysis::visit(VariableDeclaration *node) dvander@0: { dvander@0: Tag *tag = NULL; dvander@0: dvander@0: Type *type = Type::NewPrimitive(tag); dvander@0: if (!type) dvander@0: return; dvander@0: dvander@0: if (node->postDimensions()) { dvander@0: if (node->postDimensions()->size() > Type::MAX_UNSAFE_ARRAY_DEPTH) { dvander@0: error(); dvander@0: return; dvander@0: } dvander@0: dvander@0: for (size_t i = node->postDimensions()->size() - 1; i < node->postDimensions()->size(); i--) { dvander@0: Expression *expr = node->postDimensions()->at(i); dvander@0: expr->accept(this); dvander@0: dvander@0: if (!IsPrimitiveType(expr->type(), PrimitiveType_Int32)) { dvander@0: typeError(expr, "integer"); dvander@0: return; dvander@0: } dvander@0: dvander@0: int size = -1; dvander@0: if (expr->isIntegerLiteralExpression()) { dvander@0: size = expr->toIntegerLiteralExpression()->value(); dvander@0: if (size <= 0) { dvander@0: error(); dvander@0: return; dvander@0: } dvander@0: if (size >= INT_MAX / sizeof(int)) { dvander@0: error(); dvander@0: return; dvander@0: } dvander@0: } dvander@0: dvander@0: type = Type::NewUnsafeArray(type, size); dvander@0: } dvander@0: } dvander@0: dvander@0: node->variable()->setType(type); dvander@0: } dvander@0: dvander@0: void dvander@0: SemanticAnalysis::visit(IntegerLiteralExpression *node) dvander@0: { dvander@0: Type *type = Type::NewPrimitive(NULL); dvander@0: node->setType(type); dvander@0: } dvander@0: dvander@0: void dvander@0: SemanticAnalysis::visit(ExpressionStatement *node) dvander@0: { dvander@0: node->expression()->accept(this); dvander@0: } dvander@0: dvander@0: void dvander@0: SemanticAnalysis::visit(FunctionStatement *node) dvander@0: { dvander@0: node->body()->accept(this); dvander@0: } dvander@0: dvander@0: void dvander@0: SemanticAnalysis::visit(CallExpression *node) dvander@0: { dvander@0: } dvander@0: dvander@0: void dvander@0: SemanticAnalysis::visit(IfStatement *node) dvander@0: { dvander@0: } dvander@0: dvander@0: void dvander@0: SemanticAnalysis::visit(IndexExpression *node) dvander@0: { dvander@0: node->left()->accept(this); dvander@0: node->right()->accept(this); dvander@0: dvander@0: if (!node->right()->type(), PrimitiveType_Int32) { dvander@0: typeError(node->right(), "integer"); dvander@0: return; dvander@0: } dvander@0: if (!node->left()->type() || !node->left()->type()->isArray()) { dvander@0: typeError(node->left(), "array"); dvander@0: return; dvander@0: } dvander@0: node->setType(node->left()->type()->contained()); dvander@0: }