annotate graal/com.oracle.truffle.ruby.parser/src/com/oracle/truffle/ruby/parser/ModuleTranslator.java @ 13514:0fbee3eb71f0

Ruby: import project.
author Chris Seaton <chris.seaton@oracle.com>
date Mon, 06 Jan 2014 17:12:09 +0000
parents
children 232eb6708943
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
13514
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
1 /*
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
2 * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
3 * code is released under a tri EPL/GPL/LGPL license. You can use it,
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
4 * redistribute it and/or modify it under the terms of the:
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
5 *
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
6 * Eclipse Public License version 1.0
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
7 * GNU General Public License version 2
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
8 * GNU Lesser General Public License version 2.1
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
9 */
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
10 package com.oracle.truffle.ruby.parser;
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
11
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
12 import com.oracle.truffle.api.*;
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
13 import com.oracle.truffle.api.nodes.*;
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
14 import com.oracle.truffle.ruby.nodes.*;
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
15 import com.oracle.truffle.ruby.nodes.constants.*;
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
16 import com.oracle.truffle.ruby.nodes.control.*;
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
17 import com.oracle.truffle.ruby.nodes.literal.*;
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
18 import com.oracle.truffle.ruby.nodes.methods.*;
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
19 import com.oracle.truffle.ruby.nodes.objects.*;
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
20 import com.oracle.truffle.ruby.runtime.*;
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
21 import com.oracle.truffle.ruby.runtime.methods.*;
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
22
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
23 /**
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
24 * Translates module and class nodes.
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
25 * <p>
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
26 * In Ruby, a module or class definition is somewhat like a method. It has a local scope and a value
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
27 * for self, which is the module or class object that is being defined. Therefore for a module or
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
28 * class definition we translate into a special method. We run that method with self set to be the
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
29 * newly allocated module or class. We then have to treat at least method and constant definitions
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
30 * differently.
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
31 */
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
32 class ModuleTranslator extends Translator {
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
33
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
34 public ModuleTranslator(RubyContext context, Translator parent, TranslatorEnvironment environment, Source source) {
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
35 super(context, parent, environment, source);
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
36 }
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
37
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
38 public MethodDefinitionNode compileClassNode(org.jrubyparser.SourcePosition sourcePosition, String name, org.jrubyparser.ast.Node bodyNode) {
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
39 final SourceSection sourceSection = translate(sourcePosition);
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
40
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
41 environment.addMethodDeclarationSlots();
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
42
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
43 final String methodName = "(" + name + "-def" + ")";
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
44 environment.setMethodName(methodName);
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
45
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
46 RubyNode body;
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
47
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
48 if (bodyNode != null) {
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
49 body = (RubyNode) bodyNode.accept(this);
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
50 } else {
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
51 body = new NilNode(context, sourceSection);
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
52 }
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
53
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
54 if (environment.getFlipFlopStates().size() > 0) {
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
55 body = new SequenceNode(context, sourceSection, initFlipFlopStates(sourceSection), body);
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
56 }
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
57
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
58 body = new CatchReturnNode(context, sourceSection, body, environment.getReturnID());
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
59
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
60 final RubyRootNode pristineRootNode = new RubyRootNode(sourceSection, methodName, body);
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
61
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
62 final CallTarget callTarget = Truffle.getRuntime().createCallTarget(NodeUtil.cloneNode(pristineRootNode), environment.getFrameDescriptor());
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
63
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
64 return new MethodDefinitionNode(context, sourceSection, methodName, environment.getUniqueMethodIdentifier(), environment.getFrameDescriptor(), environment.needsDeclarationFrame(),
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
65 pristineRootNode, callTarget);
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
66 }
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
67
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
68 @Override
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
69 public Object visitConstDeclNode(org.jrubyparser.ast.ConstDeclNode node) {
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
70 final SourceSection sourceSection = translate(node.getPosition());
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
71
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
72 final SelfNode selfNode = new SelfNode(context, sourceSection);
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
73
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
74 return new WriteConstantNode(context, sourceSection, node.getName(), selfNode, (RubyNode) node.getValue().accept(this));
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
75 }
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
76
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
77 @Override
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
78 public Object visitConstNode(org.jrubyparser.ast.ConstNode node) {
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
79 final SourceSection sourceSection = translate(node.getPosition());
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
80
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
81 final SelfNode selfNode = new SelfNode(context, sourceSection);
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
82
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
83 return new UninitializedReadConstantNode(context, sourceSection, node.getName(), selfNode);
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
84 }
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
85
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
86 @Override
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
87 public Object visitDefnNode(org.jrubyparser.ast.DefnNode node) {
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
88 /*
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
89 * The top-level translator puts methods into Object. We put ours into the self, which is
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
90 * the class being defined.
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
91 */
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
92
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
93 final TranslatorEnvironment newEnvironment = new TranslatorEnvironment(context, environment, environment.getParser(), environment.getParser().allocateReturnID(), true, true,
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
94 new UniqueMethodIdentifier());
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
95 final MethodTranslator methodCompiler = new MethodTranslator(context, this, newEnvironment, false, source);
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
96 final MethodDefinitionNode functionExprNode = methodCompiler.compileFunctionNode(translate(node.getPosition()), node.getName(), node.getArgs(), node.getBody());
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
97
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
98 final SourceSection sourceSection = translate(node.getPosition());
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
99 return new AddMethodNode(context, sourceSection, new SelfNode(context, sourceSection), functionExprNode);
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
100 }
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
101
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
102 @Override
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
103 public Object visitClassVarAsgnNode(org.jrubyparser.ast.ClassVarAsgnNode node) {
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
104 final SourceSection sourceSection = translate(node.getPosition());
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
105
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
106 final RubyNode receiver = new SelfNode(context, sourceSection);
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
107
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
108 final RubyNode rhs = (RubyNode) node.getValue().accept(this);
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
109
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
110 return new WriteClassVariableNode(context, sourceSection, node.getName(), receiver, rhs);
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
111 }
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
112
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
113 @Override
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
114 public Object visitClassVarNode(org.jrubyparser.ast.ClassVarNode node) {
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
115 final SourceSection sourceSection = translate(node.getPosition());
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
116 return new ReadClassVariableNode(context, sourceSection, node.getName(), new SelfNode(context, sourceSection));
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
117 }
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
118
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
119 @Override
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
120 public Object visitAliasNode(org.jrubyparser.ast.AliasNode node) {
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
121 final SourceSection sourceSection = translate(node.getPosition());
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
122
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
123 final org.jrubyparser.ast.LiteralNode oldName = (org.jrubyparser.ast.LiteralNode) node.getOldName();
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
124 final org.jrubyparser.ast.LiteralNode newName = (org.jrubyparser.ast.LiteralNode) node.getNewName();
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
125
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
126 return new AliasNode(context, sourceSection, new SelfNode(context, sourceSection), newName.getName(), oldName.getName());
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
127 }
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
128
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
129 @Override
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
130 protected RubyNode getModuleToDefineModulesIn(SourceSection sourceSection) {
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
131 return new SelfNode(context, sourceSection);
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
132 }
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
133
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
134 }