From eae318e2ac6b5fcf9e27819340919d130746dc28 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 11 Oct 2010 03:53:52 -0700 Subject: [PATCH] generate 3 address code --- TODO | 10 +- code_generation.cpp | 311 +++++++++++++++++++++++++++++++++--- insensitive_map.h | 4 +- semantic_checker.cpp | 36 ++--- symbol_table.cpp | 26 +-- tests/control_flow/simple.p | 4 +- 6 files changed, 334 insertions(+), 57 deletions(-) diff --git a/TODO b/TODO index 63a788b..ca3e88c 100644 --- a/TODO +++ b/TODO @@ -1,8 +1,12 @@ -Project 1 Release: - * test object instantiation & new keyword - * test strings +Project 2 Release: Bonus: + * add NOT operator + * test for negating non-numeric types + * document enum hax + * test for expressions in a compare (1 < this) + * test for boolean expression in if statement + * pass the test that crashes program * evaluate constant expressions before semantic checking * test for invalid/valid array indicies with expressions like 8*8-32 * print statement with trailing comma (meaning no newline) diff --git a/code_generation.cpp b/code_generation.cpp index dba3e2d..ee7f2c4 100644 --- a/code_generation.cpp +++ b/code_generation.cpp @@ -1,28 +1,98 @@ #include "code_generation.h" +#include "insensitive_map.h" #include #include +#include -class Instruction { +struct Instruction { + enum Type { + COPY, + OPERATOR, + UNARY, + IMMEDIATE_BOOLEAN, + IMMEDIATE_INT, + }; + Type type; + + Instruction(Type type) : type(type) {} +}; + +struct CopyInstruction : public Instruction { + int dest; // register number + int source; // register number + CopyInstruction(int dest, int source) : Instruction(COPY), dest(dest), source(source) {} +}; + +struct OperatorInstruction : public Instruction { + enum Operator { + EQUAL, NOT_EQUAL, LESS, GREATER, LESS_EQUAL, GREATER_EQUAL, + PLUS, MINUS, OR, + TIMES, DIVIDE, MOD, AND, + }; + + int dest; + int left; + Operator _operator; + int right; + + OperatorInstruction(int dest, int left, Operator _operator, int right) : Instruction(OPERATOR), dest(dest), left(left), _operator(_operator), right(right) {} +}; + +struct UnaryInstruction : public Instruction { + enum Operator { + NOT, + NEGATE, + }; + + int dest; + Operator _operator; + int source; + + UnaryInstruction(int dest, Operator _operator, int source) : Instruction(UNARY), dest(dest), _operator(_operator), source(source) {} +}; + +struct ImmediateBoolean : public Instruction { + int dest; + bool constant; + + ImmediateBoolean(int dest, bool constant) : Instruction(IMMEDIATE_BOOLEAN), dest(dest), constant(constant) {} +}; + +struct ImmediateInteger : public Instruction { + int dest; + int constant; + + ImmediateInteger(int dest, int constant) : Instruction(IMMEDIATE_INT), dest(dest), constant(constant) {} }; -class CodeGenerator { -private: - std::vector m_instructions; - int next_register_number; +class CodeGenerator { public: + CodeGenerator() : m_register_count(0) {} void generate(FunctionDeclaration * function_declaration); + void pretty_print(); + private: - int current_index() { return m_instructions.size(); } + std::vector m_instructions; + OrderedInsensitiveMap m_variable_numbers; + int m_register_count; - void scan_statement_list(StatementList * statement_list); - void scan_statement(Statement * statement); - int scan_expression(Expression * expression); +private: + int current_index() { return m_instructions.size(); } + int next_available_register() { return m_register_count++; } + void gen_statement_list(StatementList * statement_list); + void gen_statement(Statement * statement); + int gen_expression(Expression * expression); + int gen_additive_expression(AdditiveExpression * additive_expression); + int gen_multiplicitive_expression(MultiplicativeExpression * multiplicative_expression); + int gen_negatable_expression(NegatableExpression * negatable_expression); + int gen_primary_expression(PrimaryExpression * primary_expression); + int gen_variable_access(VariableAccess * variable); - void add_assignment(VariableAccess * variable, int value_register); + void gen_assignment(VariableAccess * variable, int value_register); }; void generate_code(Program * program) { @@ -32,25 +102,114 @@ void generate_code(Program * program) { FunctionDeclaration * function_declaration = function_list_node->item; CodeGenerator generator; generator.generate(function_declaration); + + std::cout << "3 Address Code for " << function_declaration->identifier->text << std::endl; + std::cout << "--------------------------" << std::endl; + generator.pretty_print(); + std::cout << "--------------------------" << std::endl; + std::cout << std::endl; + } + } +} + +void CodeGenerator::pretty_print() { + for (unsigned int i=0; itype) { + case Instruction::COPY: + { + CopyInstruction * copy_instruction = (CopyInstruction *) instruction; + std::cout << "$" << copy_instruction->dest << " = $" << copy_instruction->source << std::endl; + break; + } + case Instruction::OPERATOR: + { + OperatorInstruction * operator_instruction = (OperatorInstruction *) instruction; + std::cout << "$" << operator_instruction->dest << " = $" << operator_instruction->left << " "; + switch (operator_instruction->_operator) { + case OperatorInstruction::EQUAL: + std::cout << "=="; break; + case OperatorInstruction::NOT_EQUAL: + std::cout << "!="; break; + case OperatorInstruction::LESS: + std::cout << "<"; break; + case OperatorInstruction::GREATER: + std::cout << ">"; break; + case OperatorInstruction::LESS_EQUAL: + std::cout << "<="; break; + case OperatorInstruction::GREATER_EQUAL: + std::cout << ">="; break; + case OperatorInstruction::PLUS: + std::cout << "+"; break; + case OperatorInstruction::MINUS: + std::cout << "-"; break; + case OperatorInstruction::OR: + std::cout << "||"; break; + case OperatorInstruction::TIMES: + std::cout << "*"; break; + case OperatorInstruction::DIVIDE: + std::cout << "/"; break; + case OperatorInstruction::MOD: + std::cout << "%"; break; + case OperatorInstruction::AND: + std::cout << "&&"; break; + default: + assert(false); + } + std::cout << " $" << operator_instruction->right << std::endl; + break; + } + case Instruction::UNARY: + { + UnaryInstruction * unary_instruction = (UnaryInstruction *) instruction; + std::cout << "$" << unary_instruction->dest << " = "; + if (unary_instruction->_operator == UnaryInstruction::NEGATE) + std::cout << "-"; + else if (unary_instruction->_operator == UnaryInstruction::NOT) + std::cout << "!"; + else + assert(false); + std::cout << "$" << unary_instruction->source << std::endl; + break; + } + case Instruction::IMMEDIATE_BOOLEAN: + { + ImmediateBoolean * immediate_bool_instruction = (ImmediateBoolean *) instruction; + std::cout << "$" << immediate_bool_instruction->dest << " = " << (immediate_bool_instruction->constant ? "true" : "false") << std::endl; + break; + } + case Instruction::IMMEDIATE_INT: + { + ImmediateInteger * immediate_int_instruction = (ImmediateInteger *) instruction; + std::cout << "$" << immediate_int_instruction->dest << " = " << immediate_int_instruction->constant << std::endl; + break; + } } } } void CodeGenerator::generate(FunctionDeclaration * function_declaration) { - scan_statement_list(function_declaration->block->statement_list); + for (VariableDeclarationList * variable_list = function_declaration->block->variable_list; variable_list != NULL; variable_list = variable_list->next) { + for (IdentifierList * id_list = variable_list->item->id_list; id_list != NULL; id_list = id_list->next) + m_variable_numbers.put(id_list->item->text, next_available_register()); + } + + gen_statement_list(function_declaration->block->statement_list); } -void CodeGenerator::scan_statement_list(StatementList * statement_list) { - for (StatementList * statement_list_node = statement_list; statement_list_node != NULL; statement_list_node = statement_list_node->next) - scan_statement(statement_list_node->item); +void CodeGenerator::gen_statement_list(StatementList * statement_list) { + for (StatementList * statement_list_node = statement_list; statement_list_node != NULL; statement_list_node = statement_list_node->next) { + if (statement_list_node->item != NULL) + gen_statement(statement_list_node->item); + } } -void CodeGenerator::scan_statement(Statement * statement) { +void CodeGenerator::gen_statement(Statement * statement) { switch (statement->type) { case Statement::ASSIGNMENT: { - int value_register = scan_expression(statement->assignment->expression); - add_assignment(statement->assignment->variable, value_register); + int value_register = gen_expression(statement->assignment->expression); + gen_assignment(statement->assignment->variable, value_register); break; } /* @@ -88,15 +247,127 @@ void CodeGenerator::scan_statement(Statement * statement) { } -int CodeGenerator::scan_expression(Expression * expression) { - return 0; +int CodeGenerator::gen_expression(Expression * expression) { + if (expression->right == NULL) { + // it's just the type of the first additive expression + return gen_additive_expression(expression->left); + } else { + // we're looking at a compare operator + int left = gen_additive_expression(expression->left); + int right = gen_additive_expression(expression->right); + int dest = next_available_register(); + OperatorInstruction::Operator _operator = (OperatorInstruction::Operator)(expression->_operator->type + OperatorInstruction::EQUAL); // LOL HAX! + m_instructions.push_back(new OperatorInstruction(dest, left, _operator, right)); + return dest; + } +} + +int CodeGenerator::gen_additive_expression(AdditiveExpression * additive_expression) { + int right = gen_multiplicitive_expression(additive_expression->right); + + if (additive_expression->left == NULL) { + // pass the right through + return right; + } else { + int left = gen_additive_expression(additive_expression->left); + int dest = next_available_register(); + OperatorInstruction::Operator _operator = (OperatorInstruction::Operator)(additive_expression->_operator->type + OperatorInstruction::PLUS); + m_instructions.push_back(new OperatorInstruction(dest, left, _operator, right)); + return dest; + } +} + +int CodeGenerator::gen_multiplicitive_expression(MultiplicativeExpression * multiplicative_expression) { + int right = gen_negatable_expression(multiplicative_expression->right); + + if (multiplicative_expression->left == NULL) { + // pass the right through + return right; + } else { + int left = gen_multiplicitive_expression(multiplicative_expression->left); + int dest = next_available_register(); + OperatorInstruction::Operator _operator = (OperatorInstruction::Operator)(multiplicative_expression->_operator->type + OperatorInstruction::TIMES); + m_instructions.push_back(new OperatorInstruction(dest, left, _operator, right)); + return dest; + } +} + +int CodeGenerator::gen_negatable_expression(NegatableExpression * negatable_expression) { + if (negatable_expression->type == NegatableExpression::PRIMARY) { + return gen_primary_expression(negatable_expression->primary_expression); + } else if (negatable_expression->type == NegatableExpression::SIGN) { + int source = gen_negatable_expression(negatable_expression->next); + int dest = next_available_register(); + m_instructions.push_back(new UnaryInstruction(dest, UnaryInstruction::NEGATE, source)); + return dest; + } else { + assert(false); + return -1; + } +} + +int CodeGenerator::gen_primary_expression(PrimaryExpression * primary_expression) { + switch (primary_expression->type) { + case PrimaryExpression::VARIABLE: + return gen_variable_access(primary_expression->variable); + case PrimaryExpression::INTEGER: + { + int dest = next_available_register(); + int constant = primary_expression->literal_integer->value; + m_instructions.push_back(new ImmediateInteger(dest, constant)); + return dest; + } + case PrimaryExpression::BOOLEAN: + { + int dest = next_available_register(); + bool constant = primary_expression->literal_boolean->value; + m_instructions.push_back(new ImmediateBoolean(dest, constant)); + return dest; + } + case PrimaryExpression::PARENS: + return gen_expression(primary_expression->parens_expression); + case PrimaryExpression::NOT: + { + int dest = next_available_register(); + int source = gen_primary_expression(primary_expression->not_expression); + m_instructions.push_back(new UnaryInstruction(dest, UnaryInstruction::NOT, source)); + return dest; + } + /* + case PrimaryExpression::REAL: + case PrimaryExpression::STRING: + case PrimaryExpression::FUNCTION: + case PrimaryExpression::METHOD: + case PrimaryExpression::OBJECT_INSTANTIATION: + */ + + default: + assert(false); + } } +int CodeGenerator::gen_variable_access(VariableAccess * variable) { + switch (variable->type) { + case VariableAccess::IDENTIFIER: + return m_variable_numbers.get(variable->identifier->text); + /* + case VariableAccess::INDEXED_VARIABLE: + return check_indexed_variable(variable_access->indexed_variable); + case VariableAccess::ATTRIBUTE: + return check_attribute_designator(variable_access->attribute); + case VariableAccess::THIS: + return new TypeDenoter(m_symbol_table->item(m_class_id)->class_declaration->identifier); + */ + default: + assert(false); + } +} -void CodeGenerator::add_assignment(VariableAccess * variable, int value_register) { +void CodeGenerator::gen_assignment(VariableAccess * variable, int value_register) { switch (variable->type) { case VariableAccess::IDENTIFIER: { + m_instructions.push_back(new CopyInstruction(m_variable_numbers.get(variable->identifier->text), value_register)); break; } /* diff --git a/insensitive_map.h b/insensitive_map.h index 2a1da57..aba2d72 100644 --- a/insensitive_map.h +++ b/insensitive_map.h @@ -16,8 +16,8 @@ class OrderedInsensitiveMap { int count() { return m_vector.size(); } bool has_key(std::string x) { return m_map.count(Utils::to_lower(x)) > 0; } - T item(std::string x) { return m_map[Utils::to_lower(x)]; } - T item(int i) { return m_vector[i]; } + T get(std::string x) { return m_map[Utils::to_lower(x)]; } + T get(int i) { return m_vector[i]; } void put(std::string key, T value); }; diff --git a/semantic_checker.cpp b/semantic_checker.cpp index f4e5422..dcc1ae9 100644 --- a/semantic_checker.cpp +++ b/semantic_checker.cpp @@ -21,10 +21,10 @@ bool SemanticChecker::internal_check() { // check the main class and constructor if (m_symbol_table->has_key(m_program->identifier->text)) { - ClassSymbolTable * class_symbols = m_symbol_table->item(m_program->identifier->text); + ClassSymbolTable * class_symbols = m_symbol_table->get(m_program->identifier->text); if (class_symbols->function_symbols->has_key(m_program->identifier->text)) { // make sure it has no parameters - FunctionSymbolTable * function_symbols = class_symbols->function_symbols->item(m_program->identifier->text); + FunctionSymbolTable * function_symbols = class_symbols->function_symbols->get(m_program->identifier->text); if (function_symbols->function_declaration->parameter_list != NULL) { std::cerr << err_header(function_symbols->function_declaration->identifier->line_number) << "constructor for main class \"" << class_symbols->class_declaration->identifier->text << @@ -48,7 +48,7 @@ bool SemanticChecker::internal_check() m_class_id = class_declaration->identifier->text; check_variable_declaration_list(class_declaration->class_block->variable_list); - + // check functions for (FunctionDeclarationList * function_list = class_declaration->class_block->function_list; function_list != NULL; function_list = function_list->next) { FunctionDeclaration * function_declaration = function_list->item; @@ -141,19 +141,19 @@ bool SemanticChecker::is_ancestor(TypeDenoter * child, TypeDenoter * ancestor) if (child->class_identifier->text.compare(ancestor->class_identifier->text) == 0) { return true; } else { - ClassDeclaration * child_declaration = m_symbol_table->item(child->class_identifier->text)->class_declaration; + ClassDeclaration * child_declaration = m_symbol_table->get(child->class_identifier->text)->class_declaration; if (child_declaration->parent_identifier == NULL) return false; return is_ancestor(new TypeDenoter(child_declaration->parent_identifier), ancestor); } } -bool SemanticChecker::structurally_equivalent(TypeDenoter * left_type, TypeDenoter * right_type) +bool SemanticChecker::structurally_equivalent(TypeDenoter * left_type, TypeDenoter * right_type) { assert(left_type->type == TypeDenoter::CLASS); assert(right_type->type == TypeDenoter::CLASS); - VariableTable * left_fields = m_symbol_table->item(left_type->class_identifier->text)->variables; - VariableTable * right_fields = m_symbol_table->item(right_type->class_identifier->text)->variables; + VariableTable * left_fields = m_symbol_table->get(left_type->class_identifier->text)->variables; + VariableTable * right_fields = m_symbol_table->get(right_type->class_identifier->text)->variables; for (int i=0; i < left_fields->count() || i < right_fields->count(); ++i) { // if we get past the end of one of them, they have differing numbers of fields. if (i >= left_fields->count()) @@ -161,7 +161,7 @@ bool SemanticChecker::structurally_equivalent(TypeDenoter * left_type, TypeDenot if (i >= right_fields->count()) return false; // each field has to be assignment compatible - if (! assignment_valid(left_fields->item(i)->type, right_fields->item(i)->type)) + if (! assignment_valid(left_fields->get(i)->type, right_fields->get(i)->type)) return false; } @@ -410,20 +410,20 @@ TypeDenoter * SemanticChecker::check_variable_access(VariableAccess * variable_a { // it's the type of the declaration // figure out what variable this is referencing - ClassSymbolTable * class_symbols = m_symbol_table->item(m_class_id); - FunctionSymbolTable * function_symbols = class_symbols->function_symbols->item(m_function_id); + ClassSymbolTable * class_symbols = m_symbol_table->get(m_class_id); + FunctionSymbolTable * function_symbols = class_symbols->function_symbols->get(m_function_id); if (function_symbols->variables->has_key(variable_access->identifier->text)) { // local variable or parameter if (! allow_function_return_value) { // if it's the function return value, we need explicit permission if (Utils::insensitive_equals(function_symbols->function_declaration->identifier->text, variable_access->identifier->text)) { - std::cerr << err_header(variable_access->identifier->line_number) << + std::cerr << err_header(variable_access->identifier->line_number) << "cannot read from \"" << variable_access->identifier->text << "\" because it is reserved for use as the function return value" << std::endl; m_success = false; } } - return function_symbols->variables->item(variable_access->identifier->text)->type; + return function_symbols->variables->get(variable_access->identifier->text)->type; } else { TypeDenoter * type = class_variable_type(m_class_id, variable_access->identifier); if (type == NULL) { @@ -444,7 +444,7 @@ TypeDenoter * SemanticChecker::check_variable_access(VariableAccess * variable_a case VariableAccess::ATTRIBUTE: return check_attribute_designator(variable_access->attribute); case VariableAccess::THIS: - return new TypeDenoter(m_symbol_table->item(m_class_id)->class_declaration->identifier); + return new TypeDenoter(m_symbol_table->get(m_class_id)->class_declaration->identifier); default: assert(false); return NULL; @@ -453,9 +453,9 @@ TypeDenoter * SemanticChecker::check_variable_access(VariableAccess * variable_a TypeDenoter * SemanticChecker::class_variable_type(std::string class_name, Identifier * variable) { - ClassSymbolTable * class_symbols = m_symbol_table->item(class_name); + ClassSymbolTable * class_symbols = m_symbol_table->get(class_name); if (class_symbols->variables->has_key(variable->text)) { - return class_symbols->variables->item(variable->text)->type; + return class_symbols->variables->get(variable->text)->type; } else if (class_symbols->class_declaration->parent_identifier == NULL) { return NULL; } else { @@ -465,9 +465,9 @@ TypeDenoter * SemanticChecker::class_variable_type(std::string class_name, Ident FunctionDeclaration * SemanticChecker::class_method(std::string class_name, FunctionDesignator * function_designator) { - ClassSymbolTable * class_symbols = m_symbol_table->item(class_name); + ClassSymbolTable * class_symbols = m_symbol_table->get(class_name); if (class_symbols->function_symbols->has_key(function_designator->identifier->text)) { - return class_symbols->function_symbols->item(function_designator->identifier->text)->function_declaration; + return class_symbols->function_symbols->get(function_designator->identifier->text)->function_declaration; } else if (class_symbols->class_declaration->parent_identifier == NULL) { return NULL; } else { @@ -518,7 +518,7 @@ TypeDenoter * SemanticChecker::check_function_designator(FunctionDesignator * fu } } } - + return function_declaration->type; } } diff --git a/symbol_table.cpp b/symbol_table.cpp index 04fa8d8..ef71f86 100644 --- a/symbol_table.cpp +++ b/symbol_table.cpp @@ -28,7 +28,7 @@ SymbolTable * build_symbol_table(Program * program) { // add the class to symbol table if (symbol_table->has_key(class_declaration->identifier->text)) { - ClassDeclaration * other_class = symbol_table->item(class_declaration->identifier->text)->class_declaration; + ClassDeclaration * other_class = symbol_table->get(class_declaration->identifier->text)->class_declaration; std::cerr << err_header(class_declaration->identifier->line_number) << "class \"" << other_class->identifier->text << "\" already declared at line " << other_class->identifier->line_number << std::endl; @@ -39,12 +39,12 @@ SymbolTable * build_symbol_table(Program * program) { } // add each class variable to symbol table - OrderedInsensitiveMap * variables = symbol_table->item(class_declaration->identifier->text)->variables; + OrderedInsensitiveMap * variables = symbol_table->get(class_declaration->identifier->text)->variables; for (VariableDeclarationList * variable_list = class_declaration->class_block->variable_list; variable_list != NULL; variable_list = variable_list->next) { VariableDeclaration * variable_declaration = variable_list->item; for (IdentifierList * id_list = variable_declaration->id_list; id_list != NULL; id_list = id_list->next) { if (variables->has_key(id_list->item->text)) { - VariableData * other_variable = variables->item(id_list->item->text); + VariableData * other_variable = variables->get(id_list->item->text); std::cerr << err_header(id_list->item->line_number) << "variable \"" << id_list->item->text << "\" already declared at line " << other_variable->line_number << std::endl; @@ -56,7 +56,7 @@ SymbolTable * build_symbol_table(Program * program) { } // for each function - OrderedInsensitiveMap * function_symbols = symbol_table->item(class_declaration->identifier->text)->function_symbols; + OrderedInsensitiveMap * function_symbols = symbol_table->get(class_declaration->identifier->text)->function_symbols; for (FunctionDeclarationList * function_list = class_declaration->class_block->function_list; function_list != NULL; function_list = function_list->next) { FunctionDeclaration * function_declaration = function_list->item; @@ -64,12 +64,12 @@ SymbolTable * build_symbol_table(Program * program) { if (function_symbols->has_key(function_declaration->identifier->text)) { std::cerr << err_header(function_declaration->identifier->line_number) << "function \"" << function_declaration->identifier->text << "\" already declared at line " << - function_symbols->item(function_declaration->identifier->text)->function_declaration->identifier->line_number << std::endl; + function_symbols->get(function_declaration->identifier->text)->function_declaration->identifier->line_number << std::endl; success = false; continue; } function_symbols->put(function_declaration->identifier->text, new FunctionSymbolTable(function_declaration)); - OrderedInsensitiveMap * function_variables = function_symbols->item(function_declaration->identifier->text)->variables; + OrderedInsensitiveMap * function_variables = function_symbols->get(function_declaration->identifier->text)->variables; // add the function name to function symbol table function_variables->put(function_declaration->identifier->text, @@ -139,7 +139,7 @@ SymbolTable * build_symbol_table(Program * program) { } bool inheritance_loop(SymbolTable * symbol_table, std::string class_name) { - ClassSymbolTable * class_symbols = symbol_table->item(class_name); + ClassSymbolTable * class_symbols = symbol_table->get(class_name); return inheritance_loop(symbol_table, class_name, class_symbols->class_declaration->parent_identifier->text); } @@ -148,7 +148,7 @@ bool inheritance_loop(SymbolTable * symbol_table, std::string original_class, st return false; if (Utils::insensitive_equals(original_class, current_class)) return true; - ClassSymbolTable * class_symbols = symbol_table->item(current_class); + ClassSymbolTable * class_symbols = symbol_table->get(current_class); if (class_symbols->class_declaration->parent_identifier == NULL) return false; return inheritance_loop(symbol_table, original_class, class_symbols->class_declaration->parent_identifier->text); @@ -157,9 +157,9 @@ bool inheritance_loop(SymbolTable * symbol_table, std::string original_class, st FunctionDeclaration * get_method(SymbolTable * symbol_table, std::string class_name, std::string method_name) { if (! symbol_table->has_key(class_name)) return NULL; - ClassSymbolTable * class_symbols = symbol_table->item(class_name); + ClassSymbolTable * class_symbols = symbol_table->get(class_name); if (class_symbols->function_symbols->has_key(method_name)) { - return class_symbols->function_symbols->item(method_name)->function_declaration; + return class_symbols->function_symbols->get(method_name)->function_declaration; } else if (class_symbols->class_declaration->parent_identifier == NULL) { return NULL; } else { @@ -171,9 +171,9 @@ FunctionDeclaration * get_method(SymbolTable * symbol_table, std::string class_n VariableData * get_field(SymbolTable * symbol_table, std::string class_name, std::string field_name) { if (! symbol_table->has_key(class_name)) return NULL; - ClassSymbolTable * class_symbols = symbol_table->item(class_name); + ClassSymbolTable * class_symbols = symbol_table->get(class_name); if (class_symbols->variables->has_key(field_name)) { - return class_symbols->variables->item(field_name); + return class_symbols->variables->get(field_name); } else if (class_symbols->class_declaration->parent_identifier == NULL) { return NULL; } else { @@ -193,7 +193,7 @@ bool add_variables(OrderedInsensitiveMap * function_variables, V } else { std::cerr << err_header(id_list->item->line_number) << "variable \"" << id_list->item->text << "\" already declared at line " << - function_variables->item(id_list->item->text)->line_number << std::endl; + function_variables->get(id_list->item->text)->line_number << std::endl; } success = false; } diff --git a/tests/control_flow/simple.p b/tests/control_flow/simple.p index 92dd1bf..f481cd8 100644 --- a/tests/control_flow/simple.p +++ b/tests/control_flow/simple.p @@ -2,10 +2,12 @@ program Main; class Main begin function Main; var a, b, c : Integer; + var z, y, x : Boolean; begin a := 1; b := 2; - print a + b; + c := a + b; + z := a < b; end end .