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