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 | }
|
---|