Permalink
Browse files

parser and semantic checker are inserting implicit 'this' references

  • Loading branch information...
1 parent a221c6d commit 07445a83903d8936be7844cc7ab8e2d28cb4bb68 @thejoshwolfe thejoshwolfe committed Dec 5, 2010
Showing with 61 additions and 87 deletions.
  1. +2 −9 parser.h
  2. +8 −4 pascal.y
  3. +51 −73 semantic_checker.cpp
  4. +0 −1 semantic_checker.h
View
@@ -157,22 +157,17 @@ struct StatementList {
struct Statement {
// don't change this enum without changing the corresponding one in CodeGenerator
- enum Type {FUNCTION, METHOD, ASSIGNMENT, IF, PRINT, WHILE, COMPOUND, ATTRIBUTE};
+ enum Type {METHOD, ASSIGNMENT, IF, PRINT, WHILE, COMPOUND};
Type type;
union {
- FunctionDesignator * function;
MethodDesignator * method;
- // hack to have methods with no parentheses
- AttributeDesignator * attribute;
AssignmentStatement * assignment;
IfStatement * if_statement;
PrintStatement * print_statement;
WhileStatement * while_statement;
StatementList * compound_statement;
};
- Statement(FunctionDesignator * function) : type(FUNCTION), function(function) {}
Statement(MethodDesignator * method) : type(METHOD), method(method) {}
- Statement(AttributeDesignator * attribute) : type(ATTRIBUTE), attribute(attribute) {}
Statement(AssignmentStatement * assignment) : type(ASSIGNMENT), assignment(assignment) {}
Statement(IfStatement * if_statement) : type(IF), if_statement(if_statement) {}
Statement(PrintStatement * print_statement) : type(PRINT), print_statement(print_statement) {}
@@ -317,15 +312,14 @@ struct NegatableExpression {
struct PrimaryExpression {
// don't change this enum without changing the corresponding one in CodeGenerator
- enum Type {INTEGER, REAL, STRING, BOOLEAN, VARIABLE, FUNCTION, METHOD, OBJECT_INSTANTIATION, PARENS, NOT};
+ enum Type {INTEGER, REAL, STRING, BOOLEAN, VARIABLE, METHOD, OBJECT_INSTANTIATION, PARENS, NOT};
int type;
union {
LiteralInteger * literal_integer;
LiteralReal * literal_real;
LiteralString * literal_string;
LiteralBoolean * literal_boolean;
VariableAccess * variable;
- FunctionDesignator * function;
MethodDesignator * method;
ObjectInstantiation * object_instantiation;
Expression * parens_expression;
@@ -337,7 +331,6 @@ struct PrimaryExpression {
PrimaryExpression(LiteralString * literal_string) : type(STRING), literal_string(literal_string) {}
PrimaryExpression(LiteralBoolean * literal_boolean) : type(BOOLEAN), literal_boolean(literal_boolean) {}
PrimaryExpression(VariableAccess * variable) : type(VARIABLE), variable(variable) {}
- PrimaryExpression(FunctionDesignator * function) : type(FUNCTION), function(function) {}
PrimaryExpression(MethodDesignator * method) : type(METHOD), method(method) {}
PrimaryExpression(ObjectInstantiation * object_instantiation)
: type(OBJECT_INSTANTIATION), object_instantiation(object_instantiation) {}
View
@@ -255,11 +255,13 @@ statement_list : statement KEYWORD_SEMICOLON statement_list {
};
statement : function_designator {
- $$ = new Statement($1);
+ // convert "a(...)" to "this.a(...)"
+ $$ = new Statement(new MethodDesignator(new VariableAccess(VariableAccess::THIS), $1));
} | method_designator {
$$ = new Statement($1);
} | attribute_designator {
- $$ = new Statement($1);
+ // convert "a.b" to "a.b()"
+ $$ = new Statement(new MethodDesignator($1->owner, new FunctionDesignator($1->identifier, NULL)));
} | assignment_statement {
$$ = new Statement($1);
} | if_statement {
@@ -271,7 +273,8 @@ statement : function_designator {
} | compound_statement {
$$ = new Statement($1);
} | TOKEN_IDENTIFIER {
- $$ = new Statement(new FunctionDesignator($1, NULL));
+ // convert "a" to "this.a()"
+ $$ = new Statement(new MethodDesignator(new VariableAccess(VariableAccess::THIS), new FunctionDesignator($1, NULL)));
} | {
$$ = NULL;
};
@@ -389,7 +392,8 @@ primary_expression : TOKEN_LITERAL_INTEGER {
} | variable_access {
$$ = new PrimaryExpression($1);
} | function_designator {
- $$ = new PrimaryExpression($1);
+ // convert "a()" to "this.a()"
+ $$ = new PrimaryExpression(new MethodDesignator(new VariableAccess(VariableAccess::THIS), $1));
} | method_designator {
$$ = new PrimaryExpression($1);
} | object_instantiation {
View
@@ -315,13 +315,6 @@ void SemanticChecker::check_statement(Statement * statement)
case Statement::METHOD:
check_method_designator(statement->method);
break;
- case Statement::FUNCTION:
- check_function_designator(statement->function);
- break;
- case Statement::ATTRIBUTE:
- // actually this is a method call
- check_method_designator(new MethodDesignator(statement->attribute->owner, new FunctionDesignator(statement->attribute->identifier, NULL)));
- break;
default:
assert(false);
}
@@ -463,9 +456,6 @@ TypeDenoter * SemanticChecker::check_primary_expression(PrimaryExpression * prim
}
break;
}
- case PrimaryExpression::FUNCTION:
- type = check_function_designator(primary_expression->function);
- break;
case PrimaryExpression::METHOD:
type = check_method_designator(primary_expression->method);
break;
@@ -507,20 +497,20 @@ TypeDenoter * SemanticChecker::check_variable_access(VariableAccess * variable_a
}
}
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) {
- // undeclared variable
- std::cerr << err_header(variable_access->identifier->line_number) <<
- "variable \"" << variable_access->identifier->text << "\" not declared" << std::endl;
- m_success = false;
- return NULL;
- } else {
- // class variable
- return type;
- }
}
- break;
+ TypeDenoter * type = class_variable_type(m_class_id, variable_access->identifier);
+ if (type != NULL) {
+ // class variable
+ // convert "a" to "this.a"
+ variable_access->type = VariableAccess::ATTRIBUTE;
+ variable_access->attribute = new AttributeDesignator(new VariableAccess(VariableAccess::THIS), variable_access->identifier);
+ return type;
+ }
+ // undeclared variable
+ std::cerr << err_header(variable_access->identifier->line_number) <<
+ "variable \"" << variable_access->identifier->text << "\" not declared" << std::endl;
+ m_success = false;
+ return NULL;
}
case VariableAccess::INDEXED_VARIABLE:
return check_indexed_variable(variable_access->indexed_variable);
@@ -558,67 +548,55 @@ FunctionDeclaration * SemanticChecker::class_method(std::string class_name, Func
}
}
-TypeDenoter * SemanticChecker::check_function_designator(FunctionDesignator * function_designator)
+TypeDenoter * SemanticChecker::check_method_designator(MethodDesignator * method_designator)
{
- // trace the class hierarchy until we find (or don't find) the function to call
- FunctionDeclaration * function_declaration = class_method(m_class_id, function_designator);
+ FunctionDesignator * function_designator = method_designator->function;
+
+ TypeDenoter * owner_type = check_variable_access(method_designator->owner);
+ assert(owner_type->type == TypeDenoter::CLASS);
+ FunctionDeclaration * function_declaration = class_method(owner_type->class_identifier->text, function_designator);
if (function_declaration == NULL) {
std::cerr << err_header(function_designator->identifier->line_number) <<
- "function \"" << function_designator->identifier->text << "\" not declared" << std::endl;
+ "class \"" << owner_type->class_identifier->text << "\" has no method \"" << function_designator->identifier->text << "\"" << std::endl;
m_success = false;
return NULL;
- } else {
- // check signature
- int parameter_index = 0;
- ExpressionList * actual_parameter_list = function_designator->parameter_list;
- VariableDeclarationList * formal_parameter_list = function_declaration->parameter_list;
- for (;actual_parameter_list != NULL || formal_parameter_list != NULL;
- actual_parameter_list = actual_parameter_list->next,
- formal_parameter_list = formal_parameter_list->next,
- ++parameter_index)
- {
- if (actual_parameter_list == NULL) {
- std::cerr << err_header(function_designator->identifier->line_number) <<
- "too few arguments to function \"" << function_designator->identifier->text << "\"" << std::endl;
- m_success = false;
- break;
- } else if (formal_parameter_list == NULL) {
+ }
+
+ // check signature
+ int parameter_index = 0;
+ ExpressionList * actual_parameter_list = function_designator->parameter_list;
+ VariableDeclarationList * formal_parameter_list = function_declaration->parameter_list;
+ for (;actual_parameter_list != NULL || formal_parameter_list != NULL;
+ actual_parameter_list = actual_parameter_list->next,
+ formal_parameter_list = formal_parameter_list->next,
+ ++parameter_index)
+ {
+ if (actual_parameter_list == NULL) {
+ std::cerr << err_header(function_designator->identifier->line_number) <<
+ "too few arguments to function \"" << function_designator->identifier->text << "\"" << std::endl;
+ m_success = false;
+ break;
+ } else if (formal_parameter_list == NULL) {
+ std::cerr << err_header(function_designator->identifier->line_number) <<
+ "too many arguments to function \"" << function_designator->identifier->text << "\"" << std::endl;
+ m_success = false;
+ break;
+ } else {
+ TypeDenoter * formal_type = formal_parameter_list->item->type;
+ TypeDenoter * actual_type = check_expression(actual_parameter_list->item);
+ if (formal_type == NULL || actual_type == NULL)
+ continue;
+ if (! assignment_valid(formal_type, actual_type)) {
std::cerr << err_header(function_designator->identifier->line_number) <<
- "too many arguments to function \"" << function_designator->identifier->text << "\"" << std::endl;
+ "function \"" << function_designator->identifier->text << "\": " <<
+ "parameter index " << parameter_index << ": cannot convert \"" <<
+ type_to_string(actual_type) << "\" to \"" << type_to_string(formal_type) << "\"" << std::endl;
m_success = false;
- break;
- } else {
- TypeDenoter * formal_type = formal_parameter_list->item->type;
- TypeDenoter * actual_type = check_expression(actual_parameter_list->item);
- if (formal_type == NULL || actual_type == NULL)
- continue;
- if (! assignment_valid(formal_type, actual_type)) {
- std::cerr << err_header(function_designator->identifier->line_number) <<
- "function \"" << function_designator->identifier->text << "\": " <<
- "parameter index " << parameter_index << ": cannot convert \"" <<
- type_to_string(actual_type) << "\" to \"" << type_to_string(formal_type) << "\"" << std::endl;
- m_success = false;
- }
}
}
-
- return function_declaration->type;
}
-}
-TypeDenoter * SemanticChecker::check_method_designator(MethodDesignator * method_designator)
-{
- TypeDenoter * owner_type = check_variable_access(method_designator->owner);
- assert(owner_type->type == TypeDenoter::CLASS);
- FunctionDeclaration * function_declaration = class_method(owner_type->class_identifier->text, method_designator->function);
- if (function_declaration == NULL) {
- std::cerr << err_header(method_designator->function->identifier->line_number) <<
- "class \"" << owner_type->class_identifier->text << "\" has no method \"" << method_designator->function->identifier->text << "\"" << std::endl;
- m_success = false;
- return NULL;
- } else {
- return function_declaration->type;
- }
+ return function_declaration->type;
}
TypeDenoter * SemanticChecker::check_object_instantiation(ObjectInstantiation * object_instantiation)
View
@@ -42,7 +42,6 @@ class SemanticChecker {
TypeDenoter * check_negatable_expression(NegatableExpression * negatable_expression);
TypeDenoter * check_primary_expression(PrimaryExpression * primary_expression);
TypeDenoter * check_variable_access(VariableAccess * variable_access, bool allow_function_return_value = false);
- TypeDenoter * check_function_designator(FunctionDesignator * function_designator);
TypeDenoter * check_method_designator(MethodDesignator * method_designator);
TypeDenoter * check_object_instantiation(ObjectInstantiation * object_instantiation);
TypeDenoter * check_indexed_variable(IndexedVariable * indexed_variable);

0 comments on commit 07445a8

Please sign in to comment.