Mercurial > hg > graal-compiler
comparison graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java @ 13805:739194d1e813
Merge.
author | Christian Humer <christian.humer@gmail.com> |
---|---|
date | Tue, 28 Jan 2014 12:55:06 +0100 |
parents | graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLNodeFactory.java@e076c87ab175 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLNodeFactory.java@cad8bed1a1ac |
children | b16ec83edc73 |
comparison
equal
deleted
inserted
replaced
13804:3840d61e0e68 | 13805:739194d1e813 |
---|---|
1 /* | |
2 * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. | |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
4 * | |
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 | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
20 * or visit www.oracle.com if you need additional information or have any | |
21 * questions. | |
22 */ | |
23 package com.oracle.truffle.sl.parser; | |
24 | |
25 import java.math.*; | |
26 import java.util.*; | |
27 | |
28 import com.oracle.truffle.api.*; | |
29 import com.oracle.truffle.api.frame.*; | |
30 import com.oracle.truffle.api.nodes.*; | |
31 import com.oracle.truffle.sl.nodes.*; | |
32 import com.oracle.truffle.sl.nodes.call.*; | |
33 import com.oracle.truffle.sl.nodes.controlflow.*; | |
34 import com.oracle.truffle.sl.nodes.expression.*; | |
35 import com.oracle.truffle.sl.nodes.local.*; | |
36 import com.oracle.truffle.sl.runtime.*; | |
37 | |
38 public class SLNodeFactory { | |
39 | |
40 static class LexicalScope { | |
41 protected final LexicalScope outer; | |
42 protected final Map<String, FrameSlot> locals; | |
43 | |
44 public LexicalScope(LexicalScope outer) { | |
45 this.outer = outer; | |
46 this.locals = new HashMap<>(); | |
47 if (outer != null) { | |
48 locals.putAll(outer.locals); | |
49 } | |
50 } | |
51 } | |
52 | |
53 /* State while parsing a source unit. */ | |
54 private final SLContext context; | |
55 private final Source source; | |
56 private final Parser parser; | |
57 | |
58 /* State while parsing a function. */ | |
59 private String functionName; | |
60 private FrameDescriptor frameDescriptor; | |
61 private List<SLStatementNode> methodNodes; | |
62 | |
63 /* State while parsing a block. */ | |
64 private LexicalScope lexicalScope; | |
65 | |
66 public SLNodeFactory(SLContext context, Source source, Parser parser) { | |
67 this.context = context; | |
68 this.source = source; | |
69 this.parser = parser; | |
70 } | |
71 | |
72 public void startFunction(String name, List<String> parameters) { | |
73 assert functionName == null; | |
74 assert frameDescriptor == null; | |
75 assert lexicalScope == null; | |
76 | |
77 functionName = name; | |
78 frameDescriptor = new FrameDescriptor(); | |
79 startBlock(); | |
80 | |
81 /* | |
82 * 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 | |
84 * specialized. | |
85 */ | |
86 methodNodes = new ArrayList<>(parameters.size()); | |
87 for (int i = 0; i < parameters.size(); i++) { | |
88 methodNodes.add(createAssignment(parameters.get(i), new SLReadArgumentNode(i))); | |
89 } | |
90 } | |
91 | |
92 public void finishFunction(SLStatementNode body) { | |
93 methodNodes.add(body); | |
94 SLStatementNode methodBlock = finishBlock(methodNodes); | |
95 assert lexicalScope == null : "Wrong scoping of blocks in parser"; | |
96 | |
97 context.getFunctionRegistry().register(functionName, SLRootNode.createFunction(functionName, frameDescriptor, methodBlock)); | |
98 | |
99 functionName = null; | |
100 frameDescriptor = null; | |
101 lexicalScope = null; | |
102 } | |
103 | |
104 public void startBlock() { | |
105 lexicalScope = new LexicalScope(lexicalScope); | |
106 } | |
107 | |
108 public SLStatementNode finishBlock(List<SLStatementNode> statements) { | |
109 lexicalScope = lexicalScope.outer; | |
110 | |
111 List<SLStatementNode> flattened = new ArrayList<>(statements.size()); | |
112 flattenBlocks(statements, flattened); | |
113 if (flattened.size() == 1) { | |
114 return flattened.get(0); | |
115 } else { | |
116 return assignSource(new SLBlockNode(flattened.toArray(new SLStatementNode[flattened.size()]))); | |
117 } | |
118 } | |
119 | |
120 private void flattenBlocks(Iterable<? extends Node> statements, List<SLStatementNode> flattened) { | |
121 for (Node statement : statements) { | |
122 if (statement instanceof SLBlockNode) { | |
123 flattenBlocks(statement.getChildren(), flattened); | |
124 } else { | |
125 flattened.add((SLStatementNode) statement); | |
126 } | |
127 } | |
128 } | |
129 | |
130 private <T extends Node> T assignSource(T node) { | |
131 assert functionName != null; | |
132 node.assignSourceSection(ParserUtils.createSourceSection(source, functionName, parser)); | |
133 return node; | |
134 } | |
135 | |
136 public SLExpressionNode createAssignment(String name, SLExpressionNode value) { | |
137 FrameSlot frameSlot = frameDescriptor.findOrAddFrameSlot(name); | |
138 lexicalScope.locals.put(name, frameSlot); | |
139 return assignSource(WriteLocalNodeFactory.create(frameSlot, value)); | |
140 } | |
141 | |
142 public SLExpressionNode createRead(String name) { | |
143 FrameSlot frameSlot = lexicalScope.locals.get(name); | |
144 if (frameSlot != null) { | |
145 /* Read of a local variable. */ | |
146 return assignSource(ReadLocalNodeFactory.create(frameSlot)); | |
147 } else { | |
148 /* Read of a global name. In our language, the only global names are functions. */ | |
149 return new SLFunctionLiteralNode(context.getFunctionRegistry().lookup(name)); | |
150 } | |
151 } | |
152 | |
153 public SLExpressionNode createNumericLiteral(String value) { | |
154 try { | |
155 return assignSource(new SLLongLiteralNode(Long.parseLong(value))); | |
156 } catch (NumberFormatException ex) { | |
157 return assignSource(new SLBigIntegerLiteralNode(new BigInteger(value))); | |
158 } | |
159 } | |
160 | |
161 public SLExpressionNode createStringLiteral(String value) { | |
162 return assignSource(new SLStringLiteralNode(value)); | |
163 } | |
164 | |
165 public SLStatementNode createWhile(SLExpressionNode condition, SLStatementNode body) { | |
166 return assignSource(new SLWhileNode(condition, body)); | |
167 } | |
168 | |
169 public SLStatementNode createBreak() { | |
170 return assignSource(new SLBreakNode()); | |
171 } | |
172 | |
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 } | |
227 } |