[2] | 1 | #include "coercion.h"
|
---|
| 2 | #include "messages.h"
|
---|
| 3 | #include "types.h"
|
---|
| 4 | #include "Node.h"
|
---|
| 5 | #include "SyntaxTree.h"
|
---|
| 6 | #include "Symbol.h"
|
---|
| 7 | #include <assert.h>
|
---|
| 8 |
|
---|
| 9 | extern int lineno; // declared in comp.l
|
---|
| 10 | extern SyntaxTree *tree; // declared in comp.y
|
---|
| 11 | extern Messages messages; // declared in comp.y
|
---|
| 12 |
|
---|
| 13 | ReturnType minimumtype(ReturnType lhs, ReturnType rhs)
|
---|
| 14 | {
|
---|
| 15 | if (lhs == RT_REAL || rhs == RT_REAL) {
|
---|
| 16 | return RT_REAL;
|
---|
| 17 | } else {
|
---|
| 18 | return RT_INT;
|
---|
| 19 | }
|
---|
| 20 | }
|
---|
| 21 |
|
---|
| 22 | void checkType(ReturnType expected, ReturnType actual) {
|
---|
| 23 | if (actual != expected) {
|
---|
| 24 | messages.TypeError(lineno, expected, actual);
|
---|
| 25 | }
|
---|
| 26 | }
|
---|
| 27 |
|
---|
| 28 | void checkType(ReturnType expected, Node *expression) {
|
---|
| 29 | checkType(expected, expression->GetReturnType());
|
---|
| 30 | }
|
---|
| 31 |
|
---|
| 32 | Node *coerce(ReturnType to, Node *expression)
|
---|
| 33 | {
|
---|
| 34 | if (to == RT_ERROR) {
|
---|
| 35 | /* ignore coercions to error type */
|
---|
| 36 | return expression;
|
---|
| 37 | }
|
---|
| 38 |
|
---|
| 39 | assert(expression != NULL);
|
---|
| 40 | ReturnType from = expression->GetReturnType();
|
---|
| 41 |
|
---|
| 42 | if (from == to) {
|
---|
| 43 | /* no coercion needed */
|
---|
| 44 | return expression;
|
---|
| 45 | }
|
---|
| 46 |
|
---|
| 47 | if (from == RT_ERROR) {
|
---|
| 48 | /* always coerce error type */
|
---|
| 49 | return tree->CreateParentNode(NODE_COERCION, to, expression);
|
---|
| 50 | }
|
---|
| 51 |
|
---|
| 52 | if (from == RT_INT && to == RT_REAL) {
|
---|
| 53 | /* coerce integer to real */
|
---|
| 54 | messages.CoercionWarning(lineno, to, from);
|
---|
| 55 | return tree->CreateParentNode(NODE_COERCION, to, expression);
|
---|
| 56 | }
|
---|
| 57 |
|
---|
| 58 | if (from == RT_INT && to == RT_BOOL) {
|
---|
| 59 | /* coerce integer to bool */
|
---|
| 60 | messages.CoercionWarning(lineno, to, from);
|
---|
| 61 | return tree->CreateParentNode(NODE_COERCION, to, expression);
|
---|
| 62 | }
|
---|
| 63 |
|
---|
| 64 | if (from == RT_BOOL && to == RT_INT) {
|
---|
| 65 | /* ../tests/varia/bitwise.p0: coerce bool to integer */
|
---|
| 66 | messages.CoercionWarning(lineno, to, from);
|
---|
| 67 | return tree->CreateParentNode(NODE_COERCION, to, expression);
|
---|
| 68 | }
|
---|
| 69 |
|
---|
| 70 | /* no coercion possible */
|
---|
| 71 | messages.TypeError(lineno, to, from);
|
---|
| 72 | return expression;
|
---|
| 73 | }
|
---|
| 74 |
|
---|
| 75 | void check_parameters(Node *call_node)
|
---|
| 76 | {
|
---|
| 77 | assert(call_node != NULL);
|
---|
| 78 | assert(call_node->GetNodeType() == NODE_PROCCALL ||
|
---|
| 79 | call_node->GetNodeType() == NODE_FUNCTIONCALL);
|
---|
| 80 |
|
---|
| 81 | Node *expression_list = call_node->GetRightChild();
|
---|
| 82 | assert(expression_list->GetNodeType() == NODE_EXPRLIST ||
|
---|
| 83 | expression_list->GetNodeType() == NODE_EMPTY);
|
---|
| 84 |
|
---|
| 85 | Node *node_id = call_node->GetLeftChild();
|
---|
| 86 | assert(node_id->GetNodeType() == NODE_ID);
|
---|
| 87 |
|
---|
| 88 | Symbol *symbol = node_id->GetSymbol();
|
---|
| 89 | assert(symbol->GetSymbolType() == ST_PROCEDURE ||
|
---|
| 90 | symbol->GetSymbolType() == ST_FUNCTION);
|
---|
| 91 | if (symbol->GetReturnType() == RT_ERROR) {
|
---|
| 92 | return;
|
---|
| 93 | }
|
---|
| 94 |
|
---|
| 95 | /* Go through parameters */
|
---|
| 96 | int parametercount = 0;
|
---|
| 97 | while (expression_list->GetNodeType() != NODE_EMPTY) {
|
---|
| 98 | ++parametercount;
|
---|
| 99 | if (parametercount > symbol->GetParameterCount()) {
|
---|
| 100 | break;
|
---|
| 101 | }
|
---|
| 102 |
|
---|
| 103 | /* Check parameter and add coercion if necessary */
|
---|
| 104 | ReturnType wanted = symbol->GetParameter(parametercount-1)->GetReturnType();
|
---|
| 105 | Node *coerced_node = coerce(wanted, expression_list->GetLeftChild());
|
---|
| 106 | expression_list->SetLeftChild(coerced_node);
|
---|
| 107 |
|
---|
| 108 | /* Next parameter */
|
---|
| 109 | expression_list = expression_list->GetRightChild();
|
---|
| 110 | assert(expression_list->GetNodeType() == NODE_EXPRLIST ||
|
---|
| 111 | expression_list->GetNodeType() == NODE_EMPTY);
|
---|
| 112 | }
|
---|
| 113 | if (parametercount != symbol->GetParameterCount()) {
|
---|
| 114 | messages.ParamCountError(lineno, parametercount, symbol);
|
---|
| 115 | }
|
---|
| 116 | }
|
---|