source: liacs/coco/assignment2/coercion.cc@ 295

Last change on this file since 295 was 2, checked in by Rick van der Zwet, 15 years ago

Initial import of data of old repository ('data') worth keeping (e.g. tracking
means of URL access statistics)

File size: 3.4 KB
Line 
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
9extern int lineno; // declared in comp.l
10extern SyntaxTree *tree; // declared in comp.y
11extern Messages messages; // declared in comp.y
12
13ReturnType 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
22void checkType(ReturnType expected, ReturnType actual) {
23 if (actual != expected) {
24 messages.TypeError(lineno, expected, actual);
25 }
26}
27
28void checkType(ReturnType expected, Node *expression) {
29 checkType(expected, expression->GetReturnType());
30}
31
32Node *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
75void 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}
Note: See TracBrowser for help on using the repository browser.