comparison graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java @ 13821:b16ec83edc73

Documentation and more refactoring of Simple Language
author Christian Wimmer <christian.wimmer@oracle.com>
date Wed, 29 Jan 2014 20:45:43 -0800
parents 739194d1e813
children 64c77f0577bb
comparison
equal deleted inserted replaced
13820:20e7727588e8 13821:b16ec83edc73
1 /* 1 /*
2 * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. 2 * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 * 4 *
5 * This code is free software; you can redistribute it and/or modify it 5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as 6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
25 import java.math.*; 25 import java.math.*;
26 import java.util.*; 26 import java.util.*;
27 27
28 import com.oracle.truffle.api.*; 28 import com.oracle.truffle.api.*;
29 import com.oracle.truffle.api.frame.*; 29 import com.oracle.truffle.api.frame.*;
30 import com.oracle.truffle.api.impl.*;
30 import com.oracle.truffle.api.nodes.*; 31 import com.oracle.truffle.api.nodes.*;
31 import com.oracle.truffle.sl.nodes.*; 32 import com.oracle.truffle.sl.nodes.*;
32 import com.oracle.truffle.sl.nodes.call.*; 33 import com.oracle.truffle.sl.nodes.call.*;
33 import com.oracle.truffle.sl.nodes.controlflow.*; 34 import com.oracle.truffle.sl.nodes.controlflow.*;
34 import com.oracle.truffle.sl.nodes.expression.*; 35 import com.oracle.truffle.sl.nodes.expression.*;
51 } 52 }
52 53
53 /* State while parsing a source unit. */ 54 /* State while parsing a source unit. */
54 private final SLContext context; 55 private final SLContext context;
55 private final Source source; 56 private final Source source;
56 private final Parser parser;
57 57
58 /* State while parsing a function. */ 58 /* State while parsing a function. */
59 private String functionName; 59 private String functionName;
60 private int parameterCount;
60 private FrameDescriptor frameDescriptor; 61 private FrameDescriptor frameDescriptor;
61 private List<SLStatementNode> methodNodes; 62 private List<SLStatementNode> methodNodes;
62 63
63 /* State while parsing a block. */ 64 /* State while parsing a block. */
64 private LexicalScope lexicalScope; 65 private LexicalScope lexicalScope;
65 66
66 public SLNodeFactory(SLContext context, Source source, Parser parser) { 67 public SLNodeFactory(SLContext context, Source source) {
67 this.context = context; 68 this.context = context;
68 this.source = source; 69 this.source = source;
69 this.parser = parser; 70 }
70 } 71
71 72 public void startFunction(Token nameToken) {
72 public void startFunction(String name, List<String> parameters) {
73 assert functionName == null; 73 assert functionName == null;
74 assert parameterCount == 0;
74 assert frameDescriptor == null; 75 assert frameDescriptor == null;
75 assert lexicalScope == null; 76 assert lexicalScope == null;
76 77
77 functionName = name; 78 functionName = nameToken.val;
78 frameDescriptor = new FrameDescriptor(); 79 frameDescriptor = new FrameDescriptor();
80 methodNodes = new ArrayList<>();
79 startBlock(); 81 startBlock();
80 82 }
83
84 public void addFormalParameter(Token nameToken) {
81 /* 85 /*
82 * Method parameters are assigned to local variables at the beginning of the method. This 86 * Method parameters are assigned to local variables at the beginning of the method. This
83 * ensures that accesses to parameters are specialized the same way as local variables are 87 * ensures that accesses to parameters are specialized the same way as local variables are
84 * specialized. 88 * specialized.
85 */ 89 */
86 methodNodes = new ArrayList<>(parameters.size()); 90 SLReadArgumentNode readArg = assignSource(nameToken, new SLReadArgumentNode(parameterCount));
87 for (int i = 0; i < parameters.size(); i++) { 91 methodNodes.add(createAssignment(nameToken, readArg));
88 methodNodes.add(createAssignment(parameters.get(i), new SLReadArgumentNode(i))); 92 parameterCount++;
89 } 93 }
90 } 94
91 95 public void finishFunction(SLStatementNode bodyNode) {
92 public void finishFunction(SLStatementNode body) { 96 methodNodes.add(bodyNode);
93 methodNodes.add(body);
94 SLStatementNode methodBlock = finishBlock(methodNodes); 97 SLStatementNode methodBlock = finishBlock(methodNodes);
95 assert lexicalScope == null : "Wrong scoping of blocks in parser"; 98 assert lexicalScope == null : "Wrong scoping of blocks in parser";
96 99
97 context.getFunctionRegistry().register(functionName, SLRootNode.createFunction(functionName, frameDescriptor, methodBlock)); 100 SLFunctionBodyNode functionBodyNode = new SLFunctionBodyNode(methodBlock);
101 SLRootNode rootNode = new SLRootNode(frameDescriptor, functionBodyNode, functionName);
102
103 context.getFunctionRegistry().register(functionName, rootNode);
98 104
99 functionName = null; 105 functionName = null;
106 parameterCount = 0;
100 frameDescriptor = null; 107 frameDescriptor = null;
101 lexicalScope = null; 108 lexicalScope = null;
102 } 109 }
103 110
104 public void startBlock() { 111 public void startBlock() {
105 lexicalScope = new LexicalScope(lexicalScope); 112 lexicalScope = new LexicalScope(lexicalScope);
106 } 113 }
107 114
108 public SLStatementNode finishBlock(List<SLStatementNode> statements) { 115 public SLStatementNode finishBlock(List<SLStatementNode> bodyNodes) {
109 lexicalScope = lexicalScope.outer; 116 lexicalScope = lexicalScope.outer;
110 117
111 List<SLStatementNode> flattened = new ArrayList<>(statements.size()); 118 List<SLStatementNode> flattenedNodes = new ArrayList<>(bodyNodes.size());
112 flattenBlocks(statements, flattened); 119 flattenBlocks(bodyNodes, flattenedNodes);
113 if (flattened.size() == 1) { 120 if (flattenedNodes.size() == 1) {
114 return flattened.get(0); 121 /* A block containing one other node is unnecessary, we can just that other node. */
122 return flattenedNodes.get(0);
115 } else { 123 } else {
116 return assignSource(new SLBlockNode(flattened.toArray(new SLStatementNode[flattened.size()]))); 124 return new SLBlockNode(flattenedNodes.toArray(new SLStatementNode[flattenedNodes.size()]));
117 } 125 }
118 } 126 }
119 127
120 private void flattenBlocks(Iterable<? extends Node> statements, List<SLStatementNode> flattened) { 128 private void flattenBlocks(Iterable<? extends Node> bodyNodes, List<SLStatementNode> flattenedNodes) {
121 for (Node statement : statements) { 129 for (Node n : bodyNodes) {
122 if (statement instanceof SLBlockNode) { 130 if (n instanceof SLBlockNode) {
123 flattenBlocks(statement.getChildren(), flattened); 131 flattenBlocks(n.getChildren(), flattenedNodes);
124 } else { 132 } else {
125 flattened.add((SLStatementNode) statement); 133 flattenedNodes.add((SLStatementNode) n);
126 } 134 }
127 } 135 }
128 } 136 }
129 137
130 private <T extends Node> T assignSource(T node) { 138 public SLStatementNode createBreak(Token t) {
131 assert functionName != null; 139 return assignSource(t, new SLBreakNode());
132 node.assignSourceSection(ParserUtils.createSourceSection(source, functionName, parser)); 140 }
133 return node; 141
134 } 142 public SLStatementNode createContinue(Token t) {
135 143 return assignSource(t, new SLContinueNode());
136 public SLExpressionNode createAssignment(String name, SLExpressionNode value) { 144 }
137 FrameSlot frameSlot = frameDescriptor.findOrAddFrameSlot(name); 145
138 lexicalScope.locals.put(name, frameSlot); 146 public SLStatementNode createWhile(Token t, SLExpressionNode conditionNode, SLStatementNode bodyNode) {
139 return assignSource(WriteLocalNodeFactory.create(frameSlot, value)); 147 return assignSource(t, new SLWhileNode(conditionNode, bodyNode));
140 } 148 }
141 149
142 public SLExpressionNode createRead(String name) { 150 public SLStatementNode createIf(Token t, SLExpressionNode conditionNode, SLStatementNode thenPartNode, SLStatementNode elsePartNode) {
143 FrameSlot frameSlot = lexicalScope.locals.get(name); 151 return assignSource(t, new SLIfNode(conditionNode, thenPartNode, elsePartNode));
152 }
153
154 public SLStatementNode createReturn(Token t, SLExpressionNode valueNode) {
155 return assignSource(t, new SLReturnNode(valueNode));
156 }
157
158 public SLExpressionNode createBinary(Token opToken, SLExpressionNode leftNode, SLExpressionNode rightNode) {
159 switch (opToken.val) {
160 case "+":
161 return assignSource(opToken, SLAddNodeFactory.create(leftNode, rightNode));
162 case "*":
163 return assignSource(opToken, SLMulNodeFactory.create(leftNode, rightNode));
164 case "/":
165 return assignSource(opToken, SLDivNodeFactory.create(leftNode, rightNode));
166 case "-":
167 return assignSource(opToken, SLSubNodeFactory.create(leftNode, rightNode));
168 case "<":
169 return assignSource(opToken, SLLessThanNodeFactory.create(leftNode, rightNode));
170 case "<=":
171 return assignSource(opToken, SLLessOrEqualNodeFactory.create(leftNode, rightNode));
172 case ">":
173 return assignSource(opToken, SLLogicalNotNodeFactory.create(assignSource(opToken, SLLessOrEqualNodeFactory.create(leftNode, rightNode))));
174 case ">=":
175 return assignSource(opToken, SLLogicalNotNodeFactory.create(assignSource(opToken, SLLessThanNodeFactory.create(leftNode, rightNode))));
176 case "==":
177 return assignSource(opToken, SLEqualNodeFactory.create(leftNode, rightNode));
178 case "!=":
179 return assignSource(opToken, SLLogicalNotNodeFactory.create(assignSource(opToken, SLEqualNodeFactory.create(leftNode, rightNode))));
180 case "&&":
181 return assignSource(opToken, SLLogicalAndNodeFactory.create(leftNode, rightNode));
182 case "||":
183 return assignSource(opToken, SLLogicalOrNodeFactory.create(leftNode, rightNode));
184 default:
185 throw new RuntimeException("unexpected operation: " + opToken.val);
186 }
187 }
188
189 public SLExpressionNode createCall(Token nameToken, List<SLExpressionNode> parameterNodes) {
190 SLExpressionNode functionNode = createRead(nameToken);
191 return assignSource(nameToken, SLCallNode.create(functionNode, parameterNodes.toArray(new SLExpressionNode[parameterNodes.size()])));
192 }
193
194 public SLExpressionNode createAssignment(Token nameToken, SLExpressionNode valueNode) {
195 FrameSlot frameSlot = frameDescriptor.findOrAddFrameSlot(nameToken.val);
196 lexicalScope.locals.put(nameToken.val, frameSlot);
197 return assignSource(nameToken, SLWriteLocalVariableNodeFactory.create(valueNode, frameSlot));
198 }
199
200 public SLExpressionNode createRead(Token nameToken) {
201 FrameSlot frameSlot = lexicalScope.locals.get(nameToken.val);
144 if (frameSlot != null) { 202 if (frameSlot != null) {
145 /* Read of a local variable. */ 203 /* Read of a local variable. */
146 return assignSource(ReadLocalNodeFactory.create(frameSlot)); 204 return assignSource(nameToken, SLReadLocalVariableNodeFactory.create(frameSlot));
147 } else { 205 } else {
148 /* Read of a global name. In our language, the only global names are functions. */ 206 /* Read of a global name. In our language, the only global names are functions. */
149 return new SLFunctionLiteralNode(context.getFunctionRegistry().lookup(name)); 207 return assignSource(nameToken, new SLFunctionLiteralNode(context.getFunctionRegistry().lookup(nameToken.val)));
150 } 208 }
151 } 209 }
152 210
153 public SLExpressionNode createNumericLiteral(String value) { 211 public SLExpressionNode createStringLiteral(Token literalToken) {
212 /* Remove the trailing and ending " */
213 String literal = literalToken.val;
214 assert literal.length() >= 2 && literal.startsWith("\"") && literal.endsWith("\"");
215 literal = literal.substring(1, literal.length() - 1);
216
217 return assignSource(literalToken, new SLStringLiteralNode(literal));
218 }
219
220 public SLExpressionNode createNumericLiteral(Token literalToken) {
154 try { 221 try {
155 return assignSource(new SLLongLiteralNode(Long.parseLong(value))); 222 /* Try if the literal is small enough to fit into a long value. */
223 return assignSource(literalToken, new SLLongLiteralNode(Long.parseLong(literalToken.val)));
156 } catch (NumberFormatException ex) { 224 } catch (NumberFormatException ex) {
157 return assignSource(new SLBigIntegerLiteralNode(new BigInteger(value))); 225 /* Overflow of long value, so fall back to BigInteger. */
158 } 226 return assignSource(literalToken, new SLBigIntegerLiteralNode(new BigInteger(literalToken.val)));
159 } 227 }
160 228 }
161 public SLExpressionNode createStringLiteral(String value) { 229
162 return assignSource(new SLStringLiteralNode(value)); 230 private <T extends Node> T assignSource(Token t, T node) {
163 } 231 assert functionName != null;
164 232 assert t != null;
165 public SLStatementNode createWhile(SLExpressionNode condition, SLStatementNode body) { 233
166 return assignSource(new SLWhileNode(condition, body)); 234 int startLine = t.line;
167 } 235 int startColumn = t.col;
168 236 int charLength = t.val.length();
169 public SLStatementNode createBreak() { 237 SourceSection sourceSection = new DefaultSourceSection(source, functionName, startLine, startColumn, 0, charLength);
170 return assignSource(new SLBreakNode()); 238
171 } 239 node.assignSourceSection(sourceSection);
172 240 return node;
173 public SLStatementNode createContinue() {
174 return assignSource(new SLContinueNode());
175 }
176
177 public SLExpressionNode createCall(SLExpressionNode function, List<SLExpressionNode> parameters) {
178 return assignSource(SLCallNode.create(function, parameters.toArray(new SLExpressionNode[parameters.size()])));
179 }
180
181 public SLExpressionNode createBinary(String operation, SLExpressionNode left, SLExpressionNode right) {
182 SLExpressionNode binary;
183 switch (operation) {
184 case "+":
185 binary = SLAddNodeFactory.create(left, right);
186 break;
187 case "*":
188 binary = SLMulNodeFactory.create(left, right);
189 break;
190 case "/":
191 binary = SLDivNodeFactory.create(left, right);
192 break;
193 case "-":
194 binary = SLSubNodeFactory.create(left, right);
195 break;
196 case "<":
197 binary = SLLessThanNodeFactory.create(left, right);
198 break;
199 case "<=":
200 binary = SLLessOrEqualNodeFactory.create(left, right);
201 break;
202 case "==":
203 binary = SLEqualNodeFactory.create(left, right);
204 break;
205 case "!=":
206 binary = SLNotEqualNodeFactory.create(left, right);
207 break;
208 case "&&":
209 binary = SLLogicalAndNodeFactory.create(left, right);
210 break;
211 case "||":
212 binary = SLLogicalOrNodeFactory.create(left, right);
213 break;
214 default:
215 throw new RuntimeException("unexpected operation: " + operation);
216 }
217 return assignSource(binary);
218 }
219
220 public SLStatementNode createReturn(SLExpressionNode value) {
221 return assignSource(new SLReturnNode(value));
222 }
223
224 public SLStatementNode createIf(SLExpressionNode condition, SLStatementNode then, SLStatementNode elseNode) {
225 return assignSource(new SLIfNode(condition, then, elseNode));
226 } 241 }
227 } 242 }