Skip to content

Commit

Permalink
parser and semantic checker are inserting implicit 'this' references
Browse files Browse the repository at this point in the history
  • Loading branch information
thejoshwolfe committed Dec 5, 2010
1 parent a221c6d commit 07445a8
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 87 deletions.
11 changes: 2 additions & 9 deletions parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) {}
Expand Down Expand Up @@ -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;
Expand All @@ -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) {}
Expand Down
12 changes: 8 additions & 4 deletions pascal.y
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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;
};
Expand Down Expand Up @@ -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 {
Expand Down
124 changes: 51 additions & 73 deletions semantic_checker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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)
Expand Down
1 change: 0 additions & 1 deletion semantic_checker.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 07445a8

Please sign in to comment.