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 }