blob: f9ea6d7d0f53421136f714e8552bee8cc0dba521 [file] [log] [blame] [edit]
/*
Copyright (c) 2009 Peter Andrew Jamieson (jamieson.peter@gmail.com)
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "odin_types.h"
#include "ast_util.h"
#include "ast_elaborate.h"
#include "ast_loop_unroll.h"
#include "parse_making_ast.h"
#include "verilog_bison.h"
#include "netlist_create_from_ast.h"
#include "ctype.h"
#include "vtr_util.h"
#include "vtr_memory.h"
#include <string>
#include <iostream>
#include <vector>
#include <stack>
// #define read_node 1
// #define write_node 2
// #define e_data 1
// #define e_operation 2
// #define e_variable 3
// #define N 64
// #define Max_size 64
// long count_id = 0;
// long count_assign = 0;
// long count;
// long count_write;
//enode *head, *p;
// void reduce_assignment_expression();
// void reduce_assignment_expression(ast_node_t *ast_module);
// void find_assign_node(ast_node_t *node, std::vector<ast_node_t *> list, char *module_name);
// struct enode
// {
// struct
// {
// short operation;
// int data;
// std::string variable;
// }type;
// int id;
// int flag;
// int priority;
// struct enode *next;
// struct enode *pre;
// };
// void record_tree_info(ast_node_t *node);
// void store_exp_list(ast_node_t *node);
// void create_enode(ast_node_t *node);
// bool simplify_expression();
// bool adjoin_constant();
// enode *replace_enode(int data, enode *t, int mark);
// bool combine_constant();
// bool delete_continuous_multiply();
// void construct_new_tree(enode *tail, ast_node_t *node, int line_num, int file_num);
// void reduce_enode_list();
// enode *find_tail(enode *node);
// int check_exp_list(enode *tail);
// void create_ast_node(enode *temp, ast_node_t *node, int line_num, int file_num);
// void create_op_node(ast_node_t *node, enode *temp, int line_num, int file_num);
// void free_exp_list();
// void change_exp_list(enode *beign, enode *end, enode *s, int flag);
// enode *copy_enode_list(enode *new_head, enode *begin, enode *end);
// void copy_enode(enode *node, enode *new_node);
// bool check_tree_operation(ast_node_t *node);
// void check_operation(enode *begin, enode *end);
// bool check_mult_bracket(std::vector<int> list);
void convert_2D_to_1D_array(ast_node_t **var_declare, STRING_CACHE_LIST *local_string_cache_list);
void convert_2D_to_1D_array_ref(ast_node_t **node, STRING_CACHE_LIST *local_string_cache_list);
char *make_chunk_size_name(char *instance_name_prefix, char *array_name);
ast_node_t *get_chunk_size_node(char *instance_name_prefix, char *array_name, STRING_CACHE_LIST *local_string_cache_list);
int simplify_ast_module(ast_node_t **ast_module, STRING_CACHE_LIST *local_string_cache_list)
{
/* resolve constant expressions */
*ast_module = reduce_expressions(*ast_module, local_string_cache_list, NULL, 0);
unroll_loops(ast_module, local_string_cache_list);
return 1;
}
// this should replace ^^
ast_node_t *reduce_expressions(ast_node_t *node, STRING_CACHE_LIST *local_string_cache_list, long *max_size, long assignment_size)
{
short *child_skip_list = NULL; // list of children not to traverse into
short skip_children = false; // skips the DFS completely if true
if (node)
{
STRING_CACHE *local_param_table_sc = local_string_cache_list->local_param_table_sc;
STRING_CACHE *local_symbol_table_sc = local_string_cache_list->local_symbol_table_sc;
if (node->num_children > 0)
{
child_skip_list = (short*)vtr::calloc(node->num_children, sizeof(short));
}
switch (node->type)
{
case MODULE:
{
// skip identifier
child_skip_list[0] = true;
break;
}
case FUNCTION:
{
skip_children = true;
break;
}
case VAR_DECLARE:
{
if (node->types.variable.is_parameter || node->types.variable.is_localparam)
{
bool is_stored = false;
long sc_spot = sc_lookup_string(local_param_table_sc, node->children[0]->types.identifier);
if (sc_spot != -1 && ((ast_node_t*)local_param_table_sc->data[sc_spot]) == node->children[5])
{
is_stored = true;
}
/* resolve right-hand side */
node->children[5] = reduce_expressions(node->children[5], local_string_cache_list, NULL, 0);
oassert(node->children[5]->type == NUMBERS);
/* this forces parameter values as unsigned, since we don't currently support signed keyword...
must be changed once support is added */
VNumber *temp = node->children[5]->types.vnumber;
VNumber *to_unsigned = new VNumber(V_UNSIGNED(*temp));
node->children[5]->types.vnumber = to_unsigned;
delete temp;
if (is_stored)
{
local_param_table_sc->data[sc_spot] = (void *) node->children[5];
}
skip_children = true;
}
else
{
// skip identifier
child_skip_list[0] = true;
}
break;
}
case IDENTIFIERS:
{
if (local_param_table_sc != NULL && node->types.identifier)
{
long sc_spot = sc_lookup_string(local_param_table_sc, node->types.identifier);
if (sc_spot != -1)
{
ast_node_t *newNode = ast_node_deep_copy((ast_node_t *)local_param_table_sc->data[sc_spot]);
if (newNode->type != NUMBERS)
{
newNode = reduce_expressions(newNode, local_string_cache_list, NULL, assignment_size);
oassert(newNode->type == NUMBERS);
/* this forces parameter values as unsigned, since we don't currently support signed keyword...
must be changed once support is added */
VNumber *temp = newNode->types.vnumber;
VNumber *to_unsigned = new VNumber(V_UNSIGNED(*temp));
newNode->types.vnumber = to_unsigned;
delete temp;
if (newNode->type != NUMBERS)
{
error_message(NETLIST_ERROR, node->line_number, node->file_number, "Parameter %s is not a constant expression\n", node->types.identifier);
}
}
node = free_whole_tree(node);
node = newNode;
}
}
break;
}
case FOR:
// look ahead for parameters
break;
case WHILE:
// look ahead for parameters
break;
case GENERATE:
break;
case BLOCKING_STATEMENT:
case NON_BLOCKING_STATEMENT:
{
/* try to resolve */
if (node->children[1]->type != FUNCTION_INSTANCE)
{
node->children[0] = reduce_expressions(node->children[0], local_string_cache_list, NULL, 0);
assignment_size = get_size_of_variable(node->children[0], local_string_cache_list);
max_size = (long*)calloc(1, sizeof(long));
if (node->children[1]->type != NUMBERS)
{
node->children[1] = reduce_expressions(node->children[1], local_string_cache_list, max_size, assignment_size);
if (node->children[1] == NULL)
{
/* resulting from replication of zero */
error_message(NETLIST_ERROR, node->line_number, node->file_number,
"%s","Cannot perform assignment with nonexistent value");
}
}
else
{
VNumber *temp = node->children[1]->types.vnumber;
node->children[1]->types.vnumber = new VNumber(*temp, assignment_size);
delete temp;
}
vtr::free(max_size);
/* cast to unsigned if necessary */
if (node_is_constant(node->children[1]))
{
char *id = NULL;
if (node->children[0]->type == IDENTIFIERS)
{
id = node->children[0]->types.identifier;
}
else
{
id = node->children[0]->children[0]->types.identifier;
}
long sc_spot = sc_lookup_string(local_symbol_table_sc, id);
if (sc_spot > -1)
{
bool is_signed = ((ast_node_t *)local_symbol_table_sc->data[sc_spot])->types.variable.is_signed;
if (!is_signed)
{
VNumber *temp = node->children[1]->types.vnumber;
VNumber *to_unsigned = new VNumber(V_UNSIGNED(*temp));
node->children[1]->types.vnumber = to_unsigned;
delete temp;
}
else
{
/* leave as is */
}
}
}
else
{
/* signed keyword is not supported, meaning unresolved values will already be handled as
unsigned at the netlist level... must update once signed support is added */
}
assignment_size = 0;
}
skip_children = true;
break;
}
case BINARY_OPERATION:
break;
case UNARY_OPERATION:
break;
case CONCATENATE:
break;
case REPLICATE:
{
node->children[0] = reduce_expressions(node->children[0], local_string_cache_list, NULL, 0);
if (!(node_is_constant(node->children[0])))
{
error_message(NETLIST_ERROR, node->line_number, node->file_number,
"%s","Replication constant must be a constant expression");
}
ast_node_t *new_node = NULL;
int64_t value = node->children[0]->types.vnumber->get_value();
if (value > 0)
{
new_node = create_node_w_type(CONCATENATE, node->line_number, node->file_number);
for (size_t i = 0; i < value; i++)
{
add_child_to_node(new_node, ast_node_deep_copy(node->children[1]));
}
}
node->children[1] = free_whole_tree(node->children[1]);
node->children[1] = NULL;
node->num_children--;
node->children[0] = free_whole_tree(node->children[0]);
node->children[0] = new_node;
break;
}
case NUMBERS:
break;
case IF_Q:
break;
case IF:
break;
case CASE:
break;
case RANGE_REF:
case ARRAY_REF:
break;
case MODULE_INSTANCE:
// flip hard blocks
break;
default:
break;
}
if (skip_children == false)
{
/* traverse all the children */
for (int i = 0; i < node->num_children; i++)
{
if (child_skip_list[i] == false)
{
/* recurse */
node->children[i] = reduce_expressions(node->children[i], local_string_cache_list, max_size, assignment_size);
}
}
}
/* post-amble */
switch (node->type)
{
case VAR_DECLARE:
{
// pack 2d array into 1d
if (node->num_children == 8
&& node->children[5]
&& node->children[6])
{
convert_2D_to_1D_array(&node, local_string_cache_list);
}
break;
}
case FOR:
// unroll
//unroll_loops(node->children[i]); // change this function (dont have to go through whole tree)
// recurse for operation resolution
break;
case WHILE:
// unroll
// recurse (simplify_ast?)
case GENERATE:
{
node->type = BLOCK;
break;
}
case BINARY_OPERATION:
{
if (node->children[0] == NULL || node->children[1] == NULL)
{
/* resulting from replication of zero */
error_message(NETLIST_ERROR, node->line_number, node->file_number,
"%s","Cannot perform operation with nonexistent value");
}
ast_node_t *new_node = fold_binary(&node);
if (node_is_constant(new_node))
{
/* resize as needed */
long new_size;
long this_size = new_node->types.vnumber->size();
if (assignment_size > 0)
{
new_size = assignment_size;
}
else if (max_size)
{
new_size = *max_size;
}
else
{
new_size = this_size;
}
/* clean up */
free_resolved_children(node);
change_to_number_node(node, VNumber(*(new_node->types.vnumber), new_size));
}
new_node = free_whole_tree(new_node);
break;
}
case UNARY_OPERATION:
{
if (node->children[0] == NULL)
{
/* resulting from replication of zero */
error_message(NETLIST_ERROR, node->line_number, node->file_number,
"%s","Cannot perform operation with nonexistent value");
}
ast_node_t *new_node = fold_unary(&node);
if (node_is_constant(new_node))
{
/* resize as needed */
long new_size;
long this_size = new_node->types.vnumber->size();
if (assignment_size > 0)
{
new_size = assignment_size;
}
else if (max_size)
{
new_size = *max_size;
}
else
{
new_size = this_size;
}
/* clean up */
free_resolved_children(node);
change_to_number_node(node, VNumber(*(new_node->types.vnumber), new_size));
}
new_node = free_whole_tree(new_node);
break;
}
case REPLICATE:
{
/* remove intermediate REPLICATE node */
ast_node_t *child = node->children[0];
node->children[0] = NULL;
node = free_whole_tree(node);
node = child;
break;
}
case CONCATENATE:
{
resolve_concat_sizes(node, local_string_cache_list);
if (node->num_children > 0)
{
size_t current = 0;
size_t previous = -1;
bool previous_is_constant = false;
while (current < node->num_children)
{
bool current_is_constant = node_is_constant(node->children[current]);
if(previous_is_constant && current_is_constant)
{
VNumber new_value = V_CONCAT({*(node->children[previous]->types.vnumber), *(node->children[current]->types.vnumber)});
node->children[current] = free_whole_tree(node->children[current]);
delete node->children[previous]->types.vnumber;
node->children[previous]->types.vnumber = new VNumber(new_value);
}
else if(node->children[current] != NULL)
{
previous += 1;
previous_is_constant = current_is_constant;
node->children[previous] = node->children[current];
}
current += 1;
}
node->num_children = previous+1;
if (node->num_children == 0)
{
// could we simply warn and continue ? any ways we can recover rather than fail?
/* resulting replication(s) of zero */
error_message(NETLIST_ERROR, node->line_number, node->file_number,
"%s","Cannot concatenate zero bitstrings");
// free_whole_tree(node);
// node = NULL;
}
// node was all constant
if (node->num_children == 1)
{
ast_node_t *tmp = node->children[0];
node->children[0] = NULL;
free_whole_tree(node);
node = tmp;
}
}
break;
}
case IDENTIFIERS:
{
// look up to resolve unresolved range refs
ast_node_t *var_node = NULL;
oassert(node->types.identifier);
long sc_spot = sc_lookup_string(local_symbol_table_sc, node->types.identifier);
if (sc_spot > -1)
{
var_node = (ast_node_t *)local_symbol_table_sc->data[sc_spot];
if (var_node->children[1] != NULL)
{
var_node->children[1] = reduce_expressions(var_node->children[1], local_string_cache_list, NULL, 0);
var_node->children[2] = reduce_expressions(var_node->children[2], local_string_cache_list, NULL, 0);
}
if (var_node->children[3] != NULL)
{
var_node->children[3] = reduce_expressions(var_node->children[3], local_string_cache_list, NULL, 0);
var_node->children[4] = reduce_expressions(var_node->children[4], local_string_cache_list, NULL, 0);
}
if (var_node->num_children == 8 && var_node->children[5])
{
var_node->children[5] = reduce_expressions(var_node->children[5], local_string_cache_list, NULL, 0);
var_node->children[6] = reduce_expressions(var_node->children[6], local_string_cache_list, NULL, 0);
}
local_symbol_table_sc->data[sc_spot] = (void *)var_node;
}
if (max_size)
{
long var_size = get_size_of_variable(node, local_string_cache_list);
if (var_size > *max_size)
{
*max_size = var_size;
}
}
break;
}
case NUMBERS:
{
if (max_size)
{
if (node->types.vnumber->size() > (*max_size))
{
*max_size = node->types.vnumber->size();
}
}
break;
}
case IF_Q:
{
fold_conditional(&node);
break;
}
case IF:
break;
case CASE:
break;
case RANGE_REF:
{
break;
}
case ARRAY_REF:
{
bool is_constant_ref = node_is_constant(node->children[1]) &&
(node->num_children == 3 ? node_is_constant(node->children[2]) : true);
if (!is_constant_ref)
{
// this must be an implicit memory
long sc_spot = sc_lookup_string(local_symbol_table_sc, node->children[0]->types.identifier);
oassert(sc_spot > -1);
((ast_node_t *)local_symbol_table_sc->data[sc_spot])->types.variable.is_memory = true;
}
if (node->num_children == 3) convert_2D_to_1D_array_ref(&node, local_string_cache_list);
break;
}
case MODULE_INSTANCE:
// flip hard blocks
break;
default:
break;
}
if (child_skip_list)
{
child_skip_list = (short*)vtr::free(child_skip_list);
}
}
return node;
}
void convert_2D_to_1D_array(ast_node_t **var_declare, STRING_CACHE_LIST *local_string_cache_list)
{
char *instance_name_prefix = local_string_cache_list->instance_name_prefix;
ast_node_t *node_max2 = (*var_declare)->children[3];
ast_node_t *node_min2 = (*var_declare)->children[4];
ast_node_t *node_max3 = (*var_declare)->children[5];
ast_node_t *node_min3 = (*var_declare)->children[6];
oassert(node_min2->type == NUMBERS && node_max2->type == NUMBERS);
oassert(node_min3->type == NUMBERS && node_max3->type == NUMBERS);
long addr_min = node_min2->types.vnumber->get_value();
long addr_max = node_max2->types.vnumber->get_value();
long addr_min1= node_min3->types.vnumber->get_value();
long addr_max1= node_max3->types.vnumber->get_value();
if((addr_min > addr_max) || (addr_min1 > addr_max1))
{
error_message(NETLIST_ERROR, (*var_declare)->children[0]->line_number, (*var_declare)->children[0]->file_number, "%s",
"Odin doesn't support arrays declared [m:n] where m is less than n.");
}
else if((addr_min < 0 || addr_max < 0) || (addr_min1 < 0 || addr_max1 < 0))
{
error_message(NETLIST_ERROR, (*var_declare)->children[0]->line_number, (*var_declare)->children[0]->file_number, "%s",
"Odin doesn't support negative number in index.");
}
char *name = (*var_declare)->children[0]->types.identifier;
if (addr_min != 0 || addr_min1 != 0)
error_message(NETLIST_ERROR, (*var_declare)->children[0]->line_number, (*var_declare)->children[0]->file_number,
"%s: right memory address index must be zero\n", name);
long addr_chunk_size = (addr_max1 - addr_min1 + 1);
ast_node_t *new_node = create_tree_node_number(addr_chunk_size, (*var_declare)->children[0]->line_number, (*var_declare)->children[0]->file_number);
STRING_CACHE *local_param_table_sc = local_string_cache_list->local_param_table_sc;
long sc_spot;
char *temp_string = make_chunk_size_name(instance_name_prefix, name);
if ((sc_spot = sc_add_string(local_param_table_sc, temp_string)) == -1)
error_message(NETLIST_ERROR, (*var_declare)->children[0]->line_number, (*var_declare)->children[0]->file_number,
"%s: name conflicts with Odin internal reference\n", temp_string);
vtr::free(temp_string);
temp_string = NULL;
local_param_table_sc->data[sc_spot] = (void *)new_node;
long new_address_max = (addr_max - addr_min + 1)*addr_chunk_size -1;
change_to_number_node((*var_declare)->children[3], new_address_max);
change_to_number_node((*var_declare)->children[4], 0);
(*var_declare)->children[5] = free_whole_tree((*var_declare)->children[5]);
(*var_declare)->children[6] = free_whole_tree((*var_declare)->children[6]);
(*var_declare)->children[5] = (*var_declare)->children[7];
(*var_declare)->children[7] = NULL;
(*var_declare)->num_children -= 2;
}
void convert_2D_to_1D_array_ref(ast_node_t **node, STRING_CACHE_LIST *local_string_cache_list)
{
char *array_name = NULL;
ast_node_t *array_row = NULL;
ast_node_t *array_col = NULL;
ast_node_t *array_size = NULL;
ast_node_t *new_node_1 = NULL;
ast_node_t *new_node_2 = NULL;
char *instance_name_prefix = local_string_cache_list->instance_name_prefix;
array_name = vtr::strdup((*node)->children[0]->types.identifier);
array_size = get_chunk_size_node(instance_name_prefix, array_name, local_string_cache_list);
array_row = (*node)->children[1];
array_col = (*node)->children[2];
// build the new AST
new_node_1 = newBinaryOperation(MULTIPLY, array_row, array_size, (*node)->children[0]->line_number);
new_node_2 = newBinaryOperation(ADD, new_node_1, array_col, (*node)->children[0]->line_number);
vtr::free(array_name);
(*node)->children[1] = new_node_2;
(*node)->children[2] = NULL;
(*node)->num_children -= 1;
return;
}
/*--------------------------------------------------------------------------
* (function: make_chunk_size_name)
* This function creates a string to reference a 2D array chunk size for
* 1D array indexing.
*------------------------------------------------------------------------*/
char *make_chunk_size_name(char *instance_name_prefix, char *array_name)
{
std::string to_return(instance_name_prefix);
to_return += "__";
to_return += array_name;
to_return += "_____CHUNK_SIZE_DEFINE";
return vtr::strdup(to_return.c_str());
}
/*--------------------------------------------------------------------------
* (function: get_chunk_size_node)
* This function gets the chunk size node for a 2D array, to be used for
* 1D array indexing.
*------------------------------------------------------------------------*/
ast_node_t *get_chunk_size_node(char *instance_name_prefix, char *array_name, STRING_CACHE_LIST *local_string_cache_list)
{
ast_node_t *array_size = NULL;
long sc_spot;
STRING_CACHE *local_param_table_sc = local_string_cache_list->local_param_table_sc;
char *temp_string = NULL;
temp_string = make_chunk_size_name(instance_name_prefix, array_name);
// look up chunk size
sc_spot = sc_lookup_string(local_param_table_sc, temp_string);
oassert(sc_spot != -1);
if (sc_spot != -1)
{
array_size = ast_node_deep_copy((ast_node_t *)local_param_table_sc->data[sc_spot]);
}
vtr::free(temp_string);
return array_size;
}
// /*---------------------------------------------------------------------------
// * (function: reduce_assignment_expression)
// * reduce the number nodes which can be calculated to optimize the AST
// *-------------------------------------------------------------------------*/
// void reduce_assignment_expression(ast_node_t *ast_module)
// {
// head = NULL;
// p = NULL;
// ast_node_t *T = NULL;
// if (count_id < ast_module->unique_count)
// count_id = ast_module->unique_count;
// count_assign = 0;
// std::vector<ast_node_t *> list_assign;
// find_assign_node(ast_module, list_assign, ast_module->children[0]->types.identifier);
// for (long j = 0; j < count_assign; j++)
// {
// if (check_tree_operation(list_assign[j]->children[1]) && (list_assign[j]->children[1]->num_children > 0))
// {
// store_exp_list(list_assign[j]->children[1]);
// if (simplify_expression())
// {
// enode *tail = find_tail(head);
// free_whole_tree(list_assign[j]->children[1]);
// T = (ast_node_t*)vtr::malloc(sizeof(ast_node_t));
// construct_new_tree(tail, T, list_assign[j]->line_number, list_assign[j]->file_number);
// list_assign[j]->children[1] = T;
// }
// free_exp_list();
// }
// }
// }
// /*---------------------------------------------------------------------------
// * (function: search_assign_node)
// * find the top of the assignment expression
// *-------------------------------------------------------------------------*/
// void find_assign_node(ast_node_t *node, std::vector<ast_node_t *> list, char *module_name)
// {
// if (node && node->num_children > 0 && (node->type == BLOCKING_STATEMENT || node->type == NON_BLOCKING_STATEMENT))
// {
// list.push_back(node);
// }
// for (long i = 0; node && i < node->num_children; i++)
// find_assign_node(node->children[i], list, module_name);
// }
// /*---------------------------------------------------------------------------
// * (function: simplify_expression)
// * simplify the expression stored in the linked_list
// *-------------------------------------------------------------------------*/
// bool simplify_expression()
// {
// bool build = adjoin_constant();
// reduce_enode_list();
// if(delete_continuous_multiply())
// build = true;
// if(combine_constant())
// build = true;
// reduce_enode_list();
// return build;
// }
// /*---------------------------------------------------------------------------
// * (function: find_tail)
// *-------------------------------------------------------------------------*/
// enode *find_tail(enode *node)
// {
// enode *temp;
// enode *tail = NULL;
// for (temp = node; temp != NULL; temp = temp->next)
// if (temp->next == NULL)
// tail = temp;
// return tail;
// }
// /*---------------------------------------------------------------------------
// * (function: reduce_enode_list)
// *-------------------------------------------------------------------------*/
// void reduce_enode_list()
// {
// enode *temp;
// int a;
// while(head != NULL && (head->type.data == 0) && (head->next->priority == 2) && (head->next->type.operation == '+')){
// temp=head;
// head = head->next->next;
// head->pre = NULL;
// vtr::free(temp->next);
// vtr::free(temp);
// }
// if(head == NULL){
// return;
// }
// temp = head->next;
// while (temp != NULL)
// {
// if ((temp->flag == 1) && (temp->pre->priority == 2))
// {
// if (temp->type.data == 0)
// {
// if (temp->next == NULL)
// temp->pre->pre->next = NULL;
// else
// {
// temp->pre->pre->next = temp->next;
// temp->next->pre = temp->pre->pre;
// }
// vtr::free(temp->pre);
// enode *toBeDeleted = temp;
// temp = temp->next;
// vtr::free(toBeDeleted);
// } else if (temp->type.data < 0)
// {
// if (temp->pre->type.operation == '+')
// temp->pre->type.operation = '-';
// else
// temp->pre->type.operation = '+';
// a = temp->type.data;
// temp->type.data = -a;
// temp = temp->next;
// } else {
// temp = temp->next;
// }
// } else {
// temp = temp->next;
// }
// }
// }
// /*---------------------------------------------------------------------------
// * (function: store_exp_list)
// *-------------------------------------------------------------------------*/
// void store_exp_list(ast_node_t *node)
// {
// enode *temp;
// head = (enode*)vtr::malloc(sizeof(enode));
// p = head;
// record_tree_info(node);
// temp = head;
// head = head->next;
// head->pre = NULL;
// p->next = NULL;
// vtr::free(temp);
// }
// /*---------------------------------------------------------------------------
// * (function: record_tree_info)
// *-------------------------------------------------------------------------*/
// void record_tree_info(ast_node_t *node)
// {
// if (node){
// if (node->num_children > 0)
// {
// record_tree_info(node->children[0]);
// create_enode(node);
// if (node->num_children > 1)
// record_tree_info(node->children[1]);
// }else{
// create_enode(node);
// }
// }
// }
// /*---------------------------------------------------------------------------
// * (function: create_enode)
// * store elements of an expression in nodes consisting the linked_list
// *-------------------------------------------------------------------------*/
// void create_enode(ast_node_t *node)
// {
// enode *s = (enode*)vtr::malloc(sizeof(enode));
// s->flag = -1;
// s->priority = -1;
// s->id = node->unique_count;
// switch (node->type)
// {
// case NUMBERS:
// {
// s->type.data = node->types.vnumber->get_value();
// s->flag = 1;
// s->priority = 0;
// break;
// }
// case BINARY_OPERATION:
// {
// s->flag = 2;
// switch(node->types.operation.op)
// {
// case ADD:
// {
// s->type.operation = '+';
// s->priority = 2;
// break;
// }
// case MINUS:
// {
// s->type.operation = '-';
// s->priority = 2;
// break;
// }
// case MULTIPLY:
// {
// s->type.operation = '*';
// s->priority = 1;
// break;
// }
// case DIVIDE:
// {
// s->type.operation = '/';
// s->priority = 1;
// break;
// }
// default:
// {
// break;
// }
// }
// break;
// }
// case IDENTIFIERS:
// {
// s->type.variable = node->types.identifier;
// s->flag = 3;
// s->priority = 0;
// break;
// }
// default:
// {
// break;
// }
// }
// p->next = s;
// s->pre = p;
// p = s;
// }
// /*---------------------------------------------------------------------------
// * (function: adjoin_constant)
// * compute the constant numbers in the linked_list
// *-------------------------------------------------------------------------*/
// bool adjoin_constant()
// {
// bool build = false;
// enode *t, *replace;
// int a, b, result = 0;
// int mark;
// for (t = head; t->next!= NULL; )
// {
// mark = 0;
// if ((t->flag == 1) && (t->next->next != NULL) && (t->next->next->flag ==1))
// {
// switch (t->next->priority)
// {
// case 1:
// a = t->type.data;
// b = t->next->next->type.data;
// if (t->next->type.operation == '*')
// result = a * b;
// else
// result = a / b;
// replace = replace_enode(result, t, 1);
// build = true;
// mark = 1;
// break;
// case 2:
// if (((t == head) || (t->pre->priority == 2)) && ((t->next->next->next == NULL) ||(t->next->next->next->priority ==2)))
// {
// a = t->type.data;
// b = t->next->next->type.data;
// if (t->pre->type.operation == '+')
// {
// if (t->next->type.operation == '+')
// result = a + b;
// else
// result = a - b;
// }
// if (t->pre->type.operation == '-')
// {
// if (t->next->type.operation == '+')
// result = a - b;
// else
// result = a + b;
// }
// replace = replace_enode(result, t, 1);
// build = true;
// mark = 1;
// }
// break;
// default:
// //pass
// break;
// }
// }
// if (mark == 0)
// t = t->next;
// else
// if (mark == 1)
// t = replace;
// }
// return build;
// }
// /*---------------------------------------------------------------------------
// * (function: replace_enode)
// *-------------------------------------------------------------------------*/
// enode *replace_enode(int data, enode *t, int mark)
// {
// enode *replace;
// replace = (enode*)vtr::malloc(sizeof(enode));
// replace->type.data = data;
// replace->flag = 1;
// replace->priority = 0;
// if (t == head)
// {
// replace->pre = NULL;
// head = replace;
// }
// else
// {
// replace->pre = t->pre;
// t->pre->next = replace;
// }
// if (mark == 1)
// {
// replace->next = t->next->next->next;
// if (t->next->next->next == NULL)
// replace->next = NULL;
// else
// t->next->next->next->pre = replace;
// vtr::free(t->next->next);
// vtr::free(t->next);
// }
// else
// {
// replace->next = t->next;
// t->next->pre = replace;
// }
// vtr::free(t);
// return replace;
// }
// /*---------------------------------------------------------------------------
// * (function: combine_constant)
// *-------------------------------------------------------------------------*/
// bool combine_constant()
// {
// enode *temp, *m, *s1, *s2, *replace;
// int a, b, result;
// int mark;
// bool build = false;
// for (temp = head; temp != NULL; )
// {
// mark = 0;
// if ((temp->flag == 1) && (temp->next != NULL) && (temp->next->priority == 2))
// {
// if ((temp == head) || (temp->pre->priority == 2))
// {
// for (m = temp->next; m != NULL; m = m->next)
// {
// if((m->flag == 1) && (m->pre->priority == 2) && ((m->next == NULL) || (m->next->priority == 2)))
// {
// s1 = temp;
// s2 = m;
// a = s1->type.data;
// b = s2->type.data;
// if ((s1 == head) || (s1->pre->type.operation == '+'))
// {
// if (s2->pre->type.operation == '+')
// result = a + b;
// else
// result = a - b;
// }
// else
// {
// if (s2->pre->type.operation == '+')
// result = a - b;
// else
// result = a + b;
// }
// replace = replace_enode(result, s1, 2);
// if (s2->next == NULL)
// {
// s2->pre->pre->next = NULL;
// mark = 2;
// }
// else
// {
// s2->pre->pre->next = s2->next;
// s2->next->pre = s2->pre->pre;
// }
// vtr::free(s2->pre);
// vtr::free(s2);
// if (replace == head)
// {
// temp = replace;
// mark = 1;
// }
// else
// temp = replace->pre;
// build = true;
// break;
// }
// }
// }
// }
// if (mark == 0)
// temp = temp->next;
// else
// if (mark == 1)
// continue;
// else
// break;
// }
// return build;
// }
// /*---------------------------------------------------------------------------
// * (function: construct_new_tree)
// *-------------------------------------------------------------------------*/
// void construct_new_tree(enode *tail, ast_node_t *node, int line_num, int file_num)
// {
// enode *temp, *tail1 = NULL, *tail2 = NULL;
// int prio = 0;
// if (tail == NULL)
// return;
// prio = check_exp_list(tail);
// if (prio == 1)
// {
// for (temp = tail; temp != NULL; temp = temp->pre)
// if ((temp->flag == 2) && (temp->priority == 2))
// {
// create_ast_node(temp, node, line_num, file_num);
// tail1 = temp->pre;
// tail2 = find_tail(temp->next);
// tail1->next = NULL;
// temp->next->pre = NULL;
// break;
// }
// }
// else
// if(prio == 2)
// {
// for (temp = tail; temp != NULL; temp = temp->pre)
// if ((temp->flag ==2) && (temp->priority == 1))
// {
// create_ast_node(temp, node, line_num, file_num);
// tail1 = temp->pre;
// tail2 = temp->next;
// tail2->pre = NULL;
// tail2->next = NULL;
// break;
// }
// }
// else
// if (prio == 3)
// create_ast_node(tail, node, line_num, file_num);
// if (prio == 1 || prio == 2)
// {
// node->children = (ast_node_t**)vtr::malloc(2*sizeof(ast_node_t*));
// node->children[0] = (ast_node_t*)vtr::malloc(sizeof(ast_node_t));
// node->children[1] = (ast_node_t*)vtr::malloc(sizeof(ast_node_t));
// create_ast_node(tail1, node->children[0], line_num, file_num);
// create_ast_node(tail2, node->children[1], line_num, file_num);
// construct_new_tree(tail1, node->children[0], line_num, file_num);
// construct_new_tree(tail2, node->children[1], line_num, file_num);
// }
// return;
// }
// /*---------------------------------------------------------------------------
// * (function: check_exp_list)
// *-------------------------------------------------------------------------*/
// int check_exp_list(enode *tail)
// {
// enode *temp;
// for (temp = tail; temp != NULL; temp = temp->pre)
// if ((temp->flag == 2) && (temp->priority == 2))
// return 1;
// for (temp = tail; temp != NULL; temp = temp->pre)
// if ((temp->flag == 2) && (temp->priority ==1))
// return 2;
// return 3;
// }
// /*---------------------------------------------------------------------------
// * (function: delete_continuous_multiply)
// *-------------------------------------------------------------------------*/
// bool delete_continuous_multiply()
// {
// enode *temp, *t, *m, *replace;
// bool build = false;
// int a, b, result;
// int mark;
// for (temp = head; temp != NULL; )
// {
// mark = 0;
// if ((temp->flag == 1) && (temp->next != NULL) && (temp->next->priority == 1))
// {
// for (t = temp->next; t != NULL; t = t->next)
// {
// if ((t->flag == 1) && (t->pre->priority ==1))
// {
// for (m = temp->next; m != t; m = m->next)
// {
// if ((m->flag == 2) && (m->priority != 1))
// {
// mark = 1;
// break;
// }
// }
// if (mark == 0)
// {
// a = temp->type.data;
// b = t->type.data;
// if (t->pre->type.operation == '*')
// result = a * b;
// else
// result = a / b;
// replace = replace_enode(result, temp, 3);
// if (t->next == NULL)
// t->pre->pre->next = NULL;
// else
// {
// t->pre->pre->next = t->next;
// t->next->pre = t->pre->pre;
// }
// mark = 2;
// build = true;
// vtr::free(t->pre);
// vtr::free(t);
// break;
// }
// break;
// }
// }
// }
// if ((mark == 0) || (mark == 1))
// temp = temp->next;
// else
// if (mark == 2)
// temp = replace;
// }
// return build;
// }
// /*---------------------------------------------------------------------------
// * (function: create_ast_node)
// *-------------------------------------------------------------------------*/
// void create_ast_node(enode *temp, ast_node_t *node, int line_num, int file_num)
// {
// switch(temp->flag)
// {
// case 1:
// initial_node(node, NUMBERS, line_num, file_num, ++count_id);
// change_to_number_node(node, temp->type.data);
// break;
// case 2:
// create_op_node(node, temp, line_num, file_num);
// break;
// case 3:
// initial_node(node, IDENTIFIERS, line_num, file_num, ++count_id);
// node->types.identifier = vtr::strdup(temp->type.variable.c_str());
// break;
// default:
// break;
// }
// }
// /*---------------------------------------------------------------------------
// * (function: create_op_node)
// *-------------------------------------------------------------------------*/
// void create_op_node(ast_node_t *node, enode *temp, int line_num, int file_num)
// {
// initial_node(node, BINARY_OPERATION, line_num, file_num, ++count_id);
// node->num_children = 2;
// switch(temp->type.operation)
// {
// case '+':
// node->types.operation.op = ADD;
// break;
// case '-':
// node->types.operation.op = MINUS;
// break;
// case '*':
// node->types.operation.op = MULTIPLY;
// break;
// case '/':
// node->types.operation.op = DIVIDE;
// break;
// default:
// oassert(false);
// break;
// }
// }
// /*---------------------------------------------------------------------------
// * (function: free_exp_list)
// *-------------------------------------------------------------------------*/
// void free_exp_list()
// {
// enode *next, *temp;
// for (temp = head; temp != NULL; temp = next)
// {
// next = temp->next;
// vtr::free(temp);
// }
// }
// /*---------------------------------------------------------------------------
// * (function: change_exp_list)
// *-------------------------------------------------------------------------*/
// void change_exp_list(enode *begin, enode *end, enode *s, int flag)
// {
// enode *temp, *new_head, *tail, *p2, *partial = NULL, *start = NULL;
// int mark;
// switch (flag)
// {
// case 1:
// {
// for (temp = begin; temp != end; temp = p2->next)
// {
// mark = 0;
// for (p2 = temp; p2 != end->next; p2 = p2->next)
// {
// if (p2 == end)
// {
// mark = 2;
// break;
// }
// if ((p2->flag == 2) && (p2->priority == 2))
// {
// partial = p2->pre;
// mark = 1;
// break;
// }
// }
// if (mark == 1)
// {
// new_head = (enode*)vtr::malloc(sizeof(enode));
// tail = copy_enode_list(new_head, end->next, s);
// tail = tail->pre;
// vtr::free(tail->next);
// partial->next = new_head;
// new_head->pre = partial;
// tail->next = p2;
// p2->pre = tail;
// }
// if (mark == 2)
// break;
// }
// break;
// }
// case 2:
// {
// for (temp = begin; temp != end->next; temp = temp->next)
// if ((temp->flag == 2) && (temp->priority == 2))
// {
// start = temp;
// break;
// }
// for (temp = start; temp != end->next; temp = partial->next)
// {
// mark = 0;
// for (p2 = temp; p2 != end->next; p2 = p2->next)
// {
// if (p2 == end)
// {
// mark = 2;
// break;
// }
// if ((p2->flag == 2) && (p2->priority == 2))
// {
// partial = p2->next;
// mark = 1;
// break;
// }
// }
// if (mark == 1)
// {
// new_head = (enode*)vtr::malloc(sizeof(enode));
// tail = copy_enode_list(new_head, s, begin->pre);
// tail = tail->pre;
// vtr::free(tail->next);
// p2->next = new_head;
// new_head->pre = p2;
// tail->next = partial;
// partial->pre = tail;
// }
// if (mark == 2)
// break;
// }
// break;
// }
// default:
// break;
// }
// }
// /*---------------------------------------------------------------------------
// * (function: copy_enode_list)
// *-------------------------------------------------------------------------*/
// enode *copy_enode_list(enode *new_head, enode *begin, enode *end)
// {
// enode *temp, *new_enode, *next_enode;
// new_enode = new_head;
// for (temp = begin; temp != end->next; temp = temp->next)
// {
// copy_enode(temp, new_enode);
// next_enode = (enode*)vtr::malloc(sizeof(enode));
// new_enode->next = next_enode;
// next_enode->pre = new_enode;
// new_enode = next_enode;
// }
// return new_enode;
// }
// /*---------------------------------------------------------------------------
// * (function: copy_enode)
// *-------------------------------------------------------------------------*/
// void copy_enode(enode *node, enode *new_node)
// {
// new_node->type = node->type;
// new_node->flag = node->flag;
// new_node->priority = node->priority;
// new_node->id = -1;
// }
// /*---------------------------------------------------------------------------
// * (function: check_tree_operation)
// *-------------------------------------------------------------------------*/
// bool check_tree_operation(ast_node_t *node)
// {
// if (node && (node->type == BINARY_OPERATION) && ((node->types.operation.op == ADD ) || (node->types.operation.op == MINUS) || (node->types.operation.op == MULTIPLY)))
// return true;
// for (long i = 0; node && i < node->num_children; i++)
// if(check_tree_operation(node->children[i]))
// return true;
// return false;
// }
// /*---------------------------------------------------------------------------
// * (function: check_operation)
// *-------------------------------------------------------------------------*/
// void check_operation(enode *begin, enode *end)
// {
// enode *temp, *op;
// for (temp = begin; temp != head; temp = temp->pre)
// {
// if (temp->flag == 2 && temp->priority == 2 && temp->type.operation == '-')
// {
// for (op = begin; op != end; op = op->next)
// {
// if (op->flag == 2 && op->priority == 2)
// {
// if (op->type.operation == '+')
// op->type.operation = '-';
// else
// op->type.operation = '+';
// }
// }
// }
// }
// }