/* Oort * Copyright 2007, Soren Sandmann Pedersen * * This program 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 2 of the License, or * (at your option) any later version. * * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ast.h" #include /* Mark constant expressions as such */ gboolean mark_constants (ast_t *ast) { ast_expression_t *expr; gboolean constant; value_t *result; GList *list; for (list = ast->common.children->head; list; list = list->next) mark_constants (list->data); if (ast->common.type != AST_EXPRESSION) return TRUE; constant = FALSE; expr = &ast->expression; result = &expr->common.constant_value; switch (expr->common.type) { case AST_INT_LITERAL_EXPRESSION: result->int32_val = expr->int_literal.value; constant = TRUE; break; case AST_FLOAT_LITERAL_EXPRESSION: result->double_val = expr->float_literal.value; constant = TRUE; break; case AST_BOOL_LITERAL_EXPRESSION: result->bool_val = expr->bool_literal.value; constant = TRUE; break; case AST_STRING_LITERAL_EXPRESSION: result->pointer_val = expr->string_literal.value; constant = TRUE; break; case AST_NULL_EXPRESSION: result->pointer_val = NULL; constant = TRUE; break; case AST_IDENTIFIER_EXPRESSION: /* FIXME: maybe check if it's a constant, particularly * when we add enums */ break; case AST_LAMBDA_EXPRESSION: case AST_CALL_EXPRESSION: case AST_STATEMENT_EXPRESSION: case AST_NEW_EXPRESSION: case AST_DOT_EXPRESSION: case AST_THIS_EXPRESSION: case AST_VOID_EXPRESSION: case AST_INDEX_EXPRESSION: break; case AST_DEFINITION_EXPRESSION: /* FIXME: It might actually be useful to allow this */ break; case AST_BLOCK_EXPRESSION: if (expr->block.body->common.constant) { *result = expr->block.body->common.constant_value; constant = TRUE; } break; case AST_UNARY_EXPRESSION: if (expr->unary.expr->common.constant) { evaluate_unary_operator (expr->unary.operator, expr->unary.expr->common.type_spec, &expr->unary.expr->common.constant_value, expr->common.type_spec, result); constant = TRUE; } break; case AST_BINARY_EXPRESSION: if (expr->binary.left->common.constant && expr->binary.right->common.constant) { value_t *left = &expr->binary.left->common.constant_value; value_t *right = &expr->binary.right->common.constant_value; evaluate_binary_operator ( expr->binary.operator, expr->binary.left->common.type_spec, left, expr->binary.right->common.type_spec, right, expr->common.type_spec, result); constant = TRUE; } break; case AST_TERNARY_EXPRESSION: /* FIXME: we could require only the taken branch to be constant */ if (expr->ternary.cond->common.constant && expr->ternary.then_expr->common.constant && expr->ternary.else_expr->common.constant) { if (expr->ternary.cond->common.constant_value.bool_val) *result = expr->ternary.then_expr->common.constant_value; else *result = expr->ternary.else_expr->common.constant_value; constant = TRUE; } break; } expr->common.constant = constant; return TRUE; }