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.nodes.debug;
|
|
11
|
|
12 import com.oracle.truffle.api.*;
|
|
13 import com.oracle.truffle.api.dsl.*;
|
|
14 import com.oracle.truffle.api.frame.*;
|
|
15 import com.oracle.truffle.api.nodes.*;
|
|
16 import com.oracle.truffle.api.source.*;
|
|
17 import com.oracle.truffle.ruby.nodes.call.*;
|
|
18 import com.oracle.truffle.ruby.nodes.core.*;
|
|
19 import com.oracle.truffle.ruby.runtime.*;
|
|
20 import com.oracle.truffle.ruby.runtime.control.*;
|
|
21 import com.oracle.truffle.ruby.runtime.core.*;
|
|
22 import com.oracle.truffle.ruby.runtime.methods.*;
|
|
23
|
|
24 @CoreClass(name = "Debug")
|
|
25 public abstract class DebugNodes {
|
|
26
|
|
27 @CoreMethod(names = "break", isModuleMethod = true, needsSelf = false, needsBlock = true, appendCallNode = true, minArgs = 0, maxArgs = 3)
|
|
28 public abstract static class BreakNode extends CoreMethodNode {
|
|
29
|
|
30 public BreakNode(RubyContext context, SourceSection sourceSection) {
|
|
31 super(context, sourceSection);
|
|
32 }
|
|
33
|
|
34 public BreakNode(BreakNode prev) {
|
|
35 super(prev);
|
|
36 }
|
|
37
|
|
38 @Specialization(order = 1)
|
|
39 public NilPlaceholder debugBreak(VirtualFrame frame, Node callNode, @SuppressWarnings("unused") UndefinedPlaceholder undefined0, @SuppressWarnings("unused") UndefinedPlaceholder undefined1,
|
|
40 @SuppressWarnings("unused") UndefinedPlaceholder block) {
|
|
41 final RubyContext context = getContext();
|
|
42 if (context.getConfiguration().getDebug()) {
|
|
43 Node realCallNode = callNode;
|
|
44 while (realCallNode != null && !(realCallNode instanceof CallNode)) {
|
|
45 realCallNode = realCallNode.getParent();
|
|
46 }
|
|
47 context.getDebugManager().haltedAt(realCallNode, frame.materialize());
|
|
48 }
|
|
49 return NilPlaceholder.INSTANCE;
|
|
50 }
|
|
51
|
|
52 @Specialization(order = 2)
|
|
53 public NilPlaceholder debugBreak(RubyString fileName, int line, @SuppressWarnings("unused") Node callNode, @SuppressWarnings("unused") UndefinedPlaceholder block) {
|
|
54 final RubyContext context = getContext();
|
|
55 if (context.getConfiguration().getDebug()) {
|
|
56 final Source source = context.getSourceManager().get(fileName.toString());
|
|
57 final SourceLineLocation lineLocation = new SourceLineLocation(source, line);
|
|
58 context.getDebugManager().setBreakpoint(lineLocation);
|
|
59 }
|
|
60 return NilPlaceholder.INSTANCE;
|
|
61 }
|
|
62
|
|
63 @Specialization(order = 3)
|
|
64 public NilPlaceholder debugBreak(RubyString fileName, int line, @SuppressWarnings("unused") Node callNode, RubyProc block) {
|
|
65 final RubyContext context = getContext();
|
|
66 if (context.getConfiguration().getDebug()) {
|
|
67 final Source source = context.getSourceManager().get(fileName.toString());
|
|
68 final SourceLineLocation lineLocation = new SourceLineLocation(source, line);
|
|
69 context.getDebugManager().setLineProc(lineLocation, block);
|
|
70 }
|
|
71 return NilPlaceholder.INSTANCE;
|
|
72 }
|
|
73
|
|
74 @Specialization(order = 4)
|
|
75 public NilPlaceholder debugBreak(RubySymbol methodName, RubySymbol localName, @SuppressWarnings("unused") Node callNode, @SuppressWarnings("unused") UndefinedPlaceholder block) {
|
|
76 final RubyContext context = getContext();
|
|
77 if (context.getConfiguration().getDebug()) {
|
|
78 final RubyMethod method = context.getCoreLibrary().getMainObject().getLookupNode().lookupMethod(methodName.toString());
|
|
79 context.getDebugManager().setLocalBreak(method.getUniqueIdentifier(), localName.toString());
|
|
80 }
|
|
81 return NilPlaceholder.INSTANCE;
|
|
82 }
|
|
83
|
|
84 @Specialization(order = 5)
|
|
85 public NilPlaceholder debugBreak(RubySymbol methodName, RubySymbol localName, @SuppressWarnings("unused") Node callNode, RubyProc block) {
|
|
86 final RubyContext context = getContext();
|
|
87 if (context.getConfiguration().getDebug()) {
|
|
88 final RubyMethod method = context.getCoreLibrary().getMainObject().getLookupNode().lookupMethod(methodName.toString());
|
|
89 context.getDebugManager().setLocalProc(method.getUniqueIdentifier(), localName.toString(), block);
|
|
90 }
|
|
91 return NilPlaceholder.INSTANCE;
|
|
92 }
|
|
93
|
|
94 }
|
|
95
|
|
96 @CoreMethod(names = "continue", isModuleMethod = true, needsSelf = false, maxArgs = 0)
|
|
97 public abstract static class ContinueNode extends CoreMethodNode {
|
|
98
|
|
99 public ContinueNode(RubyContext context, SourceSection sourceSection) {
|
|
100 super(context, sourceSection);
|
|
101 }
|
|
102
|
|
103 public ContinueNode(ContinueNode prev) {
|
|
104 super(prev);
|
|
105 }
|
|
106
|
|
107 @Specialization
|
|
108 public Object debugContinue() {
|
|
109 if (getContext().getConfiguration().getDebug()) {
|
|
110 throw new BreakShellException();
|
|
111 }
|
|
112 return NilPlaceholder.INSTANCE;
|
|
113 }
|
|
114
|
|
115 }
|
|
116
|
|
117 @CoreMethod(names = "enabled?", isModuleMethod = true, needsSelf = false, maxArgs = 0)
|
|
118 public abstract static class EnabledNode extends CoreMethodNode {
|
|
119
|
|
120 public EnabledNode(RubyContext context, SourceSection sourceSection) {
|
|
121 super(context, sourceSection);
|
|
122 }
|
|
123
|
|
124 public EnabledNode(ContinueNode prev) {
|
|
125 super(prev);
|
|
126 }
|
|
127
|
|
128 @Specialization
|
|
129 public boolean enabled() {
|
|
130 return getContext().getConfiguration().getDebug();
|
|
131 }
|
|
132
|
|
133 }
|
|
134
|
|
135 @CoreMethod(names = "where", isModuleMethod = true, needsSelf = false, appendCallNode = true, minArgs = 1, maxArgs = 1)
|
|
136 public abstract static class WhereNode extends CoreMethodNode {
|
|
137
|
|
138 public WhereNode(RubyContext context, SourceSection sourceSection) {
|
|
139 super(context, sourceSection);
|
|
140 }
|
|
141
|
|
142 public WhereNode(WhereNode prev) {
|
|
143 super(prev);
|
|
144 }
|
|
145
|
|
146 @Specialization
|
|
147 public NilPlaceholder where(Node callNode) {
|
|
148 final RubyContext context = getContext();
|
|
149 if (context.getConfiguration().getDebug()) {
|
|
150 context.getConfiguration().getStandardOut().println(callNode.getSourceSection());
|
|
151 }
|
|
152 return NilPlaceholder.INSTANCE;
|
|
153 }
|
|
154
|
|
155 }
|
|
156
|
|
157 @CoreMethod(names = "remove", isModuleMethod = true, needsSelf = false, needsBlock = true, minArgs = 2, maxArgs = 2)
|
|
158 public abstract static class RemoveNode extends CoreMethodNode {
|
|
159
|
|
160 public RemoveNode(RubyContext context, SourceSection sourceSection) {
|
|
161 super(context, sourceSection);
|
|
162 }
|
|
163
|
|
164 public RemoveNode(RemoveNode prev) {
|
|
165 super(prev);
|
|
166 }
|
|
167
|
|
168 @Specialization
|
|
169 public NilPlaceholder debugRemove(RubyString fileName, int line) {
|
|
170 final RubyContext context = getContext();
|
|
171 if (context.getConfiguration().getDebug()) {
|
|
172 final Source source = context.getSourceManager().get(fileName.toString());
|
|
173 final SourceLineLocation lineLocation = new SourceLineLocation(source, line);
|
|
174 context.getDebugManager().removeBreakpoint(lineLocation);
|
|
175 }
|
|
176 return NilPlaceholder.INSTANCE;
|
|
177 }
|
|
178
|
|
179 @Specialization
|
|
180 public NilPlaceholder debugRemove(RubySymbol methodName, RubySymbol localName) {
|
|
181 final RubyContext context = getContext();
|
|
182 if (context.getConfiguration().getDebug()) {
|
|
183 final RubyMethod method = context.getCoreLibrary().getMainObject().getLookupNode().lookupMethod(methodName.toString());
|
|
184 context.getDebugManager().removeLocalProbe(method.getUniqueIdentifier(), localName.toString());
|
|
185 }
|
|
186 return NilPlaceholder.INSTANCE;
|
|
187 }
|
|
188
|
|
189 }
|
|
190
|
|
191 }
|