Mercurial > hg > graal-compiler
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 } |