blob: 5f5489b6a780e309f5d351044de441c0f6d28df1 [file] [log] [blame]
Jan Lahodaa21102b2015-10-19 19:15:16 +02001/*
2 * Copyright (c) 2015, 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. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package jdk.jshell;
27
28import java.util.Collection;
29import java.util.Collections;
30import java.util.List;
31import static jdk.jshell.Util.REPL_CLASS_PREFIX;
32import static jdk.jshell.Util.asLetters;
33
34/**
35 * A Snippet represents a snippet of Java source code as passed to
36 * {@link jdk.jshell.JShell#eval}. It is associated only with the
37 * {@link jdk.jshell.JShell JShell} instance that created it.
38 * An instance of Snippet (including its subclasses) is immutable: an access to
39 * any of its methods will always return the same result.
40 * For information about the current state of the snippet within the JShell
41 * state engine, query <code>JShell</code> passing the Snippet.
42 * <p>
43 * Because it is immutable, <code>Snippet</code> (and subclasses) is thread-safe.
44 * @author Robert Field
45 * @see jdk.jshell.JShell#status
46 */
47public abstract class Snippet {
48
49 /**
50 * Describes the general kind of snippet.
51 * The <code>Kind</code> is an immutable property of a Snippet.
52 * It is accessed with {@link jdk.jshell.Snippet#kind()}.
53 * The <code>Kind</code> can be used to determine which
54 * subclass of Snippet it is. For example,
55 * {@link jdk.jshell.JShell#eval eval("int three() { return 3; }")} will
56 * return a snippet creation event. The <code>Kind</code> of that Snippet
57 * will be <code>METHOD</code>, from which you know that the subclass
58 * of <code>Snippet</code> is <code>MethodSnippet</code> and it can be
59 * cast as such.
60 */
61 public enum Kind {
62 /**
63 * An import declaration: <code>import</code> ...
64 * The snippet is an instance of {@link jdk.jshell.ImportSnippet}.
65 * An import can be a single type import
66 * ({@link jdk.jshell.Snippet.SubKind#SINGLE_TYPE_IMPORT_SUBKIND}),
67 * a static single import
68 * ({@link jdk.jshell.Snippet.SubKind#SINGLE_STATIC_IMPORT_SUBKIND}),
69 * an on-demand type import
70 * ({@link jdk.jshell.Snippet.SubKind#TYPE_IMPORT_ON_DEMAND_SUBKIND}),
71 * or a static on-demand type import
72 * ({@link jdk.jshell.Snippet.SubKind#SINGLE_STATIC_IMPORT_SUBKIND}) --
73 * use {@link jdk.jshell.Snippet#subKind()} to distinguish.
74 * @jls 8.3: importDeclaration.
75 */
76 IMPORT(true),
77
78 /**
79 * A type declaration.
80 * Which includes: NormalClassDeclaration, EnumDeclaration,
81 * NormalInterfaceDeclaration, and AnnotationTypeDeclaration.
82 * The snippet is an instance of {@link jdk.jshell.TypeDeclSnippet}.
83 * A type declaration may be an interface
84 * {@link jdk.jshell.Snippet.SubKind#INTERFACE_SUBKIND},
85 * classes {@link jdk.jshell.Snippet.SubKind#CLASS_SUBKIND}, enums, and
86 * annotation interfaces -- see {@link jdk.jshell.Snippet.SubKind} to
87 * differentiate.
88 * @jls 7.6: TypeDeclaration.
89 */
90 TYPE_DECL(true),
91
92 /**
93 * A method declaration.
94 * The snippet is an instance of {@link jdk.jshell.MethodSnippet}.
95 * @jls 8.4: MethodDeclaration.
96 */
97 METHOD(true),
98
99 /**
100 * One variable declaration.
101 * Corresponding to one <i>VariableDeclarator</i>.
102 * The snippet is an instance of {@link jdk.jshell.VarSnippet}.
103 * The variable may be with or without initializer, or be a temporary
104 * variable representing an expression -- see
105 * {@link jdk.jshell.Snippet.SubKind}to differentiate.
106 * @jls 8.3: FieldDeclaration.
107 */
108 VAR(true),
109
110 /**
111 * An expression, with or without side-effects.
112 * The snippet is an instance of {@link jdk.jshell.ExpressionSnippet}.
113 * The expression is currently either a simple named reference to a
114 * variable ({@link jdk.jshell.Snippet.SubKind#VAR_VALUE_SUBKIND}) or an
115 * assignment (both of which have natural referencing
116 * names) -- see {@link jdk.jshell.Snippet.SubKind} to differentiate.
117 * @jls 15: Expression.
118 */
119 EXPRESSION(false),
120
121 /**
122 * A statement.
123 * The snippet is an instance of {@link jdk.jshell.StatementSnippet}.
124 * @jls 14.5: Statement.
125 */
126 STATEMENT(false),
127
128 /**
129 * A syntactically incorrect input for which the specific
130 * kind could not be determined.
131 * The snippet is an instance of {@link jdk.jshell.ErroneousSnippet}.
132 */
133 ERRONEOUS(false);
134
135 /**
136 * True if this kind of snippet adds a declaration or declarations
137 * which are visible to subsequent evaluations.
138 */
139 public final boolean isPersistent;
140
141 Kind(boolean isPersistent) {
142 this.isPersistent = isPersistent;
143 }
144 }
145
146 /**
147 * The detailed variety of a snippet. This is a sub-classification of the
148 * Kind. The Kind of a SubKind is accessible with
149 * {@link jdk.jshell.Snippet.SubKind#kind}.
150 */
151 public enum SubKind {
152
153 /**
154 * Single-Type-Import Declaration.
155 * An import declaration of a single type.
156 * @jls 7.5.1 SingleTypeImportDeclaration.
157 */
158 SINGLE_TYPE_IMPORT_SUBKIND(Kind.IMPORT),
159
160 /**
161 * Type-Import-on-Demand Declaration.
162 * A non-static "star" import.
163 * @jls 7.5.2. TypeImportOnDemandDeclaration.
164 */
165 TYPE_IMPORT_ON_DEMAND_SUBKIND(Kind.IMPORT),
166
167 /**
168 * Single-Static-Import Declaration.
169 * An import of a static member.
170 * @jls 7.5.3 Single-Static-Import.
171 */
172 SINGLE_STATIC_IMPORT_SUBKIND(Kind.IMPORT),
173
174 /**
175 * Static-Import-on-Demand Declaration.
176 * A static "star" import of all static members of a named type.
177 * @jls 7.5.4. Static-Import-on-Demand Static "star" import.
178 */
179 STATIC_IMPORT_ON_DEMAND_SUBKIND(Kind.IMPORT),
180
181 /**
182 * A class declaration.
183 * A <code>SubKind</code> of {@link Kind#TYPE_DECL}.
184 * @jls 8.1. NormalClassDeclaration.
185 */
186 CLASS_SUBKIND(Kind.TYPE_DECL),
187
188 /**
189 * An interface declaration.
190 * A <code>SubKind</code> of {@link Kind#TYPE_DECL}.
191 * @jls 9.1. NormalInterfaceDeclaration.
192 */
193 INTERFACE_SUBKIND(Kind.TYPE_DECL),
194
195 /**
196 * An enum declaration.
197 * A <code>SubKind</code> of {@link Kind#TYPE_DECL}.
198 * @jls 8.9. EnumDeclaration.
199 */
200 ENUM_SUBKIND(Kind.TYPE_DECL),
201
202 /**
203 * An annotation interface declaration. A <code>SubKind</code> of
204 * {@link Kind#TYPE_DECL}.
205 * @jls 9.6. AnnotationTypeDeclaration.
206 */
207 ANNOTATION_TYPE_SUBKIND(Kind.TYPE_DECL),
208
209 /**
210 * A method. The only <code>SubKind</code> for {@link Kind#METHOD}.
211 * @jls 8.4. MethodDeclaration.
212 */
213 METHOD_SUBKIND(Kind.METHOD),
214
215 /**
216 * A variable declaration without initializer.
217 * A <code>SubKind</code> of {@link Kind#VAR}.
218 * @jls 8.3. VariableDeclarator without VariableInitializer in
219 * FieldDeclaration.
220 */
221 VAR_DECLARATION_SUBKIND(Kind.VAR),
222
223 /**
224 * A variable declaration with an initializer expression. A
225 * <code>SubKind</code> of {@link Kind#VAR}.
226 * @jls 8.3. VariableDeclarator with VariableInitializer in
227 * FieldDeclaration.
228 */
229 VAR_DECLARATION_WITH_INITIALIZER_SUBKIND(Kind.VAR, true, true),
230
231 /**
232 * An expression whose value has been stored in a temporary variable. A
233 * <code>SubKind</code> of {@link Kind#VAR}.
234 * @jls 15. Primary.
235 */
236 TEMP_VAR_EXPRESSION_SUBKIND(Kind.VAR, true, true),
237
238 /**
239 * A simple variable reference expression. A <code>SubKind</code> of
240 * {@link Kind#EXPRESSION}.
241 * @jls 15.11. Field Access as 3.8. Identifier.
242 */
243 VAR_VALUE_SUBKIND(Kind.EXPRESSION, true, true),
244
245 /**
246 * An assignment expression. A <code>SubKind</code> of
247 * {@link Kind#EXPRESSION}.
248 * @jls 15.26. Assignment.
249 */
250 ASSIGNMENT_SUBKIND(Kind.EXPRESSION, true, true),
251
252 /**
253 * An expression which has not been wrapped in a temporary variable
254 * (reserved). A <code>SubKind</code> of {@link Kind#EXPRESSION}.
255 */
256 OTHER_EXPRESSION_SUBKIND(Kind.EXPRESSION, true, true),
257
258 /**
259 * A statement. The only <code>SubKind</code> for {@link Kind#STATEMENT}.
260 * @jls 14.5. Statement.
261 */
262 STATEMENT_SUBKIND(Kind.STATEMENT, true, false),
263
264 /**
265 * An unknown snippet. The only <code>SubKind</code> for
266 * {@link Kind#ERRONEOUS}.
267 */
268 UNKNOWN_SUBKIND(Kind.ERRONEOUS, false, false);
269
270 private final boolean isExecutable;
271 private final boolean hasValue;
272 private final Kind kind;
273
274 SubKind(Kind kind) {
275 this.kind = kind;
276 this.isExecutable = false;
277 this.hasValue = false;
278 }
279
280 SubKind(Kind kind, boolean isExecutable, boolean hasValue) {
281 this.kind = kind;
282 this.isExecutable = isExecutable;
283 this.hasValue = hasValue;
284 }
285
286 /**
287 * Is this <code>SubKind</code> executable?
288 *
289 * @return true if this <code>SubKind</code> can be executed.
290 */
291 public boolean isExecutable() {
292 return isExecutable;
293 }
294
295 /**
296 * Is this <code>SubKind</code> executable and is non-<code>void</code>.
297 *
298 * @return true if this <code>SubKind</code> has a value.
299 */
300 public boolean hasValue() {
301 return hasValue;
302 }
303
304 /**
305 * The {@link Snippet.Kind} that corresponds to this <code>SubKind</code>.
306 *
307 * @return the fixed <code>Kind</code> for this <code>SubKind</code>
308 */
309 public Kind kind() {
310 return kind;
311 }
312 }
313
314 /**
315 * Describes the current state of a Snippet.
316 * This is a dynamic property of a Snippet within the JShell state --
317 * thus is retrieved with a {@linkplain
318 * jdk.jshell.JShell#status(jdk.jshell.Snippet) query on <code>JShell</code>}.
319 * <p>
320 * The <code>Status</code> changes as the state changes.
321 * For example, creation of another snippet with
322 * {@link jdk.jshell.JShell#eval(java.lang.String) eval}
323 * may resolve dependencies of this Snippet (or invalidate those dependencies), or
324 * {@linkplain jdk.jshell.Snippet.Status#OVERWRITTEN overwrite}
325 * this Snippet changing its
326 * <code>Status</code>.
327 * <p>
328 * Important properties associated with <code>Status</code> are:
329 * {@link jdk.jshell.Snippet.Status#isDefined}, if it is visible to other
330 * existing and new snippets; and
331 * {@link jdk.jshell.Snippet.Status#isActive}, if, as the
332 * JShell state changes, the snippet will update, possibly
333 * changing <code>Status</code>.
334 * An executable Snippet can only be executed if it is in the the
335 * {@link jdk.jshell.Snippet.Status#VALID} <code>Status</code>.
336 * @see JShell#status(jdk.jshell.Snippet)
337 */
338 public enum Status {
339 /**
340 * The snippet is a valid snippet
341 * (in the context of current <code>JShell</code> state).
342 * Only snippets with <code>VALID</code>
343 * <code>Status</code> can be executed (though not all
344 * <code>VALID</code> snippets have executable code).
345 * If the snippet is a declaration or import, it is visible to other
346 * snippets ({@link Status#isDefined isDefined} <code> == true</code>).
347 * <p>
348 * The snippet will update as dependents change
349 * ({@link Status#isActive isActive} <code> == true</code>), its
350 * status could become <code>RECOVERABLE_DEFINED</code>, <code>RECOVERABLE_NOT_DEFINED</code>,
351 * <code>DROPPED</code>, or <code>OVERWRITTEN</code>.
352 */
353 VALID(true, true),
354
355 /**
356 * The snippet is a declaration snippet with potentially recoverable
357 * unresolved references or other issues in its body
358 * (in the context of current <code>JShell</code> state).
359 * Only a {@link jdk.jshell.DeclarationSnippet} can have this
360 * <code>Status</code>.
361 * The snippet has a valid signature and it is visible to other
362 * snippets ({@link Status#isDefined isDefined} <code> == true</code>)
363 * and thus can be referenced in existing or new snippets
364 * but the snippet cannot be executed.
365 * An {@link UnresolvedReferenceException} will be thrown on an attempt
366 * to execute it.
367 * <p>
368 * The snippet will update as dependents change
369 * ({@link Status#isActive isActive} <code> == true</code>), its
370 * status could become <code>VALID</code>, <code>RECOVERABLE_NOT_DEFINED</code>,
371 * <code>DROPPED</code>, or <code>OVERWRITTEN</code>.
372 * <p>
373 * Note: both <code>RECOVERABLE_DEFINED</code> and <code>RECOVERABLE_NOT_DEFINED</code>
374 * indicate potentially recoverable errors, they differ in that, for
375 * <code>RECOVERABLE_DEFINED</code>, the snippet is
376 * {@linkplain Status#isDefined defined}.
377 */
378 RECOVERABLE_DEFINED(true, true),
379
380 /**
381 * The snippet is a declaration snippet with potentially recoverable
382 * unresolved references or other issues
383 * (in the context of current <code>JShell</code> state).
384 * Only a {@link jdk.jshell.DeclarationSnippet} can have this
385 * <code>Status</code>.
386 * The snippet has an invalid signature or the implementation is
387 * otherwise unable to define it.
388 * The snippet it is not visible to other snippets
389 * ({@link Status#isDefined isDefined} <code> == false</code>)
390 * and thus cannot be referenced or executed.
391 * <p>
392 * The snippet will update as dependents change
393 * ({@link Status#isActive isActive} <code> == true</code>), its
394 * status could become <code>VALID</code>, <code>RECOVERABLE_DEFINED</code>,
395 * <code>DROPPED</code>, or <code>OVERWRITTEN</code>.
396 * <p>
397 * Note: both <code>RECOVERABLE_DEFINED</code> and <code>RECOVERABLE_NOT_DEFINED</code>
398 * indicate potentially recoverable errors, they differ in that, for
399 * <code>RECOVERABLE_DEFINED</code>, the snippet is
400 * {@linkplain Status#isDefined defined}.
401 */
402 RECOVERABLE_NOT_DEFINED(true, false),
403
404 /**
405 * The snippet is inactive because of an explicit call to
406 * the {@link JShell#drop(jdk.jshell.PersistentSnippet)}.
407 * Only a {@link jdk.jshell.PersistentSnippet} can have this
408 * <code>Status</code>.
409 * The snippet is not visible to other snippets
410 * ({@link Status#isDefined isDefined} <code> == false</code>)
411 * and thus cannot be referenced or executed.
412 * <p>
413 * The snippet will not update as dependents change
414 * ({@link Status#isActive isActive} <code> == false</code>), its
415 * <code>Status</code> will never change again.
416 */
417 DROPPED(false, false),
418
419 /**
420 * The snippet is inactive because it has been replaced by a new
421 * snippet. This occurs when the new snippet added with
422 * {@link jdk.jshell.JShell#eval} matches a previous snippet.
423 * A <code>TypeDeclSnippet</code> will match another
424 * <code>TypeDeclSnippet</code> if the names match.
425 * For example <code>class X { }</code> will overwrite
426 * <code>class X { int ii; }</code> or
427 * <code>interface X { }</code>.
428 * A <code>MethodSnippet</code> will match another
429 * <code>MethodSnippet</code> if the names and parameter types
430 * match.
431 * For example <code>void m(int a) { }</code> will overwrite
432 * <code>int m(int a) { return a+a; }</code>.
433 * A <code>VarSnippet</code> will match another
434 * <code>VarSnippet</code> if the names match.
435 * For example <code>double z;</code> will overwrite
436 * <code>long z = 2L;</code>.
437 * Only a {@link jdk.jshell.PersistentSnippet} can have this
438 * <code>Status</code>.
439 * The snippet is not visible to other snippets
440 * ({@link Status#isDefined isDefined} <code> == false</code>)
441 * and thus cannot be referenced or executed.
442 * <p>
443 * The snippet will not update as dependents change
444 * ({@link Status#isActive isActive} <code> == false</code>), its
445 * <code>Status</code> will never change again.
446 */
447 OVERWRITTEN(false, false),
448
449 /**
450 * The snippet is inactive because it failed compilation on initial
451 * evaluation and it is not capable of becoming valid with further
452 * changes to the JShell state.
453 * The snippet is not visible to other snippets
454 * ({@link Status#isDefined isDefined} <code> == false</code>)
455 * and thus cannot be referenced or executed.
456 * <p>
457 * The snippet will not update as dependents change
458 * ({@link Status#isActive isActive} <code> == false</code>), its
459 * <code>Status</code> will never change again.
460 */
461 REJECTED(false, false),
462
463 /**
464 * The snippet is inactive because it does not yet exist.
465 * Used only in {@link SnippetEvent#previousStatus} for new
466 * snippets.
467 * {@link jdk.jshell.JShell#status(jdk.jshell.Snippet) JShell.status(Snippet)}
468 * will never return this <code>Status</code>.
469 * Vacuously, {@link Status#isDefined isDefined} and
470 * {@link Status#isActive isActive} are both defined <code>false</code>.
471 */
472 NONEXISTENT(false, false);
473
474 /**
475 * Is the Snippet active, that is, will the snippet
476 * be re-evaluated when a new
477 * {@link JShell#eval(java.lang.String) JShell.eval(String)} or
478 * {@link JShell#drop(jdk.jshell.PersistentSnippet)
479 * JShell.drop(PersistentSnippet)} that could change
480 * its status is invoked? This is more broad than
481 * {@link Status#isDefined} since a Snippet which is
482 * {@link Status#RECOVERABLE_NOT_DEFINED}
483 * will be updated.
484 */
485 public final boolean isActive;
486
487 /**
488 * Is the snippet currently part of the defined state of the JShell?
489 * Is it visible to compilation of other snippets?
490 */
491 public final boolean isDefined;
492
493 Status(boolean isActive, boolean isDefined) {
494 this.isActive = isActive;
495 this.isDefined = isDefined;
496 }
497 }
498
499 private final Key key;
500 private final String source;
501 private final Wrap guts;
502 final String unitName;
503 private final SubKind subkind;
504
505 private int seq;
506 private String className;
507 private String id;
508 private OuterWrap outer;
509 private Status status;
510 private List<String> unresolved;
511 private DiagList diagnostics;
512
513 Snippet(Key key, String userSource, Wrap guts, String unitName, SubKind subkind) {
514 this.key = key;
515 this.source = userSource;
516 this.guts = guts;
517 this.unitName = unitName;
518 this.subkind = subkind;
519 this.status = Status.NONEXISTENT;
520 setSequenceNumber(0);
521 }
522
523 /**** public access ****/
524
525 /**
526 * The unique identifier for the snippet. No two active snippets will have
Robert Field39df1f12016-04-08 10:51:57 -0700527 * the same id(). Value of id has no prescribed meaning. The details of
528 * how the id is generated and the mechanism to change it is documented in
Robert Fieldc1f45bd2016-04-08 13:26:38 -0700529 * {@link JShell.Builder#idGenerator(BiFunction)}.
Jan Lahodaa21102b2015-10-19 19:15:16 +0200530 * @return the snippet id string.
531 */
532 public String id() {
533 return id;
534 }
535
536 /**
537 * The {@link jdk.jshell.Snippet.Kind} for the snippet.
538 * Indicates the subclass of Snippet.
539 * @return the Kind of the snippet
540 * @see Snippet.Kind
541 */
542 public Kind kind() {
543 return subkind.kind();
544 }
545
546 /**
547 * Return the {@link SubKind} of snippet.
548 * The SubKind is useful for feedback to users.
549 * @return the SubKind corresponding to this snippet
550 */
551 public SubKind subKind() {
552 return subkind;
553 }
554
555 /**
556 * Return the source code of the snippet.
557 * @return the source code corresponding to this snippet
558 */
559 public String source() {
560 return source;
561 }
562
563 @Override
564 public String toString() {
565 StringBuilder sb = new StringBuilder();
566 sb.append("Snippet:");
567 if (key() != null) {
568 sb.append(key().toString());
569 }
570 sb.append('-');
571 sb.append(source);
572 return sb.toString();
573 }
574
575 //**** internal access ****
576
577 String name() {
578 return unitName;
579 }
580
581 Key key() {
582 return key;
583 }
584
585 List<String> unresolved() {
586 return Collections.unmodifiableList(unresolved);
587 }
588
589 DiagList diagnostics() {
590 return diagnostics;
591 }
592
593 /**
594 * @return the corralled guts
595 */
596 Wrap corralled() {
597 return null;
598 }
599
600 Collection<String> declareReferences() {
601 return null;
602 }
603
604 Collection<String> bodyReferences() {
605 return null;
606 }
607
608 String importLine(JShell state) {
609 return "";
610 }
611
612 void setId(String id) {
613 this.id = id;
614 }
615
616 final void setSequenceNumber(int seq) {
617 this.seq = seq;
618 this.className = REPL_CLASS_PREFIX + key().index() + asLetters(seq);
619 }
620
621 void setOuterWrap(OuterWrap outer) {
622 this.outer = outer;
623 }
624
625 void setCompilationStatus(Status status, List<String> unresolved, DiagList diagnostics) {
626 this.status = status;
627 this.unresolved = unresolved;
628 this.diagnostics = diagnostics;
629 }
630
631 void setDiagnostics(DiagList diagnostics) {
632 this.diagnostics = diagnostics;
633 }
634
635 void setFailed(DiagList diagnostics) {
636 this.seq = -1;
637 this.outer = null;
638 this.status = Status.REJECTED;
639 this.unresolved = Collections.emptyList();
640 this.diagnostics = diagnostics;
641 }
642
643 void setDropped() {
644 this.status = Status.DROPPED;
645 }
646
647 void setOverwritten() {
648 this.status = Status.OVERWRITTEN;
649 }
650
651 Status status() {
652 return status;
653 }
654
655 String className() {
656 return className;
657 }
658
659 /**
660 * Top-level wrap
661 * @return
662 */
663 OuterWrap outerWrap() {
664 return outer;
665 }
666
667 /**
668 * Basically, class version for this Key.
669 * @return int
670 */
671 int sequenceNumber() {
672 return seq;
673 }
674
675 Wrap guts() {
676 return guts;
677 }
678
679 boolean isExecutable() {
680 return subkind.isExecutable();
681 }
682
683}