Source Code Cross Referenced for TJC.java in  » Scripting » jacl » tcl » lang » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Scripting » jacl » tcl.lang 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright (c) 2005 Advanced Micro Devices, Inc.
0003:         *
0004:         * See the file "license.amd" for information on usage and
0005:         * redistribution of this file, and for a DISCLAIMER OF ALL
0006:         * WARRANTIES.
0007:         * 
0008:         * RCS: @(#) $Id: TJC.java,v 1.35 2006/08/21 21:41:13 mdejong Exp $ *
0009:         */
0010:
0011:        // Runtime support for TJC compiler implementation.
0012:        package tcl.lang;
0013:
0014:        import java.util.HashMap;
0015:        import java.util.Arrays;
0016:
0017:        public class TJC {
0018:
0019:            // Constants
0020:
0021:            public static final int SWITCH_MODE_EXACT = 0;
0022:            public static final int SWITCH_MODE_GLOB = 1;
0023:            public static final int SWITCH_MODE_REGEXP = 2;
0024:
0025:            public static final int EXPR_OP_MULT = Expression.MULT;
0026:            public static final int EXPR_OP_DIVIDE = Expression.DIVIDE;
0027:            public static final int EXPR_OP_MOD = Expression.MOD;
0028:            public static final int EXPR_OP_PLUS = Expression.PLUS;
0029:            public static final int EXPR_OP_MINUS = Expression.MINUS;
0030:            public static final int EXPR_OP_LEFT_SHIFT = Expression.LEFT_SHIFT;
0031:            public static final int EXPR_OP_RIGHT_SHIFT = Expression.RIGHT_SHIFT;
0032:            public static final int EXPR_OP_LESS = Expression.LESS;
0033:            public static final int EXPR_OP_GREATER = Expression.GREATER;
0034:            public static final int EXPR_OP_LEQ = Expression.LEQ;
0035:            public static final int EXPR_OP_GEQ = Expression.GEQ;
0036:            public static final int EXPR_OP_EQUAL = Expression.EQUAL;
0037:            public static final int EXPR_OP_NEQ = Expression.NEQ;
0038:            public static final int EXPR_OP_BIT_AND = Expression.BIT_AND;
0039:            public static final int EXPR_OP_BIT_XOR = Expression.BIT_XOR;
0040:            public static final int EXPR_OP_BIT_OR = Expression.BIT_OR;
0041:            public static final int EXPR_OP_STREQ = Expression.STREQ;
0042:            public static final int EXPR_OP_STRNEQ = Expression.STRNEQ;
0043:
0044:            public static final int EXPR_OP_UNARY_MINUS = Expression.UNARY_MINUS;
0045:            public static final int EXPR_OP_UNARY_PLUS = Expression.UNARY_PLUS;
0046:            public static final int EXPR_OP_UNARY_NOT = Expression.NOT;
0047:            public static final int EXPR_OP_UNARY_BIT_NOT = Expression.BIT_NOT;
0048:
0049:            public static final WrappedCommand INVALID_COMMAND_CACHE;
0050:
0051:            static {
0052:                // Setup a fake command wrapper. The only
0053:                // point of this is to have a wrapper with
0054:                // and invalid cmdEpoch that will never be
0055:                // equal to a valid cmdEpoch for a command.
0056:
0057:                INVALID_COMMAND_CACHE = new WrappedCommand();
0058:                INVALID_COMMAND_CACHE.deleted = true;
0059:                INVALID_COMMAND_CACHE.cmdEpoch = -1;
0060:            }
0061:
0062:            // Invoked to create and push a new CallFrame for local
0063:            // variables when a command begins to execute. This
0064:            // method does not assign method arguments to local
0065:            // variables inside the CallFrame. The logic here is
0066:            // copied from CallFrame.chain().
0067:
0068:            public static CallFrame pushLocalCallFrame(Interp interp,
0069:                    Namespace ns) {
0070:                CallFrame frame = interp.newCallFrame();
0071:
0072:                // Namespace the command is defined in, default to global namespace
0073:
0074:                if (ns != null) {
0075:                    frame.ns = ns;
0076:                }
0077:
0078:                // ignore objv
0079:
0080:                // isProcCallFrame should be true
0081:                if (frame.isProcCallFrame == false) {
0082:                    throw new TclRuntimeError(
0083:                            "expected isProcCallFrame to be true");
0084:                }
0085:
0086:                frame.level = (interp.varFrame == null) ? 1
0087:                        : (interp.varFrame.level + 1);
0088:                frame.caller = interp.frame;
0089:                frame.callerVar = interp.varFrame;
0090:                interp.frame = frame;
0091:                interp.varFrame = frame;
0092:
0093:                return frame;
0094:            }
0095:
0096:            // Invoked to pop a local CallFrame when a command is finished.
0097:
0098:            public static void popLocalCallFrame(Interp interp, CallFrame frame) {
0099:                // Cleanup code copied from Procedure.java. See the cmdProc
0100:                // implementation in that class for more info.
0101:
0102:                if (interp.errInProgress) {
0103:                    frame.dispose();
0104:                    interp.errInProgress = true;
0105:                } else {
0106:                    frame.dispose();
0107:                }
0108:            }
0109:
0110:            // Invoked to add a compiledLocals array to a
0111:            // CallFrame that was just pushed. This
0112:            // compiledLocals array is disposed of
0113:            // automatically when the CallFrame is popped.
0114:
0115:            public static Var[] initCompiledLocals(final CallFrame frame,
0116:                    final int size, final String[] names) {
0117:                frame.compiledLocalsNames = names;
0118:                return frame.compiledLocals = new Var[size];
0119:            }
0120:
0121:            // Evaluate a Tcl string that is the body of a Tcl procedure.
0122:
0123:            public static void evalProcBody(Interp interp, String body)
0124:                    throws TclException {
0125:                interp.eval(body);
0126:            }
0127:
0128:            // Check a TclException raised while a compiled Tcl procedure
0129:            // is executing. This method should be invoked from a catch
0130:            // block around the body code for a proc. This method could
0131:            // handle the exception and stop if from propagating in the
0132:            // case of a return, or it could allow it to propagate for
0133:            // a normal error case. The logic in this method is copied
0134:            // from Procedure.cmdProc().
0135:
0136:            public static void checkTclException(Interp interp, TclException e,
0137:                    String procName) throws TclException {
0138:                // FIXME: Ugh this is nasty. How can TCL.OK be package private if this
0139:                // kind of mess could appear in the result from any eval()? All of this
0140:                // should be in an interp method to handle these cases.
0141:
0142:                int code = e.getCompletionCode();
0143:                if (code == TCL.RETURN) {
0144:                    int realCode = interp.updateReturnInfo();
0145:                    if (realCode != TCL.OK) {
0146:                        e.setCompletionCode(realCode);
0147:                        throw e;
0148:                    }
0149:                } else if (code == TCL.ERROR) {
0150:                    interp.addErrorInfo("\n    (procedure \"" + procName
0151:                            + "\" line 1)");
0152:                    throw e;
0153:                } else if (code == TCL.BREAK) {
0154:                    throw new TclException(interp,
0155:                            "invoked \"break\" outside of a loop");
0156:                } else if (code == TCL.CONTINUE) {
0157:                    throw new TclException(interp,
0158:                            "invoked \"continue\" outside of a loop");
0159:                } else {
0160:                    throw e;
0161:                }
0162:            }
0163:
0164:            // Base class for TJC compiled commands
0165:
0166:            public static abstract class CompiledCommand implements  Command {
0167:                public WrappedCommand wcmd = null;
0168:
0169:                // A CompiledCommand implementation must define cmdProc
0170:
0171:                // This flag is used to indicate that the command was
0172:                // compiled with inlined Tcl commands.
0173:
0174:                protected boolean inlineCmds = false;
0175:
0176:                // A CompiledCommand implementation may want to init
0177:                // instance data members when first invoked. This
0178:                // flag and method are used to implement this init
0179:                // check.
0180:
0181:                protected boolean initCmd = false;
0182:
0183:                protected void initCmd(Interp interp) throws TclException {
0184:                    if (initCmd) {
0185:                        throw new TclRuntimeError("initCmd already invoked");
0186:                    }
0187:                    builtinCommandsCheck(interp);
0188:                    initConstants(interp);
0189:                    initCmd = true;
0190:                }
0191:
0192:                // The following method should be defined in a specific
0193:                // command implementations to init constant instance data.
0194:
0195:                protected void initConstants(Interp interp) throws TclException {
0196:                }
0197:
0198:                // Verify that this compiled command is not being used
0199:                // in a namespace that contains commands with the same
0200:                // name Tcl commands that could have been inlined.
0201:                // Since this check is only done when the command is
0202:                // first invoked, it should not be a performance concern.
0203:
0204:                protected void builtinCommandsCheck(Interp interp)
0205:                        throws TclException {
0206:                    if (wcmd.ns.fullName.equals("::")) {
0207:                        return; // loaded into global namespace
0208:                    }
0209:                    String[] containers = { "break", "catch", "continue",
0210:                            "expr", "for", "foreach", "if", "return", "switch",
0211:                            "while" };
0212:                    String[] containers_and_inlines = { "break", "catch",
0213:                            "continue", "expr", "for", "foreach", "global",
0214:                            "if", "list", "llength", "return", "set", "switch",
0215:                            "while" };
0216:                    String[] builtin = (inlineCmds ? containers_and_inlines
0217:                            : containers);
0218:                    WrappedCommand cmd;
0219:                    String cmdName;
0220:                    for (int i = 0; i < builtin.length; i++) {
0221:                        cmdName = builtin[i];
0222:                        cmd = Namespace.findCommand(interp, cmdName, wcmd.ns,
0223:                                TCL.NAMESPACE_ONLY);
0224:                        if (cmd != null) {
0225:                            throw new TclException(
0226:                                    interp,
0227:                                    "TJC compiled command"
0228:                                            + " can't be loaded into the namespace "
0229:                                            + wcmd.ns.fullName
0230:                                            + " as it defines the builtin Tcl command \""
0231:                                            + cmdName + "\" (" + cmd.toString()
0232:                                            + ")");
0233:                        }
0234:                    }
0235:                }
0236:
0237:                // The following methods are used in compiled commands
0238:                // that make use of cached variable access.
0239:
0240:                // initVarScoped() is invoked for a scoped variable
0241:                // like "::myglobal". This method will create a local
0242:                // var linked to a variable defined in another scope
0243:                // if the compiled local has not been initialized yet.
0244:
0245:                protected final void initVarScoped(final Interp interp,
0246:                        final String varname, // Fully qualified varname
0247:                        // including namespace scope.
0248:                        // Can be array or scalar.
0249:                        final Var[] compiledLocals, final int localIndex)
0250:                        throws TclException {
0251:                    if (compiledLocals[localIndex] == null) {
0252:                        // Passing EXPLICIT_LOCAL_NAME tells makeUpvar 
0253:                        // to do nothing when varname lookup fails.
0254:                        Var.makeUpvar(interp, null, varname, null,
0255:                                TCL.GLOBAL_ONLY, varname,
0256:                                Var.EXPLICIT_LOCAL_NAME, localIndex);
0257:                    }
0258:                }
0259:
0260:                // getVarScalar() will get a variable value, if a
0261:                // cached variable is available then it will be used.
0262:                // Otherwise the runtime getVar() will be invoked to get
0263:                // the value. This method will raise a TclException
0264:                // on error, it will never return null.
0265:
0266:                protected final TclObject getVarScalar(final Interp interp,
0267:                        final String varname, // Scalar variable name
0268:                        final Var[] compiledLocals, final int localIndex)
0269:                        throws TclException {
0270:                    Var var = compiledLocals[localIndex];
0271:
0272:                    if ((var == null)
0273:                            || ((var = Var.resolveScalar(var)) == null)) {
0274:                        return Var.getVarCompiledLocalScalarInvalid(interp,
0275:                                varname);
0276:                    } else {
0277:                        return var.tobj;
0278:                    }
0279:                }
0280:
0281:                // getVarArray() will get an array element value,
0282:                // if a cached variable is available, then it will be used.
0283:                // Otherwise the runtime getVar() will be invoked to get
0284:                // the value. This method will raise a TclException
0285:                // on error, it will never return null.
0286:
0287:                protected final TclObject getVarArray(final Interp interp,
0288:                        final String varname, // Array variable name
0289:                        final String key, // Array key
0290:                        final Var[] compiledLocals, final int localIndex)
0291:                        throws TclException {
0292:                    Var var = compiledLocals[localIndex];
0293:
0294:                    if (var == null || ((var = Var.resolveArray(var)) == null)) {
0295:                        return Var.getVarCompiledLocalArrayInvalid(interp,
0296:                                varname, key);
0297:                    } else {
0298:                        return Var.getVarCompiledLocalArray(interp, varname,
0299:                                key, var, true);
0300:                    }
0301:                }
0302:
0303:                // setVarScalar() will set a scalar variable value,
0304:                // if a cached variable is available then it will be used,
0305:                // otherwise the runtime setVar() will be invoked to set
0306:                // the value. This method will raise a TclException
0307:                // on error, it will never return null.
0308:
0309:                protected final TclObject setVarScalar(final Interp interp,
0310:                        final String varname, // Scalar variable name
0311:                        final TclObject value, // New variable value
0312:                        final Var[] compiledLocals, final int localIndex)
0313:                        throws TclException {
0314:                    Var var = compiledLocals[localIndex];
0315:
0316:                    if (var == null) {
0317:                        return Var.initVarCompiledLocalScalar(interp, varname,
0318:                                value, compiledLocals, localIndex);
0319:                    } else if ((var = Var.resolveScalar(var)) == null) {
0320:                        return Var.setVarCompiledLocalScalarInvalid(interp,
0321:                                varname, value);
0322:                    } else {
0323:                        TJC.setVarScalar(var, value);
0324:                        return value;
0325:                    }
0326:                }
0327:
0328:                protected final TclObject setVarScalar(final Interp interp,
0329:                        final String varname, final String value,
0330:                        final Var[] compiledLocals, final int localIndex)
0331:                        throws TclException {
0332:                    TclObject tobj = interp.checkCommonString(value);
0333:                    return setVarScalar(interp, varname, tobj, compiledLocals,
0334:                            localIndex);
0335:                }
0336:
0337:                // setVarArray() will set an array element to a value,
0338:                // if a cached variable is available then it will be used,
0339:                // otherwise the runtime setVar() will be invoked to set
0340:                // the value. This method will raise a TclException
0341:                // on error, it will never return null.
0342:
0343:                protected final TclObject setVarArray(final Interp interp,
0344:                        final String varname, final String key,
0345:                        final TclObject value, final Var[] compiledLocals,
0346:                        final int localIndex) throws TclException {
0347:                    Var var = compiledLocals[localIndex];
0348:
0349:                    if (var == null) {
0350:                        return Var.initVarCompiledLocalArray(interp, varname,
0351:                                key, value, compiledLocals, localIndex);
0352:                    } else if ((var = Var.resolveArray(var)) == null) {
0353:                        return Var.setVarCompiledLocalArrayInvalid(interp,
0354:                                varname, key, value);
0355:                    } else {
0356:                        return Var.setVarCompiledLocalArray(interp, varname,
0357:                                key, value, var);
0358:                    }
0359:                }
0360:
0361:                protected final TclObject setVarArray(final Interp interp,
0362:                        final String varname, final String key,
0363:                        final String value, final Var[] compiledLocals,
0364:                        final int localIndex) throws TclException {
0365:                    TclObject tobj = interp.checkCommonString(value);
0366:                    return setVarArray(interp, varname, key, tobj,
0367:                            compiledLocals, localIndex);
0368:                }
0369:
0370:                // incrVarScalar() will increment a scalar compiled local
0371:                // by the given incrAmount. If the variable is not a
0372:                // scalar local or has traces set then the runtime version
0373:                // of the incr command will be used.
0374:
0375:                protected final TclObject incrVarScalar(final Interp interp,
0376:                        final String varname, final int incrAmount,
0377:                        final Var[] compiledLocals, final int localIndex)
0378:                        throws TclException {
0379:                    Var var = compiledLocals[localIndex];
0380:
0381:                    if (var == null || ((var = Var.resolveScalar(var)) == null)) {
0382:                        return TJC.incrVar(interp, varname, null, incrAmount);
0383:                    } else {
0384:                        TclObject varValue = var.tobj;
0385:
0386:                        boolean createdNewObj = false;
0387:                        if (varValue.isShared()) {
0388:                            varValue = varValue.duplicate();
0389:                            createdNewObj = true;
0390:                        }
0391:                        try {
0392:                            TclInteger.incr(interp, varValue, incrAmount);
0393:                        } catch (TclException ex) {
0394:                            if (createdNewObj) {
0395:                                varValue.release(); // free unneeded copy
0396:                            }
0397:                            throw ex;
0398:                        }
0399:
0400:                        // If we create a new TclObject, then save it
0401:                        // as the variable value.
0402:
0403:                        if (createdNewObj) {
0404:                            TJC.setVarScalar(var, varValue);
0405:                        }
0406:                        return varValue;
0407:                    }
0408:                }
0409:
0410:                // incrVarArray() will increment an array element.
0411:                // If the array is not a compiled local scalar then
0412:                // the runtime implementation will be used.
0413:
0414:                protected final TclObject incrVarArray(final Interp interp,
0415:                        final String varname, final String key,
0416:                        final int incrAmount, final Var[] compiledLocals,
0417:                        final int localIndex) throws TclException {
0418:                    Var var = compiledLocals[localIndex];
0419:
0420:                    if (var == null || ((var = Var.resolveArray(var)) == null)) {
0421:                        return TJC.incrVar(interp, varname, key, incrAmount);
0422:                    } else {
0423:                        TclObject varValue = Var.getVarCompiledLocalArray(
0424:                                interp, varname, key, var, true);
0425:
0426:                        boolean createdNewObj = false;
0427:                        if (varValue.isShared()) {
0428:                            varValue = varValue.duplicate();
0429:                            createdNewObj = true;
0430:                        }
0431:                        try {
0432:                            TclInteger.incr(interp, varValue, incrAmount);
0433:                        } catch (TclException ex) {
0434:                            if (createdNewObj) {
0435:                                varValue.release(); // free unneeded copy
0436:                            }
0437:                            throw ex;
0438:                        }
0439:
0440:                        // Set the array element once again since the
0441:                        // variable could have traces.
0442:
0443:                        return Var.setVarCompiledLocalArray(interp, varname,
0444:                                key, varValue, var);
0445:                    }
0446:                }
0447:
0448:                // lappendVarScalar() will append list elements to
0449:                // a scalar local variable. If the variable is not a
0450:                // scalar local or has traces set then the runtime version
0451:                // of the lappend command will be used.
0452:
0453:                protected final TclObject lappendVarScalar(final Interp interp,
0454:                        final String varname, final TclObject[] values,
0455:                        final Var[] compiledLocals, final int localIndex)
0456:                        throws TclException {
0457:                    Var var = compiledLocals[localIndex];
0458:
0459:                    // Use runtime impl of lappend if resolved var
0460:                    // is not available. The lappend command
0461:                    // accepts an undefined variable name, but we
0462:                    // don't optimize that case.
0463:
0464:                    if (var == null || ((var = Var.resolveScalar(var)) == null)) {
0465:                        return TJC.lappendVar(interp, varname, null, values);
0466:                    }
0467:
0468:                    // The cache var is valid, but it might indicate
0469:                    // a shared value. If the value is shared then
0470:                    // we need to duplicate it and invoke setVar()
0471:                    // to implement "copy on write".
0472:
0473:                    TclObject varValue = var.tobj;
0474:                    boolean createdNewObj = false;
0475:
0476:                    if (varValue.isShared()) {
0477:                        varValue = varValue.duplicate();
0478:                        createdNewObj = true;
0479:                    }
0480:
0481:                    // Insert the new elements at the end of the list.
0482:
0483:                    final int len = values.length;
0484:                    if (len == 1) {
0485:                        TclList.append(interp, varValue, values[0]);
0486:                    } else {
0487:                        TclList.append(interp, varValue, values, 0, len);
0488:                    }
0489:
0490:                    if (createdNewObj) {
0491:                        TJC.setVarScalar(var, varValue);
0492:                    }
0493:                    return varValue;
0494:                }
0495:
0496:                // lappendVarArray() will append list elements to
0497:                // an array element in a compiled local array variable.
0498:                // If the variable is not an array variable then the runtime
0499:                // implementation of the lappend command will be used.
0500:
0501:                protected final TclObject lappendVarArray(final Interp interp,
0502:                        final String varname, final String key,
0503:                        final TclObject[] values, final Var[] compiledLocals,
0504:                        final int localIndex) throws TclException {
0505:                    Var var = compiledLocals[localIndex];
0506:
0507:                    // Use runtime impl of lappend if resolved array
0508:                    // var is null or is not valid. The lappend command
0509:                    // accepts an undefined variable name, but we
0510:                    // don't optimize that case.
0511:
0512:                    if (var == null || ((var = Var.resolveArray(var)) == null)) {
0513:                        return TJC.lappendVar(interp, varname, key, values);
0514:                    }
0515:
0516:                    // The cache var is valid but need to lookup the
0517:                    // array element to see if it exists. If the
0518:                    // array element does not exist then it is
0519:                    // assumed to be an empty list. If the element
0520:                    // does exist, then check to see if it is
0521:                    // shared and if so then make a copy to
0522:                    // implement "copy on write".
0523:
0524:                    TclObject varValue = Var.getVarCompiledLocalArray(interp,
0525:                            varname, key, var, false);
0526:
0527:                    if (varValue == null) {
0528:                        // Array element does not exist, use {}
0529:                        varValue = TclList.newInstance();
0530:                    } else if (varValue.isShared()) {
0531:                        varValue = varValue.duplicate();
0532:                    }
0533:
0534:                    // Insert the new elements at the end of the list.
0535:
0536:                    final int len = values.length;
0537:                    if (len == 1) {
0538:                        TclList.append(interp, varValue, values[0]);
0539:                    } else {
0540:                        TclList.append(interp, varValue, values, 0, len);
0541:                    }
0542:
0543:                    return Var.setVarCompiledLocalArray(interp, varname, key,
0544:                            varValue, var);
0545:                }
0546:
0547:                // appendVarScalar() will append string elements to
0548:                // a scalar local variable. If the variable is not a
0549:                // scalar local or has traces set then the runtime version
0550:                // of the append command will be used.
0551:
0552:                protected final TclObject appendVarScalar(final Interp interp,
0553:                        final String varname, final TclObject[] values,
0554:                        final Var[] compiledLocals, final int localIndex)
0555:                        throws TclException {
0556:                    Var var = compiledLocals[localIndex];
0557:
0558:                    // Use runtime impl of append if resolved var
0559:                    // is not available. The append command
0560:                    // accepts an undefined variable name, but we
0561:                    // don't optimize that case.
0562:
0563:                    if (var == null || (var = Var.resolveScalar(var)) == null) {
0564:                        return TJC.appendVar(interp, varname, null, values);
0565:                    }
0566:
0567:                    // The cache var is valid, but it might indicate
0568:                    // a shared value. If the value is shared then
0569:                    // we need to create a new TclString object
0570:                    // and drop refs to the previous TclObject value.
0571:
0572:                    TclObject varValue = var.tobj;
0573:                    boolean createdNewObj = false;
0574:
0575:                    if (varValue.isShared()) {
0576:                        varValue = TclString.newInstance(varValue.toString());
0577:                        createdNewObj = true;
0578:                    }
0579:
0580:                    // Insert the new elements at the end of the string.
0581:
0582:                    final int len = values.length;
0583:                    if (len == 1) {
0584:                        TclString.append(varValue, values[0].toString());
0585:                    } else {
0586:                        TclString.append(varValue, values, 0, len);
0587:                    }
0588:
0589:                    if (createdNewObj) {
0590:                        TJC.setVarScalar(var, varValue);
0591:                    }
0592:                    return varValue;
0593:                }
0594:
0595:                // appendVarArray() will append string elements to an
0596:                // element inside an array variable.
0597:
0598:                protected final TclObject appendVarArray(final Interp interp,
0599:                        final String varname, final String key,
0600:                        final TclObject[] values, final Var[] compiledLocals,
0601:                        final int localIndex) throws TclException {
0602:                    // This is way lame, but the append command
0603:                    // semantics for arrays with traces are
0604:                    // such that we can't use an optimized
0605:                    // implementation. Use the runtime append
0606:                    // command implementation for now until
0607:                    // the Tcl core can be fixed to correct this.
0608:                    // The implementation should work the same
0609:                    // way as the lappend command.
0610:
0611:                    return TJC.appendVar(interp, varname, key, values);
0612:                }
0613:
0614:            } // end class CompiledCommand
0615:
0616:            // Used to create a TJC compiled command. This method will
0617:            // use the fully qualified command name passed in to
0618:            // create the command in the correct namespace.
0619:
0620:            public static void createCommand(Interp interp, // Interp to create command in
0621:                    String cmdName, // Fully qualified or short name of command
0622:                    TJC.CompiledCommand cmd) // Instance for new compiled command
0623:                    throws TclException {
0624:                ProcCmd.FindCommandNamespaceResult result = ProcCmd
0625:                        .FindCommandNamespace(interp, cmdName);
0626:
0627:                interp.createCommand(result.cmdFullName, cmd);
0628:
0629:                cmd.wcmd = Namespace.findCommand(interp, result.cmdName,
0630:                        result.ns, TCL.NAMESPACE_ONLY);
0631:            }
0632:
0633:            // Used to load an init file from the package JAR file.
0634:            // This command should be invoked from a TJCExtension
0635:            // to source the init Tcl script in the JAR. It is
0636:            // possible that the TJC package is not yet loaded
0637:            // if java::load was used to load the Extension. Just
0638:            // require TJC package to take care of this case.
0639:
0640:            public static void sourceInitFile(Interp interp, String init_file,
0641:                    String[] files, String prefix) throws TclException {
0642:                // Install temp source command
0643:                interp.eval("package require TJC");
0644:                interp.eval("rename ::source ::TJC::source");
0645:                interp.createCommand("::source", new InitSourceCmd(init_file,
0646:                        files, prefix));
0647:
0648:                //System.out.println("sourceInitFile: will source \"" + (prefix + init_file) + "\"");
0649:                TclException tex = null;
0650:                try {
0651:                    interp.evalResource(prefix + init_file);
0652:                } catch (TclException ex) {
0653:                    tex = ex;
0654:                } finally {
0655:                    // Remove temp source command
0656:                    interp.eval("rename ::source {}");
0657:                    interp.eval("rename ::TJC::source ::source");
0658:
0659:                    if (tex != null) {
0660:                        interp.setResult(tex.getMessage());
0661:                        throw tex;
0662:                    }
0663:                }
0664:            }
0665:
0666:            // This class implements a fake "source" command that is
0667:            // only active while a package init file is being sourced
0668:            // inside sourceInitFile().
0669:
0670:            static class InitSourceCmd implements  Command {
0671:                String init_file;
0672:                String[] files;
0673:                String prefix;
0674:                HashMap filesTable;
0675:
0676:                InitSourceCmd(String init_file, String[] files, String prefix) {
0677:                    this .init_file = init_file;
0678:                    this .files = files;
0679:                    this .prefix = prefix;
0680:
0681:                    filesTable = new HashMap();
0682:                    for (int i = 0; i < files.length; i++) {
0683:                        filesTable.put(files[i], "");
0684:                    }
0685:                }
0686:
0687:                public void cmdProc(Interp interp, TclObject[] objv)
0688:                        throws TclException {
0689:                    boolean handled = false;
0690:
0691:                    // Expected syntax "source filename"
0692:
0693:                    if (objv.length == 2) {
0694:                        String filepath = objv[1].toString();
0695:
0696:                        interp.eval("file tail {" + filepath + "}");
0697:
0698:                        String filename = interp.getResult().toString();
0699:
0700:                        if (filesTable.containsKey(filename)) {
0701:                            // Sourced a file in files array, this
0702:                            // file should be read from a resource.
0703:                            handled = true;
0704:
0705:                            //System.out.println("sourceInitFile.files: will source \"" + (prefix + filename) + "\"");
0706:                            interp.evalResource(prefix + filename);
0707:                        }
0708:                    }
0709:
0710:                    if (!handled) {
0711:                        // Invoke TJC::source, this is the original source command.
0712:                        // The original command will deal with error reporting
0713:                        // as well as invocations that source a file not in "files".
0714:                        Command cmd = interp.getCommand("TJC::source");
0715:                        cmd.cmdProc(interp, objv);
0716:                    }
0717:                }
0718:            }
0719:
0720:            // Resolve a command name into a WrappedCommand reference
0721:            // that is cached. Note that this method is only ever
0722:            // invoked after a command has been successfully invoked,
0723:            // so there should be no need to worry about loading the
0724:            // command or dealing with stub commands. If the command
0725:            // can't be located, null is returned. This command is
0726:            // always invoked after the CallFrame for a compiled
0727:            // command has been pushed, so it is safe to assume
0728:            // that the current namespace is the namespace the
0729:            // command is defined in.
0730:
0731:            public static WrappedCommand resolveCmd(Interp interp,
0732:                    String cmdName) throws TclException {
0733:                return Namespace.findCommand(interp, cmdName, null, 0);
0734:            }
0735:
0736:            // This method is used to set the TclObject value
0737:            // contained inside a cached scalar Var reference.
0738:            // This method works like interp.setVar(), it should
0739:            // be used when a valid cached var reference is
0740:            // held.
0741:
0742:            static final void setVarScalar(final Var var,
0743:                    final TclObject newValue) // New value to set varible to, can't be null
0744:            {
0745:                TclObject oldValue = var.tobj;
0746:                if (oldValue != newValue) {
0747:                    var.tobj = newValue;
0748:                    newValue.preserve();
0749:                    if (oldValue != null) {
0750:                        oldValue.release();
0751:                    }
0752:                }
0753:                // Unlike Var.setVar(), this method does not invoke
0754:                // setVarScalar() or clearVarUndefined() since a
0755:                // cached array variable will never be passed to
0756:                // this method and an undefined variable will never
0757:                // be cached. This method does not return a value
0758:                // since the return value would always be the passed
0759:                // in newValue.
0760:                return;
0761:            }
0762:
0763:            // This method is invoked when a compiled incr command
0764:            // is inlined. This methods works for both scalar
0765:            // variables and array scalars. This method is not
0766:            // used for cached variables.
0767:
0768:            public static final TclObject incrVar(Interp interp, String part1,
0769:                    String part2, int incrAmount) throws TclException {
0770:                return Var.incrVar(interp, part1, part2, incrAmount,
0771:                        TCL.LEAVE_ERR_MSG);
0772:            }
0773:
0774:            // Get a TclObject[] of the given size. This array will
0775:            // be allocated quickly from a cache if it is a common size.
0776:            // The array must be released by releaseObjv(). Each element
0777:            // in the returned array will be null.
0778:
0779:            private static final boolean USE_OBJV_CACHE = true;
0780:
0781:            public static TclObject[] grabObjv(final Interp interp,
0782:                    final int size) {
0783:                if (USE_OBJV_CACHE) {
0784:                    return Parser.grabObjv(interp, size);
0785:                } else {
0786:                    return new TclObject[size];
0787:                }
0788:            }
0789:
0790:            // Release the array back into the common array
0791:            // cache. This array must have been allocated
0792:            // with grabObjv(). This method will not release
0793:            // TclObject values in the array, use the
0794:            // releaseObjvElems() method for that.
0795:
0796:            public static void releaseObjv(final Interp interp,
0797:                    final TclObject[] objv, final int size) {
0798:                if (USE_OBJV_CACHE) {
0799:                    Parser.releaseObjv(interp, objv, size);
0800:                }
0801:            }
0802:
0803:            // For each non-null TclObject element in the array,
0804:            // invoke TclObject.release() and then return the
0805:            // array to the common cache of array values.
0806:            // The array must have been allocated with grabObjv().
0807:
0808:            public static void releaseObjvElems(final Interp interp,
0809:                    final TclObject[] objv, final int size) {
0810:                for (int i = 0; i < size; i++) {
0811:                    TclObject tobj = objv[i];
0812:                    if (tobj != null) {
0813:                        tobj.release();
0814:                    }
0815:                }
0816:                if (USE_OBJV_CACHE) {
0817:                    Parser.releaseObjv(interp, objv, size);
0818:                }
0819:            }
0820:
0821:            // Invoke a Command with TclObject arguments. This method
0822:            // will invoke an already resolved Command passed in "cmd" or
0823:            // it will resolve objv[0] into a command. This method
0824:            // assumes that the ref count of each element in the
0825:            // objv was already incremented by the caller. This method
0826:            // does not modify or cleanup the passed in objv array.
0827:
0828:            public static void invoke(Interp interp, // Interp to invoke command in
0829:                    Command cmd, // Resolved command ref, null to lookup objv[0]
0830:                    TclObject[] objv, // TclObject arguments to command
0831:                    int flags) // Either 0 or TCL.EVAL_GLOBAL. If 0 is passed
0832:                    // then objv[0] is resolved in the current
0833:                    // namespace and then the global one. If
0834:                    // TCL.EVAL_GLOBAL is passed then the command
0835:                    // is resolved and evaluated in the global namespace.
0836:                    // If the cmd argument is non-null, then this
0837:                    // flag only controls evaluation scope.
0838:                    throws TclException {
0839:                boolean grabbed_objv = false;
0840:
0841:                // Save copy of interp.varFrame in case TCL.EVAL_GLOBAL is set.
0842:                CallFrame savedVarFrame = interp.varFrame;
0843:
0844:                // If cmd is null, then resolve objv[0] into a Command.
0845:
0846:                if (cmd == null) {
0847:                    WrappedCommand wcmd;
0848:                    int fflags = 0;
0849:                    if ((flags & TCL.EVAL_GLOBAL) != 0) {
0850:                        fflags |= TCL.GLOBAL_ONLY;
0851:                    }
0852:                    // Find the procedure to execute this command. If there isn't one,
0853:                    // then see if there is a command "unknown".  If so, create a new
0854:                    // word array with "unknown" as the first word and the original
0855:                    // command words as arguments.
0856:                    String cmdName = objv[0].toString();
0857:                    wcmd = Namespace.findCommand(interp, cmdName, null, fflags);
0858:                    if (wcmd != null) {
0859:                        cmd = wcmd.cmd;
0860:                    }
0861:                    if (cmd == null) {
0862:                        wcmd = Namespace.findCommand(interp, "unknown", null,
0863:                                TCL.GLOBAL_ONLY);
0864:                        if (wcmd != null) {
0865:                            cmd = wcmd.cmd;
0866:                        }
0867:                        if (cmd == null) {
0868:                            throw new TclException(interp,
0869:                                    "invalid command name \"" + cmdName + "\"");
0870:                        }
0871:                        int len = objv.length;
0872:                        if (len == 0) {
0873:                            throw new TclRuntimeError("zero length objv array");
0874:                        }
0875:                        TclObject[] newObjv = TJC.grabObjv(interp, len + 1);
0876:                        newObjv[0] = TclString.newInstance("unknown");
0877:                        newObjv[0].preserve();
0878:                        for (int i = (len - 1); i >= 0; i--) {
0879:                            newObjv[i + 1] = objv[i];
0880:                        }
0881:                        objv = newObjv;
0882:                        grabbed_objv = true;
0883:                    }
0884:                }
0885:
0886:                try {
0887:                    interp.preserve();
0888:                    interp.allowExceptions();
0889:
0890:                    interp.ready();
0891:
0892:                    interp.nestLevel++;
0893:                    interp.cmdCount++;
0894:
0895:                    // Invoke cmdProc for the command.
0896:
0897:                    if ((flags & TCL.EVAL_GLOBAL) != 0) {
0898:                        interp.varFrame = null;
0899:                    }
0900:
0901:                    cmd.cmdProc(interp, objv);
0902:                } catch (TclException ex) {
0903:                    // Generate error info that includes the arguments
0904:                    // to the command and add these to the errorInfo var.
0905:
0906:                    if (ex.getCompletionCode() == TCL.ERROR
0907:                            && !(interp.errAlreadyLogged)) {
0908:                        StringBuffer cmd_strbuf = new StringBuffer(64);
0909:
0910:                        int len = objv.length;
0911:                        if (len == 0) {
0912:                            throw new TclRuntimeError("zero length objv array");
0913:                        }
0914:                        for (int i = 0; i < len; i++) {
0915:                            Util.appendElement(interp, cmd_strbuf, objv[i]
0916:                                    .toString());
0917:                        }
0918:                        String cmd_str = cmd_strbuf.toString();
0919:                        char[] script_array = cmd_str.toCharArray();
0920:                        int script_index = 0;
0921:                        int command_start = 0;
0922:                        int command_length = cmd_str.length();
0923:                        Parser
0924:                                .logCommandInfo(interp, script_array,
0925:                                        script_index, command_start,
0926:                                        command_length, ex);
0927:                    }
0928:
0929:                    throw ex;
0930:                } finally {
0931:                    if (grabbed_objv) {
0932:                        objv[0].release();
0933:                        TJC.releaseObjv(interp, objv, objv.length);
0934:                    }
0935:                    interp.nestLevel--;
0936:                    interp.varFrame = savedVarFrame;
0937:                    interp.release();
0938:
0939:                    interp.checkInterrupted();
0940:                }
0941:            }
0942:
0943:            // Most efficient way to query a TclObject
0944:            // to determine its boolean value. If a
0945:            // TclString is passed into this method,
0946:            // it will be parsed and the object's internal
0947:            // rep will be updated to a numeric type.
0948:
0949:            public static boolean getBoolean(final Interp interp,
0950:                    final TclObject obj) throws TclException {
0951:                if (obj.isIntType()) {
0952:                    return (obj.ivalue != 0); // Inline TclInteger.get()
0953:                } else if (obj.isDoubleType()) {
0954:                    return (TJC.exprGetKnownDouble(obj) != 0.0);
0955:                }
0956:
0957:                ExprValue value;
0958:                if (USE_EXPR_CACHE) {
0959:                    value = interp.expr.grabExprValue();
0960:                } else {
0961:                    value = new ExprValue(0, null);
0962:                }
0963:                // The logic above already checked for an int or
0964:                // double type so just reparse from the string
0965:                // instead of calling ExprParseObject().
0966:                Expression.ExprParseString(interp, obj, value);
0967:                boolean b = value.getBooleanValue(interp);
0968:                if (USE_EXPR_CACHE) {
0969:                    interp.expr.releaseExprValue(value);
0970:                }
0971:                return b;
0972:            }
0973:
0974:            // This method will invoke logic for the switch
0975:            // command at runtime. If no body is matched,
0976:            // then -1 will be returned. Otherwise, the
0977:            // offset from the first pattern is returned.
0978:            // The caller must take care to release the
0979:            // pbObjv array after invoking this method.
0980:
0981:            public static int invokeSwitch(Interp interp, TclObject[] pbObjv,
0982:                    int pbStart, // Index > 0 of first pattern
0983:                    String string, // String to be matched against patterns
0984:                    int mode) // Either TJC.SWITCH_MODE_EXACT
0985:                    // or     TJC.SWITCH_MODE_GLOB
0986:                    // or     TJC.SWITCH_MODE_REGEXP
0987:                    throws TclException {
0988:                int offset = SwitchCmd.getBodyOffset(interp, pbObjv, pbStart,
0989:                        string, mode);
0990:                return offset;
0991:            }
0992:
0993:            // Check a switch string and raise an error
0994:            // if it starts with a '-' character. This
0995:            // runtime check is needed for a compiled
0996:            // switch command like [switch $str {...}]
0997:            // which has no option terminator "--".
0998:
0999:            public static void switchStringIsNotOption(Interp interp, String str)
1000:                    throws TclException {
1001:                if (str.startsWith("-")) {
1002:                    TclObject[] objv = new TclObject[1];
1003:                    objv[0] = TclString.newInstance("switch");
1004:                    throw new TclNumArgsException(interp, 1, objv,
1005:                            "?switches? string pattern body ... ?default body?");
1006:                }
1007:            }
1008:
1009:            // Raise exception when a variable could not
1010:            // be set during a catch command. This
1011:            // exception is defined here so that the
1012:            // constant string need not appear in
1013:            // every class file.
1014:
1015:            public static void catchVarErr(Interp interp) throws TclException {
1016:                throw new TclException(interp,
1017:                        "couldn't save command result in variable");
1018:            }
1019:
1020:            // Raise exception when a loop variable could
1021:            // not be set in a foreach command.
1022:
1023:            public static void foreachVarErr(Interp interp, String varname)
1024:                    throws TclException {
1025:                throw new TclException(interp, "couldn't set loop variable: \""
1026:                        + varname + "\"");
1027:            }
1028:
1029:            private static final boolean USE_EXPR_CACHE = true;
1030:
1031:            // Release an ExprValue that was returned by
1032:            // one of the exprGetValue methods.
1033:
1034:            public static void exprReleaseValue(Interp interp, ExprValue value) {
1035:                if (USE_EXPR_CACHE) {
1036:                    interp.expr.releaseExprValue(value);
1037:                }
1038:            }
1039:
1040:            // Return the ExprValue for the given int value.
1041:            // If the value was parsed from a String that
1042:            // differs from the parsed value of the integer,
1043:            // then it should be passed as the srep.
1044:
1045:            public static ExprValue exprGetValue(Interp interp, int ival,
1046:                    String srep) throws TclException {
1047:                if (USE_EXPR_CACHE) {
1048:                    ExprValue value = interp.expr.grabExprValue();
1049:                    value.setIntValue(ival, srep);
1050:                    return value;
1051:                } else {
1052:                    return new ExprValue(ival, srep);
1053:                }
1054:            }
1055:
1056:            // Return the expr value contained in the double
1057:
1058:            public static ExprValue exprGetValue(Interp interp, double dval,
1059:                    String srep) throws TclException {
1060:                if (USE_EXPR_CACHE) {
1061:                    ExprValue value = interp.expr.grabExprValue();
1062:                    value.setDoubleValue(dval, srep);
1063:                    return value;
1064:                } else {
1065:                    return new ExprValue(dval, srep);
1066:                }
1067:            }
1068:
1069:            // Return the expr value for the String
1070:
1071:            public static ExprValue exprGetValue(Interp interp, String srep)
1072:                    throws TclException {
1073:                if (USE_EXPR_CACHE) {
1074:                    ExprValue value = interp.expr.grabExprValue();
1075:                    value.setStringValue(srep);
1076:                    return value;
1077:                } else {
1078:                    return new ExprValue(srep);
1079:                }
1080:            }
1081:
1082:            // Return the expr value for the boolean, this
1083:            // boolean has no string rep and is represented
1084:            // by an integer type.
1085:
1086:            public static ExprValue exprGetValue(Interp interp, boolean bval)
1087:                    throws TclException {
1088:                if (USE_EXPR_CACHE) {
1089:                    ExprValue value = interp.expr.grabExprValue();
1090:                    value.setIntValue(bval);
1091:                    return value;
1092:                } else {
1093:                    return new ExprValue(bval);
1094:                }
1095:            }
1096:
1097:            // Return the expr value contained in the TclObject
1098:
1099:            public static ExprValue exprGetValue(Interp interp, TclObject tobj)
1100:                    throws TclException {
1101:                if (USE_EXPR_CACHE) {
1102:                    ExprValue value = interp.expr.grabExprValue();
1103:                    Expression.ExprParseObject(interp, tobj, value);
1104:                    return value;
1105:                } else {
1106:                    ExprValue value = new ExprValue(0, null);
1107:                    Expression.ExprParseObject(interp, tobj, value);
1108:                    return value;
1109:                }
1110:            }
1111:
1112:            // Init expr value with the value in the TclObject
1113:
1114:            public static void exprInitValue(final Interp interp,
1115:                    final ExprValue value, final TclObject tobj)
1116:                    throws TclException {
1117:                Expression.ExprParseObject(interp, tobj, value);
1118:            }
1119:
1120:            // Return an uninitialized ExprValue.
1121:
1122:            public static ExprValue exprGetValue(Interp interp) {
1123:                if (USE_EXPR_CACHE) {
1124:                    return interp.expr.grabExprValue();
1125:                } else {
1126:                    return new ExprValue(0, null);
1127:                }
1128:            }
1129:
1130:            // Return the int value inside a TclObject known
1131:            // to be of type integer. This method should
1132:            // only be used inside the expr layer. Testing
1133:            // indicates that this method executes 25%
1134:            // faster than TclInteger.get().
1135:
1136:            public static int exprGetKnownInt(final TclObject tobj) {
1137:                return tobj.ivalue;
1138:            }
1139:
1140:            // Return the double value inside a TclObject known
1141:            // to be of type double. This method should
1142:            // only be used inside the expr layer. Testing
1143:            // indicates that this method executes about
1144:            // 4x faster than TclDouble.get().
1145:
1146:            public static double exprGetKnownDouble(final TclObject tobj) {
1147:                return ((TclDouble) tobj.getInternalRep()).value;
1148:            }
1149:
1150:            // Evaluate a unary expr operator.
1151:
1152:            public static void exprUnaryOperator(final Interp interp, // current interp, can't be null.
1153:                    final int op, // One of the EXPR_OP_* values
1154:                    final ExprValue value) throws TclException {
1155:                Expression.evalUnaryOperator(interp, op, value);
1156:            }
1157:
1158:            // Evaluate a binary expr operator.
1159:
1160:            public static void exprBinaryOperator(final Interp interp, // current interp, can't be null.
1161:                    final int op, // One of the EXPR_OP_* values
1162:                    final ExprValue value, final ExprValue value2)
1163:                    throws TclException {
1164:                Expression.evalBinaryOperator(interp, op, value, value2);
1165:            }
1166:
1167:            // Evaluate a math function. This method will release
1168:            // the values ExprValue objects when finished. The
1169:            // values argument should be null where the math
1170:            // function takes no arguments.
1171:
1172:            public static void exprMathFunction(Interp interp, // current interp, can't be null.
1173:                    String funcName, // Name of math function
1174:                    ExprValue[] values, // Array of arguments, can be null
1175:                    ExprValue result) // Location to store result
1176:                    throws TclException {
1177:                interp.expr.evalMathFunction(interp, funcName, values, false,
1178:                        result);
1179:            }
1180:
1181:            // Set the interp result to the given expr value. This
1182:            // method is used only for a compiled version of the expr
1183:            // command.
1184:
1185:            public static void exprSetResult(Interp interp, ExprValue value)
1186:                    throws TclException {
1187:                switch (value.getType()) {
1188:                case ExprValue.INT:
1189:                    interp.setResult(value.getIntValue());
1190:                    break;
1191:                case ExprValue.DOUBLE:
1192:                    interp.setResult(value.getDoubleValue());
1193:                    break;
1194:                case ExprValue.STRING:
1195:                    interp.setResult(value.getStringValue());
1196:                    break;
1197:                default:
1198:                    throw new TclRuntimeError(
1199:                            "internal error: expression, unknown");
1200:                }
1201:                return;
1202:            }
1203:
1204:            // Determine if the given TclObject is equal to
1205:            // the empty string. This method implements an
1206:            // optimized version of an expr comparison
1207:            // like expr {$obj == ""} or expr {$obj != {}}.
1208:            // This method sets the value argument to
1209:            // an integer, either 0 or 1.
1210:
1211:            public static void exprEqualsEmptyString(ExprValue value, // Location for result value
1212:                    TclObject obj, // TclObject to compare to empty string
1213:                    final boolean negate) // Negate result if true
1214:                    throws TclException {
1215:                boolean isEmptyString;
1216:
1217:                if (obj.hasNoStringRep() && obj.isListType()) {
1218:                    // A pure Tcl list is equal to the empty string
1219:                    // when the list length is zero. This check
1220:                    // avoids the possibly slow generation of
1221:                    // a string rep from a pure TclList object.
1222:                    // Note that passing null as the Interp
1223:                    // argument is fine since we know this object
1224:                    // has the TclList internal rep already.
1225:                    isEmptyString = (TclList.getLength(null, obj) == 0);
1226:                } else {
1227:                    // TclObject already has a string rep, check if it is a
1228:                    // ref to the interned empty string or if the len is 0.
1229:                    String s = obj.toString();
1230:                    isEmptyString = (s == "" || s.length() == 0);
1231:                }
1232:                if (negate) {
1233:                    isEmptyString = !isEmptyString;
1234:                }
1235:                value.setIntValue(isEmptyString);
1236:            }
1237:
1238:            // Implement an optimized version of the
1239:            // int() math function used in an expr.
1240:            // This method will raise an error if
1241:            // the value is non-numeric, otherwise
1242:            // it will case a double type to an int.
1243:
1244:            public static void exprIntMathFunction(Interp interp,
1245:                    ExprValue value) throws TclException {
1246:                switch (value.getType()) {
1247:                case ExprValue.INT: {
1248:                    // No-op
1249:                    break;
1250:                }
1251:                case ExprValue.DOUBLE: {
1252:                    double d = value.getDoubleValue();
1253:                    if (((d < 0) && (d < ((double) TCL.INT_MIN)))
1254:                            || ((d > 0) && (d > ((double) TCL.INT_MAX)))) {
1255:                        Expression.IntegerTooLarge(interp);
1256:                    }
1257:                    value.setIntValue((int) d);
1258:                    break;
1259:                }
1260:                case ExprValue.STRING: {
1261:                    throw new TclException(interp,
1262:                            "argument to math function didn't have numeric value");
1263:                }
1264:                }
1265:            }
1266:
1267:            // Implement an optimized version of the
1268:            // double() math function used in an expr.
1269:            // This method will raise an error if
1270:            // the value is non-numeric, otherwise
1271:            // it will case an int type to a double.
1272:
1273:            public static void exprDoubleMathFunction(Interp interp,
1274:                    ExprValue value) throws TclException {
1275:                if (value.isStringType()) {
1276:                    throw new TclException(interp,
1277:                            "argument to math function didn't have numeric value");
1278:                } else if (value.isIntType()) {
1279:                    value.setDoubleValue((double) value.getIntValue());
1280:                }
1281:            }
1282:
1283:            // Evaluate a unary not operator. This method accepts an
1284:            // ExprValue value and returns the result in the ExprValue.
1285:            // This method is invoked when an ExprValue is known
1286:            // at compile time to be a double or a string.
1287:            // This method should not be invoked when the ExprValue
1288:            // is known to be of type int (or boolean).
1289:
1290:            public static void exprUnaryNotOperator(final Interp interp, // current interp, can't be null.
1291:                    final ExprValue value) // operand value
1292:                    throws TclException {
1293:                // Special case of int type should have been handled
1294:                // in inline code before this method is invoked.
1295:
1296:                if (value.isDoubleType()) {
1297:                    value.setIntValue(value.getDoubleValue() == 0.0);
1298:                } else {
1299:                    Expression.evalUnaryOperator(interp, TJC.EXPR_OP_UNARY_NOT,
1300:                            value);
1301:                }
1302:            }
1303:
1304:            // Evaluate a unary not operator. This method accepts a
1305:            // TclObject value and returns the result in an ExprValue.
1306:
1307:            public static void exprUnaryNotOperator(final Interp interp, // current interp, can't be null.
1308:                    final ExprValue value, // where to store result of operator
1309:                    final TclObject tobj) // contains the value as a TclObject
1310:                    throws TclException {
1311:                // Special case of int type should have been handled
1312:                // in inline code before this method is invoked.
1313:
1314:                if (tobj.isDoubleType()) {
1315:                    value.setIntValue(TJC.exprGetKnownDouble(tobj) == 0.0);
1316:                    return;
1317:                }
1318:
1319:                Expression.ExprParseString(interp, tobj, value);
1320:                if (value.isIntType()) {
1321:                    // ExprValue is known to be an int, so
1322:                    // invoke specific method that does not
1323:                    // change the type.
1324:
1325:                    value.optIntUnaryNot();
1326:                } else if (value.isDoubleType()) {
1327:                    value.setIntValue(value.getDoubleValue() == 0.0);
1328:                } else {
1329:                    Expression.evalUnaryOperator(interp, EXPR_OP_UNARY_NOT,
1330:                            value);
1331:                }
1332:            }
1333:
1334:            // These methods are used when inlining a
1335:            // unary not operator. In the case where
1336:            // the operand is known to be of type int,
1337:            // these methods are used to inline the op.
1338:            // This impl executes about 4x faster than
1339:            // a exprUnaryNotOperator() that checks
1340:            // for a TclObject that contains an int.
1341:
1342:            public static void exprUnaryNotOperatorKnownInt(
1343:                    final ExprValue value, // where to store result of operator
1344:                    final TclObject tobj) // contains the value as a TclObject
1345:            {
1346:                // Invoking ExprValue.setInt(boolean) here is the most
1347:                // efficient implementation. Invoking TJC.exprGetKnownInt()
1348:                // and inlining the branching logic in calling code is slower.
1349:
1350:                value.setIntValue(tobj.ivalue == 0);
1351:            }
1352:
1353:            public static int exprUnaryNotOperatorKnownInt(final TclObject tobj) // contains the value as a TclObject
1354:            {
1355:                return (tobj.ivalue == 0) ? 1 : 0;
1356:            }
1357:
1358:            public static boolean exprUnaryNotOperatorKnownIntAsBoolean(
1359:                    final TclObject tobj) // contains the value as a TclObject
1360:            {
1361:                return (tobj.ivalue == 0);
1362:            }
1363:
1364:            // Implements inlined global command, this method
1365:            // will create a local var linked to a global var.
1366:            // A compiled global command accepts a varTail
1367:            // that is either a scalar or an array name.
1368:            // If the localIndex argument is not -1, it
1369:            // indicates the compiledLocal slot to use.
1370:
1371:            public static final void makeGlobalLinkVar(Interp interp,
1372:                    String varName, // Fully qualified name of global variable.
1373:                    String varTail, // Variable name without namespace qualifiers.
1374:                    int localIndex) // Index into compiledLocals array
1375:                    throws TclException {
1376:                // Link to the variable "varName" in the global :: namespace.
1377:                // A local link var named varTail is defined.
1378:
1379:                Var.makeUpvar(interp, null, varName, null, TCL.GLOBAL_ONLY,
1380:                        varTail, 0, localIndex);
1381:            }
1382:
1383:            // Implements inlined lindex command for non-constant integer
1384:            // index values. This implementation is used only with lindex
1385:            // commands that have 3 arguments. If the index argument
1386:            // is already a TclInteger type then an optimized lindex
1387:            // impl is used. The interp result is always set by this
1388:            // method.
1389:
1390:            public static final void lindexNonconst(final Interp interp,
1391:                    final TclObject listObj, // List value
1392:                    final TclObject indexValue) // List index to be resolved.
1393:                    throws TclException {
1394:                // Optimized check for integer indexValue argument.
1395:                // This is the most common use case:
1396:                // set obj [lindex $list $i]
1397:
1398:                if (indexValue.isIntType()) {
1399:                    TclObject result = TclList.index(interp, listObj,
1400:                            indexValue.ivalue);
1401:                    if (result == null) {
1402:                        interp.resetResult();
1403:                    } else {
1404:                        interp.setResult(result);
1405:                    }
1406:                    return;
1407:                } else {
1408:                    // Invoke the static lindex command impl.
1409:
1410:                    TclObject[] objv = TJC.grabObjv(interp, 3);
1411:                    try {
1412:                        //objv[0] = null;
1413:
1414:                        objv[1] = listObj;
1415:
1416:                        objv[2] = indexValue;
1417:                        indexValue.preserve();
1418:
1419:                        TclObject elem = LindexCmd.TclLindexList(interp,
1420:                                listObj, objv, 2);
1421:                        interp.setResult(elem);
1422:                        elem.release();
1423:                    } finally {
1424:                        // Caller should preserve() and release() listObj
1425:                        objv[2].release();
1426:                        TJC.releaseObjv(interp, objv, 3);
1427:                    }
1428:                    return;
1429:                }
1430:            }
1431:
1432:            // Implements inlined lappend command that appends 1 or more
1433:            // TclObject values to a variable. This implementation
1434:            // makes use of runtime support found in the LappendCmd class.
1435:            // The new variable value after the lappend operation is returned.
1436:
1437:            public static final TclObject lappendVar(Interp interp,
1438:                    String varName, // Name of variable
1439:                    String key, // Array element key (can be null)
1440:                    TclObject[] values) // Array of TclObject values to append
1441:                    throws TclException {
1442:                if (key == null) {
1443:                    return LappendCmd.lappendVar(interp, varName, values, 0);
1444:                } else {
1445:                    // LappendCmd expects a single var name in a String,
1446:                    // so create one for this uncommon case.
1447:                    String avName = varName + "(" + key + ")";
1448:                    return LappendCmd.lappendVar(interp, avName, values, 0);
1449:                }
1450:            }
1451:
1452:            // Implements inlined append command that appends 1 or more
1453:            // TclObject values to a variable. This implementation
1454:            // duplicates the logic found in AppendCmd. The new
1455:            // variable value after the lappend operation is returned.
1456:
1457:            public static final TclObject appendVar(Interp interp,
1458:                    String varName, // Name of variable
1459:                    String key, // Array element key (can be null)
1460:                    TclObject[] values) // Array of TclObject values to append
1461:                    throws TclException {
1462:                TclObject varValue = null;
1463:                final int len = values.length;
1464:                if (key != null) {
1465:                    varName = varName + "(" + key + ")";
1466:                }
1467:
1468:                for (int i = 0; i < len; i++) {
1469:                    varValue = interp.setVar(varName, values[i],
1470:                            TCL.APPEND_VALUE);
1471:                }
1472:
1473:                if (varValue == null) {
1474:                    // Return empty result object if null
1475:                    varValue = interp.checkCommonString(null);
1476:                }
1477:
1478:                return varValue;
1479:            }
1480:
1481:            // Implements inlined string index command. This
1482:            // implementation duplicates the logic found
1483:            // in StringCmd.java. The new value is returned.
1484:            // If the index is out of range the null result
1485:            // will be returned.
1486:
1487:            public static final TclObject stringIndex(final Interp interp,
1488:                    final String str, // string
1489:                    final TclObject indObj) // index into string
1490:                    throws TclException {
1491:                final int len = str.length();
1492:                int i;
1493:
1494:                if (indObj.isIntType()) {
1495:                    i = indObj.ivalue; // Inline TclInteger.get()
1496:                } else {
1497:                    i = Util.getIntForIndex(interp, indObj, len - 1);
1498:                }
1499:
1500:                if ((i >= 0) && (i < len)) {
1501:                    TclObject obj = interp.checkCommonCharacter(str.charAt(i));
1502:                    if (obj == null) {
1503:                        obj = TclString.newInstance(str.substring(i, i + 1));
1504:                    }
1505:                    return obj;
1506:                } else {
1507:                    return interp.checkCommonString(null);
1508:                }
1509:            }
1510:
1511:            // Implements inlined string range command. This
1512:            // implementation duplicates the logic found
1513:            // in StringCmd.java. The new value is returned.
1514:            // This method assumes that the firstObj TclObject
1515:            // was preserved() before this method is invoked.
1516:            // This method will always release() the firstObj.
1517:
1518:            public static final TclObject stringRange(final Interp interp,
1519:                    final String str, // string
1520:                    final TclObject firstObj, // first index (ref count incremented)
1521:                    final TclObject lastObj) // last index
1522:                    throws TclException {
1523:                final int len = str.length();
1524:                int first, last;
1525:
1526:                try {
1527:                    if (firstObj.isIntType()) {
1528:                        first = firstObj.ivalue; // Inline TclInteger.get()
1529:                    } else {
1530:                        first = Util.getIntForIndex(interp, firstObj, len - 1);
1531:                    }
1532:                    if (first < 0) {
1533:                        first = 0;
1534:                    }
1535:
1536:                    if (lastObj.isIntType()) {
1537:                        last = lastObj.ivalue; // Inline TclInteger.get()
1538:                    } else {
1539:                        last = Util.getIntForIndex(interp, lastObj, len - 1);
1540:                    }
1541:                    if (last >= len) {
1542:                        last = len - 1;
1543:                    }
1544:                } finally {
1545:                    // Release firstObj after lastObj has been queried.
1546:                    // There could only be a ref count problem if firstObj
1547:                    // was released before lastObj and lastObj was a list
1548:                    // element of firstObj and lastObj had a ref count of 1.
1549:
1550:                    firstObj.release();
1551:                }
1552:
1553:                if (first > last) {
1554:                    return interp.checkCommonString(null);
1555:                } else {
1556:                    String substr = str.substring(first, last + 1);
1557:                    return TclString.newInstance(substr);
1558:                }
1559:            }
1560:
1561:            // Implements inlined "string first" command, this
1562:            // duplicates the logic found in StringCmd.java.
1563:            // A TclObject that holds the new value is
1564:            // returned.
1565:
1566:            public static final TclObject stringFirst(Interp interp,
1567:                    String substr, // substring to search for
1568:                    String str, // string to search in
1569:                    TclObject startObj) // start index (null if start is 0)
1570:                    throws TclException {
1571:                int substrLen = substr.length();
1572:                int strLen = str.length();
1573:                int index;
1574:
1575:                int start;
1576:
1577:                if (startObj == null) {
1578:                    start = 0;
1579:                } else {
1580:                    // If a startIndex is specified, we will need to fast
1581:                    // forward to that point in the string before we think
1582:                    // about a match.
1583:
1584:                    start = Util.getIntForIndex(interp, startObj, strLen - 1);
1585:                    if (start >= strLen) {
1586:                        return interp.checkCommonInteger(-1);
1587:                    }
1588:                }
1589:
1590:                if (substrLen == 0) {
1591:                    index = -1;
1592:                } else if (substrLen == 1) {
1593:                    char c = substr.charAt(0);
1594:                    index = str.indexOf(c, start);
1595:                } else {
1596:                    index = str.indexOf(substr, start);
1597:                }
1598:                return interp.checkCommonInteger(index);
1599:            }
1600:
1601:            // Implements inlined "string last" command, this
1602:            // duplicates the logic found in StringCmd.java.
1603:            // A TclObject that holds the new value is
1604:            // returned.
1605:
1606:            public static final TclObject stringLast(Interp interp,
1607:                    String substr, // substring to search for
1608:                    String str, // string to search in
1609:                    TclObject lastObj) // last index (null if last is 0)
1610:                    throws TclException {
1611:                int substrLen = substr.length();
1612:                int strLen = str.length();
1613:                int index;
1614:                int last;
1615:
1616:                if (lastObj == null) {
1617:                    last = 0;
1618:                } else {
1619:                    last = Util.getIntForIndex(interp, lastObj, strLen - 1);
1620:                    if (last < 0) {
1621:                        return interp.checkCommonInteger(-1);
1622:                    } else if (last < strLen) {
1623:                        str = str.substring(0, last + 1);
1624:                    }
1625:                }
1626:
1627:                if (substrLen == 0) {
1628:                    index = -1;
1629:                } else if (substrLen == 1) {
1630:                    char c = substr.charAt(0);
1631:                    index = str.lastIndexOf(c);
1632:                } else {
1633:                    index = str.lastIndexOf(substr);
1634:                }
1635:                return interp.checkCommonInteger(index);
1636:            }
1637:
1638:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.