#include "coercion.h" #include "messages.h" #include "types.h" #include "Node.h" #include "SyntaxTree.h" #include "Symbol.h" #include extern int lineno; // declared in comp.l extern SyntaxTree *tree; // declared in comp.y extern Messages messages; // declared in comp.y ReturnType minimumtype(ReturnType lhs, ReturnType rhs) { if (lhs == RT_REAL || rhs == RT_REAL) { return RT_REAL; } else { return RT_INT; } } void checkType(ReturnType expected, ReturnType actual) { if (actual != expected) { messages.TypeError(lineno, expected, actual); } } void checkType(ReturnType expected, Node *expression) { checkType(expected, expression->GetReturnType()); } Node *coerce(ReturnType to, Node *expression) { if (to == RT_ERROR) { /* ignore coercions to error type */ return expression; } assert(expression != NULL); ReturnType from = expression->GetReturnType(); if (from == to) { /* no coercion needed */ return expression; } if (from == RT_ERROR) { /* always coerce error type */ return tree->CreateParentNode(NODE_COERCION, to, expression); } if (from == RT_INT && to == RT_REAL) { /* coerce integer to real */ messages.CoercionWarning(lineno, to, from); return tree->CreateParentNode(NODE_COERCION, to, expression); } if (from == RT_INT && to == RT_BOOL) { /* coerce integer to bool */ messages.CoercionWarning(lineno, to, from); return tree->CreateParentNode(NODE_COERCION, to, expression); } if (from == RT_BOOL && to == RT_INT) { /* ../tests/varia/bitwise.p0: coerce bool to integer */ messages.CoercionWarning(lineno, to, from); return tree->CreateParentNode(NODE_COERCION, to, expression); } /* no coercion possible */ messages.TypeError(lineno, to, from); return expression; } void check_parameters(Node *call_node) { assert(call_node != NULL); assert(call_node->GetNodeType() == NODE_PROCCALL || call_node->GetNodeType() == NODE_FUNCTIONCALL); Node *expression_list = call_node->GetRightChild(); assert(expression_list->GetNodeType() == NODE_EXPRLIST || expression_list->GetNodeType() == NODE_EMPTY); Node *node_id = call_node->GetLeftChild(); assert(node_id->GetNodeType() == NODE_ID); Symbol *symbol = node_id->GetSymbol(); assert(symbol->GetSymbolType() == ST_PROCEDURE || symbol->GetSymbolType() == ST_FUNCTION); if (symbol->GetReturnType() == RT_ERROR) { return; } /* Go through parameters */ int parametercount = 0; while (expression_list->GetNodeType() != NODE_EMPTY) { ++parametercount; if (parametercount > symbol->GetParameterCount()) { break; } /* Check parameter and add coercion if necessary */ ReturnType wanted = symbol->GetParameter(parametercount-1)->GetReturnType(); Node *coerced_node = coerce(wanted, expression_list->GetLeftChild()); expression_list->SetLeftChild(coerced_node); /* Next parameter */ expression_list = expression_list->GetRightChild(); assert(expression_list->GetNodeType() == NODE_EXPRLIST || expression_list->GetNodeType() == NODE_EMPTY); } if (parametercount != symbol->GetParameterCount()) { messages.ParamCountError(lineno, parametercount, symbol); } }