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