0001: /*
0002: * PnutsInterpreter.java
0003: *
0004: * Copyright (c) 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
0005: *
0006: * See the file "LICENSE.txt" for information on usage and redistribution
0007: * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
0008: */
0009: package pnuts.lang;
0010:
0011: import java.io.PrintWriter;
0012: import java.lang.reflect.Array;
0013: import java.util.Enumeration;
0014: import java.util.Map;
0015: import java.util.HashMap;
0016: import java.util.Set;
0017: import java.util.HashSet;
0018: import java.util.List;
0019: import java.util.Iterator;
0020: import java.util.ArrayList;
0021:
0022: import org.pnuts.lang.ConstraintsTransformer;
0023: import org.pnuts.lang.GeneratorHelper;
0024: import org.pnuts.util.Cell;
0025:
0026: import pnuts.compiler.Compiler;
0027: import pnuts.compiler.ClassGenerator;
0028:
0029: /**
0030: * The pure interpreter
0031: */
0032: public class PnutsInterpreter extends Runtime implements Visitor {
0033:
0034: private final static Integer one = new Integer(1);
0035:
0036: private final static Object GENERATOR = new Object();
0037:
0038: private final static Object FUNCTION = new Object();
0039:
0040: static PnutsInterpreter instance = new PnutsInterpreter();
0041: static Compiler compiler = new Compiler();
0042:
0043: static PnutsInterpreter getInstance() {
0044: return instance;
0045: }
0046:
0047: final static int CODE = 0;
0048: final static int VALUE = 1;
0049: final static int BROKEN = 0;
0050: final static int CONT = 1;
0051: final static int PASSED = 2;
0052:
0053: public Object start(SimpleNode node, Context context) {
0054: if (node.jjtGetNumChildren() > 0) {
0055: if (context.stackFrame == null) {
0056: context.stackFrame = new StackFrame();
0057: }
0058: try {
0059: return accept(node, 0, context);
0060: } catch (Throwable t) {
0061: checkException(context, t);
0062: }
0063: }
0064: return null;
0065: }
0066:
0067: public Object startSet(SimpleNode node, Context context) {
0068: if (context.stackFrame == null) {
0069: context.stackFrame = new StackFrame();
0070: }
0071: int n = node.jjtGetNumChildren();
0072: Object ret = null;
0073: try {
0074: for (int i = 0; i < n; i++) {
0075: ret = accept(node, i, context);
0076: }
0077: } catch (Throwable t) {
0078: checkException(context, t);
0079: } finally {
0080: if (context.evalFrameStack == null) {
0081: PrintWriter pw = context.getWriter();
0082: if (pw != null) {
0083: pw.flush();
0084: }
0085: } else {
0086: Cell cell = context.evalFrameStack;
0087: if (cell != null) {
0088: context.evalFrameStack = cell.next;
0089: context.stackFrame = (StackFrame) cell.object;
0090: }
0091: }
0092: }
0093: return ret;
0094: }
0095:
0096: public Object expressionList(SimpleNode node, Context context) {
0097: Object ret = null;
0098: int n = node.jjtGetNumChildren();
0099: for (int i = 0; i < n; i++) {
0100: ret = accept(node, i, context);
0101: }
0102: return ret;
0103: }
0104:
0105: public Object global(SimpleNode node, Context context) {
0106: String symbol = node.str;
0107: Package pkg = Package.find("", context);
0108: if (pkg != null) {
0109: Value val = pkg.lookup(symbol, context);
0110: if (val != null) {
0111: return val.get();
0112: }
0113: }
0114: return context.undefined(symbol);
0115: }
0116:
0117: public Object idNode(SimpleNode node, Context context) {
0118: return context.getValue(node.str);
0119: }
0120:
0121: public Object className(SimpleNode node, Context context) {
0122: return resolveClassNameNode(node, context);
0123: }
0124:
0125: public Object arrayType(SimpleNode node, Context context) {
0126: SimpleNode n = node;
0127: int count = 0;
0128: while (n != null
0129: && n.id == PnutsParserTreeConstants.JJTARRAYTYPE) {
0130: count++;
0131: n = n.jjtGetChild(0);
0132: }
0133: if (n != null && n.id == PnutsParserTreeConstants.JJTINDEXNODE) {
0134: Class type;
0135: Object[] idx = parseIndex(n);
0136: SimpleNode idx0 = (SimpleNode) idx[0];
0137: Object tgt = idx0.accept(this , context);
0138: if (tgt instanceof Class) {
0139: type = Runtime.arrayType((Class) tgt, count);
0140: } else {
0141: throw new PnutsException("classOrArray.expected",
0142: new Object[] { Pnuts.format(tgt) }, context);
0143: }
0144: Object[] dim = (Object[]) idx[1];
0145: int[] idim = new int[dim.length];
0146: for (int i = 0; i < dim.length; i++) {
0147: Object o = ((SimpleNode) dim[i]).accept(this , context);
0148: if (o instanceof Number) {
0149: idim[i] = ((Number) o).intValue();
0150: } else {
0151: throw new PnutsException("number.expected",
0152: new Object[] { Pnuts.format(o) }, context);
0153: }
0154: }
0155: return Array.newInstance(type, idim);
0156: } else if (node.jjtGetParent().id != PnutsParserTreeConstants.JJTNEW) {
0157: Object tgt = n.accept(this , context);
0158: if (tgt instanceof Class) {
0159: return Runtime.arrayType((Class) tgt, count);
0160: } else {
0161: throw new PnutsException("classOrArray.expected",
0162: new Object[] { Pnuts.format(tgt) }, context);
0163: }
0164: } else {
0165: throw new IllegalArgumentException();
0166: }
0167: }
0168:
0169: public Object[] _listElements(SimpleNode node, Context context) {
0170: int n = node.jjtGetNumChildren();
0171: Object array[] = new Object[n];
0172:
0173: for (int i = 0; i < n; i++) {
0174: array[i] = accept(node, i, context);
0175: }
0176: return array;
0177: }
0178:
0179: public Object listElements(SimpleNode node, Context context) {
0180: if ("{".equals(node.str)) {
0181: List list = context.config.createList();
0182: int n = node.jjtGetNumChildren();
0183: for (int i = 0; i < n; i++) {
0184: list.add(accept(node, i, context));
0185: }
0186: return list;
0187: } else {
0188: return context.config.makeArray(
0189: _listElements(node, context), context);
0190: }
0191: }
0192:
0193: public Object mapNode(SimpleNode node, Context context) {
0194: int n = node.jjtGetNumChildren();
0195: Map map = context.config.createMap(n, context);
0196: for (int i = 0; i < n; i++) {
0197: SimpleNode c = node.jjtGetChild(i);
0198: map.put(accept(c, 0, context), accept(c, 1, context));
0199: }
0200: return map;
0201: }
0202:
0203: public Object castExpression(SimpleNode node, Context context) {
0204: SimpleNode typeNode = node.jjtGetChild(0);
0205: Class type = resolveTypeNode(typeNode, context);
0206: Object obj = accept(node, 1, context);
0207: return Runtime.cast(context, type, obj, true);
0208: }
0209:
0210: public Object classNode(SimpleNode node, Context context) {
0211: SimpleNode c = node.jjtGetChild(0);
0212: String className = null;
0213: if (c.id == PnutsParserTreeConstants.JJTCLASSNAME) {
0214: StringBuffer sbuf = new StringBuffer();
0215: sbuf.append(c.children[0].str);
0216: int n = c.jjtGetNumChildren();
0217: for (int i = 1; i < n; i++) {
0218: SimpleNode ch = c.children[i];
0219: sbuf.append('.');
0220: sbuf.append(ch.str);
0221: }
0222: className = sbuf.toString();
0223: } else {
0224: className = (String) c.accept(this , context);
0225: }
0226: try {
0227: return Pnuts.loadClass(className, context);
0228: } catch (ClassNotFoundException e) {
0229: throw new PnutsException(e, context);
0230: }
0231: }
0232:
0233: Object buildSubclassInstance(SimpleNode node, Context context) {
0234: return compiler.buildSubclassInstance(node, context);
0235: }
0236:
0237: public Object newNode(SimpleNode node, Context context) {
0238: int n = node.jjtGetNumChildren();
0239: SimpleNode n0 = node.jjtGetChild(0);
0240: if (n == 3
0241: && node.jjtGetChild(2).id == PnutsParserTreeConstants.JJTCLASSDEFBODY) { // subclass
0242: return buildSubclassInstance(node, context);
0243:
0244: } else if (n0.id == PnutsParserTreeConstants.JJTINDEXNODE) {
0245: Object[] idx = parseIndex(n0);
0246: SimpleNode c = (SimpleNode) idx[0];
0247: Object[] dim = (Object[]) idx[1];
0248: Class cls = resolveClassNameNode(c, context);
0249: return newArray(cls, dim, context);
0250:
0251: } else if (n0.id == PnutsParserTreeConstants.JJTARRAYTYPE) {
0252: return arrayType(n0, context);
0253:
0254: } else if (n0.id == PnutsParserTreeConstants.JJTARRAYNODE) {
0255: Class type = (Class) accept(n0, 0, context);
0256: Object obj = _listElements(n0.jjtGetChild(1), context);
0257: return Runtime.cast(context, type, obj, true);
0258:
0259: } else { // instantiation
0260: SimpleNode nameNode = node.jjtGetChild(0);
0261: Class cls = resolveClassNameNode(nameNode, context);
0262: Object[] arg = _listElements(node.jjtGetChild(1), context);
0263: return Runtime.callConstructor(context, cls, arg, null);
0264: }
0265: }
0266:
0267: public Object classDef(SimpleNode node, Context context) {
0268: return compiler.defineClass(node, context);
0269: }
0270:
0271: public Object methodDef(SimpleNode node, Context context) {
0272: return null;
0273: }
0274:
0275: public Object classDefBody(SimpleNode node, Context context) {
0276: return null;
0277: }
0278:
0279: public Object classScript(SimpleNode node, Context context) {
0280: return null;
0281: }
0282:
0283: public Object packageNode(SimpleNode node, Context context) {
0284: int n = node.jjtGetNumChildren();
0285: if (n == 0) {
0286: if ("(".equals(node.str)) {
0287: return PnutsFunction.PACKAGE.call(NO_PARAM, context);
0288: } else {
0289: return PnutsFunction.PACKAGE;
0290: }
0291: } else {
0292: SimpleNode c = node.jjtGetChild(0);
0293: if (n == 1 && c.id != PnutsParserTreeConstants.JJTPACKAGE) { // package("...")
0294: return PnutsFunction.PACKAGE.call(new Object[] { c
0295: .accept(this , context) }, context);
0296: } else {
0297: StringBuffer sbuf = new StringBuffer();
0298: sbuf.append(node.jjtGetChild(0).str);
0299: for (int i = 1; i < n; i++) {
0300: sbuf.append('.');
0301: sbuf.append(node.jjtGetChild(i).str);
0302: }
0303: return PnutsFunction.PACKAGE.call(new Object[] { sbuf
0304: .toString() }, context);
0305: }
0306: }
0307: }
0308:
0309: public Object importNode(SimpleNode node, Context context) {
0310: String t2 = node.str;
0311: int n = node.jjtGetNumChildren();
0312: if (n == 0) {
0313: if ("*".equals(t2)) { // import *
0314: context.addPackageToImport("");
0315: return null;
0316: } else if ("(".equals(t2)) {
0317: return context.importEnv.list();
0318: } else {
0319: return PnutsFunction.IMPORT;
0320: }
0321: }
0322: if (n == 1
0323: && node.children[0].id != PnutsParserTreeConstants.JJTPACKAGE) { // import(...)
0324: String s = (String) node.children[0].accept(this , context);
0325: if (s == null) {
0326: context.importEnv = new ImportEnv();
0327: } else if (!s.endsWith("*")) {
0328: context.addClassToImport(s);
0329: } else {
0330: int idx = s.lastIndexOf('.');
0331: if (idx > 0) {
0332: context.addPackageToImport(s.substring(0, idx));
0333: } else {
0334: context.addPackageToImport("");
0335: }
0336: }
0337: return null;
0338: }
0339: StringBuffer sbuf = new StringBuffer();
0340: sbuf.append(node.children[0].str);
0341: for (int i = 1; i < n; i++) {
0342: sbuf.append('.');
0343: sbuf.append(node.children[i].str);
0344: }
0345: String arg = sbuf.toString();
0346: if (node.info != null) { // static import
0347: context.addStaticMembers(arg, t2 != null);
0348: } else {
0349: if (t2 == null) {
0350: context.addClassToImport(arg);
0351: } else {
0352: context.addPackageToImport(arg);
0353: }
0354: }
0355: return null;
0356: }
0357:
0358: public Object rangeNode(SimpleNode node, Context context) {
0359: Object target = accept(node, 0, context);
0360: Object idx1 = accept(node, 1, context);
0361: Object idx2 = null;
0362: if (node.jjtGetNumChildren() >= 3) {
0363: idx2 = accept(node, 2, context);
0364: }
0365: return Runtime.getRange(target, idx1, idx2, context);
0366: }
0367:
0368: /**
0369: * @return [base_component_node, [idx_node_0, idx_node_1, ...]]
0370: */
0371: static Object[] parseIndex(SimpleNode node) {
0372: SimpleNode c0 = node.jjtGetChild(0);
0373: SimpleNode c1 = node.jjtGetChild(1);
0374: if (c0.id != PnutsParserTreeConstants.JJTINDEXNODE) {
0375: return new Object[] { c0, new Object[] { c1 } };
0376: } else {
0377: Object[] r = parseIndex(c0);
0378: Object[] d = (Object[]) r[1];
0379: Object[] a = new Object[d.length + 1];
0380: System.arraycopy(d, 0, a, 0, d.length);
0381: a[d.length] = c1;
0382: return new Object[] { r[0], a };
0383: }
0384: }
0385:
0386: static void convertIndexNode(SimpleNode node) {
0387: SimpleNode n0 = node.jjtGetChild(0);
0388: SimpleNode n1 = node.jjtGetChild(1);
0389: if (ConstraintsTransformer.isPredicate(n1)) {
0390: SimpleNode n = ConstraintsTransformer.buildFunc(n1);
0391: node.jjtAddChild(n, 1);
0392: n.jjtSetParent(node);
0393: }
0394: if (n0.id == PnutsParserTreeConstants.JJTINDEXNODE) {
0395: convertIndexNode(n0);
0396: }
0397: }
0398:
0399: public Object indexNode(SimpleNode node, Context context) {
0400: synchronized (node) {
0401: if (node.getAttribute("index") == null) {
0402: node.setAttribute("index", Boolean.TRUE);
0403: convertIndexNode(node);
0404: }
0405: }
0406: Object[] idx = parseIndex(node);
0407: SimpleNode c = (SimpleNode) idx[0];
0408: Object[] dim = (Object[]) idx[1];
0409: Object target = c.accept(this , context);
0410: if (target instanceof Class) {
0411: return newArray((Class) target, dim, context);
0412: } else {
0413: for (int i = 0; i < dim.length; i++) {
0414: target = Runtime.getElement(target,
0415: ((SimpleNode) dim[i]).accept(this , context),
0416: context);
0417: }
0418: return target;
0419: }
0420: }
0421:
0422: Object newArray(Class cls, Object[] dim, Context context) {
0423: int[] sizes = new int[dim.length];
0424: for (int i = 0; i < dim.length; i++) {
0425: sizes[i] = ((Number) ((SimpleNode) dim[i]).accept(this ,
0426: context)).intValue();
0427: }
0428: return Array.newInstance(cls, sizes);
0429: }
0430:
0431: public Object methodNode(SimpleNode node, Context context) {
0432: Object target = accept(node, 0, context);
0433: Object[] arg = _listElements(node.jjtGetChild(1), context);
0434:
0435: SimpleNode argNode = node.children[1];
0436: Class types[] = null;
0437: for (int i = 0; i < arg.length; i++) {
0438: SimpleNode n = argNode.children[i];
0439: if (n.id == PnutsParserTreeConstants.JJTCASTEXPRESSION) {
0440: if (types == null) {
0441: types = new Class[arg.length];
0442: }
0443: types[i] = resolveType(n.jjtGetChild(0), context);
0444: }
0445: }
0446:
0447: if (target == null) {
0448: PnutsException pe = new PnutsException(
0449: new NullPointerException(), context);
0450: pe.line = node.beginLine;
0451: throw pe;
0452: }
0453: return Runtime.callMethod(context, target.getClass(), node.str,
0454: arg, types, target);
0455: }
0456:
0457: public Object staticMethodNode(SimpleNode node, Context context) {
0458: SimpleNode c1 = node.children[0];
0459: String pkgName = getPackageName(c1);
0460:
0461: SimpleNode argNode = node.children[1];
0462: Class types[] = null;
0463: Object[] arg = null;
0464:
0465: Package pkg = Package.find(pkgName, context);
0466: if (pkg != null) {
0467: Object fun = pkg.get(node.str, context);
0468:
0469: if (fun instanceof PnutsFunction) {
0470: arg = _listElements(node.jjtGetChild(1), context);
0471: PnutsFunction ft = (PnutsFunction) fun;
0472: return ft.exec(arg, context);
0473: } else if (fun instanceof Class) {
0474: arg = _listElements(node.jjtGetChild(1), context);
0475: for (int i = 0; i < arg.length; i++) {
0476: SimpleNode n = argNode.children[i];
0477: if (n.id == PnutsParserTreeConstants.JJTCASTEXPRESSION) {
0478: if (types == null) {
0479: types = new Class[arg.length];
0480: }
0481: types[i] = resolveType(n.jjtGetChild(0),
0482: context);
0483: }
0484: }
0485: return Runtime.callConstructor(context, (Class) fun,
0486: arg, types);
0487: } else {
0488: throw new PnutsException(
0489: "illegal.staticCall",
0490: new Object[] {
0491: pkgName,
0492: node.str,
0493: new Integer(argNode.jjtGetNumChildren()) },
0494: context);
0495: }
0496: }
0497: Object target = accept(node, 0, context);
0498: arg = _listElements(node.jjtGetChild(1), context);
0499: if (target instanceof Class) {
0500: for (int i = 0; i < arg.length; i++) {
0501: SimpleNode n = argNode.children[i];
0502: if (n.id == PnutsParserTreeConstants.JJTCASTEXPRESSION) {
0503: if (types == null) {
0504: types = new Class[arg.length];
0505: }
0506: types[i] = resolveType(n.jjtGetChild(0), context);
0507: }
0508: }
0509: return Runtime.callMethod(context, (Class) target,
0510: node.str, arg, types, null);
0511: } else {
0512: throw new PnutsException("illegal.staticCall",
0513: new Object[] { pkgName, node.str,
0514: new Integer(arg.length) }, context);
0515: }
0516: }
0517:
0518: public Object memberNode(SimpleNode node, Context context) {
0519: Object target = accept(node, 0, context);
0520:
0521: if (target == null) {
0522: throw new PnutsException(new NullPointerException(),
0523: context);
0524: } else if (Runtime.isArray(target) && node.str.equals("length")) {
0525: return new Integer(Runtime.getArrayLength(target));
0526: }
0527: if (node.info != null) { /* experimental BIND feature */
0528: Object[] info = (Object[]) node.info;
0529: Object obj = info[0];
0530: SimpleNode c = (SimpleNode) info[1];
0531: SimpleNode c0 = c.jjtGetChild(0);
0532: Map table = (Map) info[2];
0533: watchProperty(table, obj, c.str, target, node.str,
0534: (Callable) toFunctionNode(c0).accept(this , context));
0535: if (c0 == node) {
0536: watchProperty(table, target, node.str, obj, c.str, null);
0537: }
0538: node.info = null;
0539: }
0540: return Runtime.getField(context, target, node.str);
0541: }
0542:
0543: static String getPackageName(SimpleNode node) {
0544: if (node.jjtGetNumChildren() > 0) {
0545: SimpleNode c1 = node.children[0];
0546: return getPackageName(c1) + "::" + node.str;
0547: } else {
0548: return node.str;
0549: }
0550: }
0551:
0552: public Object staticMemberNode(SimpleNode node, Context context) {
0553:
0554: SimpleNode c1 = node.children[0];
0555: String pkgName = getPackageName(c1);
0556:
0557: Package pkg = Package.find(pkgName, context);
0558: if (pkg != null) {
0559: Value v = pkg.lookup(node.str, context);
0560: if (v != null) {
0561: return v.get();
0562: } else {
0563: return context.undefined(node.str);
0564: }
0565: }
0566: Object target = c1.accept(this , context);
0567: if (target instanceof Class) {
0568: return Runtime.getStaticField(context, (Class) target,
0569: node.str);
0570: } else {
0571: throw new PnutsException("packageOrClass.expected",
0572: new Object[] { Pnuts.format(target) }, context);
0573: }
0574: }
0575:
0576: public Object applicationNode(SimpleNode node, Context context) {
0577:
0578: Object target = accept(node, 0, context);
0579: Object[] arg = _listElements(node.jjtGetChild(1), context);
0580:
0581: SimpleNode argNode = node.children[1];
0582: Class types[] = null;
0583: for (int i = 0; i < arg.length; i++) {
0584: SimpleNode n = argNode.children[i];
0585: if (n.id == PnutsParserTreeConstants.JJTCASTEXPRESSION) {
0586: if (types == null) {
0587: types = new Class[arg.length];
0588: }
0589: types[i] = resolveType(n.jjtGetChild(0), context);
0590: }
0591: }
0592: return Runtime.call(context, target, arg, types,
0593: node.beginLine, node.beginColumn);
0594: }
0595:
0596: // node.info => [int[] unitOffset]
0597:
0598: public Object integerNode(SimpleNode node, Context context) {
0599: if (node.value != null) {
0600: return node.value;
0601: }
0602: String str = node.str;
0603: Object[] a = (Object[]) node.info;
0604: int[] off = (int[]) a[1];
0605: Number n = (Number) a[0];
0606: if (off != null) {
0607: int offset = off[0];
0608: return Runtime.quantity(n, str.substring(0, offset), str
0609: .substring(offset), context);
0610: } else {
0611: node.value = n;
0612: return n;
0613: }
0614: }
0615:
0616: public Object floatingNode(SimpleNode node, Context context) {
0617: if (node.value != null) {
0618: return node.value;
0619: }
0620: String str = node.str;
0621: Object[] p = (Object[]) node.info;
0622: Number n = (Number) p[0];
0623: if (p[1] != null) {
0624: int offset = ((int[]) p[1])[0];
0625: return Runtime.quantity(n, str.substring(0, offset), str
0626: .substring(offset), context);
0627: } else {
0628: node.value = n;
0629: return n;
0630: }
0631: }
0632:
0633: public Object characterNode(SimpleNode node, Context context) {
0634: return node.info;
0635: }
0636:
0637: public Object stringNode(SimpleNode node, Context context) {
0638: String str = node.str;
0639: if (str != null) {
0640: return str;
0641: } else {
0642: int n = node.jjtGetNumChildren();
0643: StringBuffer sbuf = new StringBuffer();
0644: for (int i = 0; i < n; i++) {
0645: SimpleNode c = node.jjtGetChild(i);
0646: if (c.id == PnutsParserTreeConstants.JJTSTRINGNODE) {
0647: sbuf.append(c.str);
0648: } else {
0649: sbuf
0650: .append(String.valueOf(c.accept(this ,
0651: context)));
0652: }
0653: }
0654: return sbuf.toString();
0655: }
0656: }
0657:
0658: public Object trueNode(SimpleNode node, Context context) {
0659: return Boolean.TRUE;
0660: }
0661:
0662: public Object falseNode(SimpleNode node, Context context) {
0663: return Boolean.FALSE;
0664: }
0665:
0666: public Object nullNode(SimpleNode node, Context context) {
0667: return null;
0668: }
0669:
0670: private void doAssign(String symbol, Object expr, Context context) {
0671: if (context.inGeneratorClosure) {
0672: if (context.frame.outer != null) {
0673: context.setValue(symbol, expr);
0674: } else {
0675: context.getCurrentPackage().set(symbol, expr);
0676: }
0677: } else {
0678: context.setValue(symbol, expr);
0679: }
0680: }
0681:
0682: private Object doAssign(SimpleNode node, Object expr,
0683: Context context, BinaryOperator op) {
0684: if (node.id == PnutsParserTreeConstants.JJTIDNODE) {
0685: if (op != null) {
0686: expr = op.operateOn(context.getValue(node.str), expr);
0687: }
0688: doAssign(node.str, expr, context);
0689: return expr;
0690: } else if (node.id == PnutsParserTreeConstants.JJTGLOBAL) {
0691: Package pkg = Package.getPackage("", context);
0692: if (op != null) {
0693: expr = op.operateOn(pkg.get(node.str, context), expr);
0694: }
0695: pkg.set(node.str, expr, context);
0696: return expr;
0697:
0698: } else if (node.id == PnutsParserTreeConstants.JJTINDEXNODE) {
0699: Object o = accept(node, 0, context);
0700: Object idx = accept(node, 1, context);
0701: if (o instanceof String) {
0702: if (op != null || !(expr instanceof Character)) {
0703: throw new PnutsException("illegal.assign",
0704: NO_PARAM, context);
0705: }
0706: expr = Runtime.replaceChar((String) o, (Number) idx,
0707: expr);
0708: String sym = node.jjtGetChild(0).str;
0709: if (sym != null) {
0710: context.setValue(sym, expr);
0711: }
0712: return expr;
0713: } else {
0714: if (op != null) {
0715: expr = op.operateOn(Runtime.getElement(o, idx,
0716: context), expr);
0717: }
0718: Runtime.setElement(o, idx, expr, context);
0719: return expr;
0720: }
0721: } else if (node.id == PnutsParserTreeConstants.JJTSTATICMEMBERNODE) {
0722: SimpleNode c1 = node.children[0];
0723: String pkgName = getPackageName(c1);
0724: Package pkg = Package.find(pkgName, context);
0725: if (pkg != null) {
0726: if (op != null) {
0727: Object f = pkg.get(node.str, context);
0728: expr = op.operateOn(f, expr);
0729: }
0730: pkg.set(node.str, expr, context);
0731: return expr;
0732: }
0733: Object target = c1.accept(this , context);
0734: if (target instanceof Class) {
0735: Class clazz = (Class) target;
0736: if (op != null) {
0737: expr = op.operateOn(Runtime.getStaticField(context,
0738: clazz, node.str), expr);
0739: }
0740: Runtime.putStaticField(context, clazz, node.str, expr);
0741: return expr;
0742: } else {
0743: throw new PnutsException("package.notFound", NO_PARAM,
0744: context);
0745: }
0746: } else if (node.id == PnutsParserTreeConstants.JJTMEMBERNODE) {
0747: Object target = accept(node, 0, context);
0748: if (op != null) {
0749: expr = op.operateOn(Runtime.getField(context, target,
0750: node.str), expr);
0751: }
0752: Runtime.putField(context, target, node.str, expr);
0753: return expr;
0754: } else if (node.id == PnutsParserTreeConstants.JJTRANGENODE) {
0755: if (op != null) {
0756: throw new PnutsException("illegal.assign", NO_PARAM,
0757: context);
0758: }
0759: Object target = accept(node, 0, context);
0760: Object idx1 = accept(node, 1, context);
0761: Object idx2 = null;
0762: if (node.jjtGetNumChildren() >= 3) {
0763: idx2 = accept(node, 2, context);
0764: }
0765: Object value = setRange(target, idx1, idx2, expr, context);
0766: if (target instanceof String) {
0767: SimpleNode cld = node.children[0];
0768:
0769: if (cld.id == PnutsParserTreeConstants.JJTIDNODE
0770: || cld.id == PnutsParserTreeConstants.JJTGLOBAL
0771: || cld.id == PnutsParserTreeConstants.JJTINDEXNODE
0772: || cld.id == PnutsParserTreeConstants.JJTSTATICMEMBERNODE
0773: || cld.id == PnutsParserTreeConstants.JJTMEMBERNODE) {
0774: return doAssign(cld, value, context, null);
0775: } else {
0776: return value;
0777: }
0778: }
0779: return value;
0780: } else {
0781: throw new PnutsException("illegal.assign", NO_PARAM,
0782: context);
0783: }
0784: }
0785:
0786: private Object assign(SimpleNode node, Context context,
0787: BinaryOperator op) {
0788:
0789: Object expr = accept(node, 1, context);
0790: try {
0791: SimpleNode lhs = node.children[0];
0792: if (lhs.id == PnutsParserTreeConstants.JJTMULTIASSIGNLHS) {
0793: int n = lhs.jjtGetNumChildren();
0794: for (int i = 0; i < n; i++) {
0795: doAssign(lhs.children[i].str, Runtime.getElementAt(
0796: expr, i, context), context);
0797: }
0798: return expr;
0799: } else {
0800: return doAssign(lhs, expr, context, op);
0801: }
0802: } catch (PnutsException p) {
0803: throw p;
0804: } catch (Throwable t) {
0805: throw new PnutsException(t, context);
0806: }
0807: }
0808:
0809: public Object assignment(SimpleNode node, Context context) {
0810: return assign(node, context, null);
0811: }
0812:
0813: public Object assignmentTA(SimpleNode node, Context context) {
0814: return assign(node, context, context._multiply);
0815: }
0816:
0817: public Object assignmentMA(SimpleNode node, Context context) {
0818: return assign(node, context, context._mod);
0819: }
0820:
0821: public Object assignmentDA(SimpleNode node, Context context) {
0822: return assign(node, context, context._divide);
0823: }
0824:
0825: public Object assignmentPA(SimpleNode node, Context context) {
0826: return assign(node, context, context._add);
0827: }
0828:
0829: public Object assignmentSA(SimpleNode node, Context context) {
0830: return assign(node, context, context._subtract);
0831: }
0832:
0833: public Object assignmentLA(SimpleNode node, Context context) {
0834: return assign(node, context, context._shiftLeft);
0835: }
0836:
0837: public Object assignmentRA(SimpleNode node, Context context) {
0838: return assign(node, context, context._shiftRight);
0839: }
0840:
0841: public Object assignmentRAA(SimpleNode node, Context context) {
0842: return assign(node, context, context._shiftArithmetic);
0843: }
0844:
0845: public Object assignmentAA(SimpleNode node, Context context) {
0846: return assign(node, context, context._and);
0847: }
0848:
0849: public Object assignmentEA(SimpleNode node, Context context) {
0850: return assign(node, context, context._xor);
0851: }
0852:
0853: public Object assignmentOA(SimpleNode node, Context context) {
0854: return assign(node, context, context._or);
0855: }
0856:
0857: public Object logOrNode(SimpleNode node, Context context) {
0858: Object o1 = accept(node, 0, context);
0859: if (!(o1 instanceof Boolean)) {
0860: o1 = Runtime.toBoolean(o1);
0861: }
0862: if (((Boolean) o1).booleanValue()) {
0863: return Boolean.TRUE;
0864: } else {
0865: Object o2 = accept(node, 1, context);
0866: if (!(o2 instanceof Boolean)) {
0867: o2 = Runtime.toBoolean(o2);
0868: }
0869: return o2;
0870: }
0871: }
0872:
0873: public Object logAndNode(SimpleNode node, Context context) {
0874: Object o1 = accept(node, 0, context);
0875: if (!(o1 instanceof Boolean)) {
0876: o1 = Runtime.toBoolean(o1);
0877: }
0878: if (((Boolean) o1).booleanValue()) {
0879: Object o2 = accept(node, 1, context);
0880: if (!(o2 instanceof Boolean)) {
0881: o2 = Runtime.toBoolean(o2);
0882: }
0883: return o2;
0884: } else {
0885: return Boolean.FALSE;
0886: }
0887: }
0888:
0889: public Object orNode(SimpleNode node, Context context) {
0890: return context._or.operateOn(accept(node, 0, context), accept(
0891: node, 1, context));
0892: }
0893:
0894: public Object xorNode(SimpleNode node, Context context) {
0895: return context._xor.operateOn(accept(node, 0, context), accept(
0896: node, 1, context));
0897: }
0898:
0899: public Object andNode(SimpleNode node, Context context) {
0900: return context._and.operateOn(accept(node, 0, context), accept(
0901: node, 1, context));
0902: }
0903:
0904: public Object equalNode(SimpleNode node, Context context) {
0905: return eq(accept(node, 0, context), accept(node, 1, context),
0906: context) ? Boolean.TRUE : Boolean.FALSE;
0907: }
0908:
0909: public Object notEqNode(SimpleNode node, Context context) {
0910: return eq(accept(node, 0, context), accept(node, 1, context),
0911: context) ? Boolean.FALSE : Boolean.TRUE;
0912: }
0913:
0914: public Object instanceof Expression(SimpleNode node, Context context) {
0915: Object o1 = accept(node, 0, context);
0916: Class type = resolveType(node.jjtGetChild(1), context);
0917: return (type.isInstance(o1) ? Boolean.TRUE : Boolean.FALSE);
0918: }
0919:
0920: public Object ltNode(SimpleNode node, Context context) {
0921: if (context._lt.operateOn(accept(node, 0, context), accept(
0922: node, 1, context))) {
0923: return Boolean.TRUE;
0924: } else {
0925: return Boolean.FALSE;
0926: }
0927: }
0928:
0929: public Object gtNode(SimpleNode node, Context context) {
0930: if (context._gt.operateOn(accept(node, 0, context), accept(
0931: node, 1, context))) {
0932: return Boolean.TRUE;
0933: } else {
0934: return Boolean.FALSE;
0935: }
0936: }
0937:
0938: public Object leNode(SimpleNode node, Context context) {
0939: if (context._le.operateOn(accept(node, 0, context), accept(
0940: node, 1, context))) {
0941: return Boolean.TRUE;
0942: } else {
0943: return Boolean.FALSE;
0944: }
0945: }
0946:
0947: public Object geNode(SimpleNode node, Context context) {
0948: if (context._ge.operateOn(accept(node, 0, context), accept(
0949: node, 1, context))) {
0950: return Boolean.TRUE;
0951: } else {
0952: return Boolean.FALSE;
0953: }
0954: }
0955:
0956: public Object shiftLeftNode(SimpleNode node, Context context) {
0957: try {
0958: return context._shiftLeft.operateOn(
0959: accept(node, 0, context), accept(node, 1, context));
0960: } catch (Exception e) {
0961: throw new PnutsException(e, context);
0962: }
0963: }
0964:
0965: public Object shiftRightNode(SimpleNode node, Context context) {
0966: try {
0967: return context._shiftRight.operateOn(accept(node, 0,
0968: context), accept(node, 1, context));
0969: } catch (Exception e) {
0970: throw new PnutsException(e, context);
0971: }
0972: }
0973:
0974: public Object shiftArithmeticNode(SimpleNode node, Context context) {
0975: try {
0976: return context._shiftArithmetic.operateOn(accept(node, 0,
0977: context), accept(node, 1, context));
0978: } catch (Exception e) {
0979: throw new PnutsException(e, context);
0980: }
0981: }
0982:
0983: public Object addNode(SimpleNode node, Context context) {
0984: try {
0985: return context._add.operateOn(accept(node, 0, context),
0986: accept(node, 1, context));
0987: } catch (Exception e) {
0988: throw new PnutsException(e, context);
0989: }
0990: }
0991:
0992: public Object subtractNode(SimpleNode node, Context context) {
0993: try {
0994: return context._subtract.operateOn(
0995: accept(node, 0, context), accept(node, 1, context));
0996: } catch (Exception e) {
0997: throw new PnutsException(e, context);
0998: }
0999: }
1000:
1001: public Object multNode(SimpleNode node, Context context) {
1002: try {
1003: return context._multiply.operateOn(
1004: accept(node, 0, context), accept(node, 1, context));
1005: } catch (Exception e) {
1006: throw new PnutsException(e, context);
1007: }
1008: }
1009:
1010: public Object divideNode(SimpleNode node, Context context) {
1011: try {
1012: return context._divide.operateOn(accept(node, 0, context),
1013: accept(node, 1, context));
1014: } catch (Exception e) {
1015: throw new PnutsException(e, context);
1016: }
1017: }
1018:
1019: public Object modNode(SimpleNode node, Context context) {
1020: try {
1021: return context._mod.operateOn(accept(node, 0, context),
1022: accept(node, 1, context));
1023: } catch (Exception e) {
1024: throw new PnutsException(e, context);
1025: }
1026: }
1027:
1028: public Object negativeNode(SimpleNode node, Context context) {
1029: try {
1030: return context._negate.operateOn(accept(node, 0, context));
1031: } catch (Exception e) {
1032: throw new PnutsException(e, context);
1033: }
1034: }
1035:
1036: public Object preIncrNode(SimpleNode node, Context context) {
1037: return doAssign(node.children[0], one, context, context._add);
1038: }
1039:
1040: public Object preDecrNode(SimpleNode node, Context context) {
1041: return doAssign(node.children[0], one, context,
1042: context._subtract);
1043: }
1044:
1045: public Object postIncrNode(SimpleNode node, Context context) {
1046: SimpleNode n = node.children[0];
1047: Object ret = n.accept(this , context);
1048: doAssign(n, one, context, context._add);
1049: return ret;
1050: }
1051:
1052: public Object postDecrNode(SimpleNode node, Context context) {
1053: SimpleNode n = node.children[0];
1054: Object ret = n.accept(this , context);
1055: doAssign(n, one, context, context._subtract);
1056: return ret;
1057: }
1058:
1059: public Object notNode(SimpleNode node, Context context) {
1060: return context._not.operateOn(accept(node, 0, context));
1061: }
1062:
1063: public Object logNotNode(SimpleNode node, Context context) {
1064: Object o = accept(node, 0, context);
1065: if (o instanceof Boolean) {
1066: return ((Boolean) o).booleanValue() ? Boolean.FALSE
1067: : Boolean.TRUE;
1068: } else {
1069: return Runtime.toBoolean(o).booleanValue() ? Boolean.FALSE
1070: : Boolean.TRUE;
1071: }
1072: }
1073:
1074: public Object continueNode(SimpleNode node, Context context) {
1075: throw new Runtime.Continue();
1076: }
1077:
1078: public Object breakNode(SimpleNode node, Context context) {
1079: Object o = null;
1080: if (node.jjtGetNumChildren() > 0) {
1081: o = accept(node, 0, context);
1082: }
1083:
1084: if (context.inGeneratorClosure) {
1085: throw new Generator.Break(o);
1086: } else {
1087: throw new Runtime.Break(o);
1088: }
1089: }
1090:
1091: public Object returnNode(SimpleNode node, Context context) {
1092: Object o = null;
1093: if (node.jjtGetNumChildren() > 0) {
1094: o = accept(node, 0, context);
1095: }
1096: throw new Jump(o);
1097: }
1098:
1099: public Object yieldNode(SimpleNode node, Context context) {
1100: throw new PnutsException(
1101: "yield must be used in a generator function", context);
1102: }
1103:
1104: public Object catchNode(SimpleNode node, Context context) {
1105: int nargs = node.jjtGetNumChildren();
1106: if (nargs == 0) {
1107: return PnutsFunction.CATCH;
1108: } else if (nargs == 1) {
1109: Class cls = (Class) accept(node, 0, context);
1110: PnutsFunction func = (PnutsFunction) accept(node, 1,
1111: context);
1112: context.catchException(cls, func);
1113: }
1114: return null;
1115: }
1116:
1117: public Object throwNode(SimpleNode node, Context context) {
1118: int nargs = node.jjtGetNumChildren();
1119: if (nargs == 0) {
1120: return PnutsFunction.THROW;
1121: } else if (nargs == 1) {
1122: Object arg = accept(node, 0, context);
1123: if (arg instanceof PnutsException) {
1124: throw (PnutsException) arg;
1125: } else if (arg instanceof Throwable) {
1126: throw new PnutsException((Throwable) arg, context);
1127: } else {
1128: throw new PnutsException(String.valueOf(arg), context);
1129: }
1130: }
1131: return null;
1132: }
1133:
1134: public Object finallyNode(SimpleNode node, Context context) {
1135: int n = node.jjtGetNumChildren();
1136: if (n == 1) {
1137: PnutsFunction f = (PnutsFunction) accept(node, 0, context);
1138: context.setFinallyFunction(f);
1139: return f;
1140: } else if (n == 2) {
1141: PnutsFunction f0 = (PnutsFunction) accept(node, 0, context);
1142: PnutsFunction f1 = (PnutsFunction) accept(node, 1, context);
1143: try {
1144: return f0.exec(NO_PARAM, context);
1145: } finally {
1146: f1.exec(NO_PARAM, context);
1147: }
1148: }
1149: return null;
1150: }
1151:
1152: public Object tryStatement(SimpleNode node, Context context) {
1153: int n = node.jjtGetNumChildren();
1154: SimpleNode lastNode = node.jjtGetChild(n - 1);
1155: PnutsException pe = null;
1156: Object value = null;
1157: boolean handled = false;
1158: SimpleNode finallyBlock = null;
1159: if (lastNode.id == PnutsParserTreeConstants.JJTFINALLYBLOCK) {
1160: finallyBlock = lastNode;
1161: }
1162: try {
1163: value = accept(node, 0, context);
1164: } catch (Escape esc) {
1165: throw esc;
1166: } catch (Runtime.Break brk) {
1167: throw brk;
1168: } catch (Runtime.Continue cont) {
1169: throw cont;
1170: } catch (Throwable t) {
1171: if (t instanceof PnutsException) {
1172: pe = (PnutsException) t;
1173: t = ((PnutsException) t).getThrowable();
1174: }
1175: for (int i = 1; i < n; i++) {
1176: SimpleNode c = node.jjtGetChild(i);
1177: if (c.id == PnutsParserTreeConstants.JJTCATCHBLOCK) {
1178: String var = c.str;
1179: StringBuffer sbuf = new StringBuffer();
1180: SimpleNode classNode = c.jjtGetChild(0);
1181: sbuf.append(classNode.jjtGetChild(0).str);
1182: for (int j = 1; j < classNode.jjtGetNumChildren(); j++) {
1183: sbuf.append('.');
1184: sbuf.append(classNode.jjtGetChild(j).str);
1185: }
1186: Class cls = context.resolveClass(sbuf.toString());
1187:
1188: if (cls != null && cls.isInstance(t)) {
1189: try {
1190: context.openLocal(new String[] {});
1191: context.bind(var, t);
1192: return accept(c, 1, context);
1193: } finally {
1194: context.closeLocal();
1195: }
1196: }
1197: }
1198: }
1199: if (pe != null) {
1200: throw pe;
1201: } else {
1202: throw new PnutsException(t, context);
1203: }
1204: } finally {
1205: if (finallyBlock != null) {
1206: accept(finallyBlock, 0, context);
1207: }
1208: }
1209: return value;
1210: }
1211:
1212: public Object catchBlock(SimpleNode node, Context context) {
1213: return null;
1214: }
1215:
1216: public Object blockNode(SimpleNode node, Context context) {
1217: Object last = null;
1218: int n = node.jjtGetNumChildren();
1219: for (int i = 0; i < n; i++) {
1220: last = accept(node, i, context);
1221: }
1222: return last;
1223: }
1224:
1225: public Object ifStatement(SimpleNode node, Context context) {
1226:
1227: Object con = accept(node, 0, context);
1228: if (condition(con, context)) {
1229: return accept(node, 1, context);
1230: }
1231: int n = node.jjtGetNumChildren();
1232: for (int i = 2; i < n; i++) {
1233: SimpleNode _node = node.children[i];
1234: if (_node.id == PnutsParserTreeConstants.JJTELSEIFNODE) {
1235: if (condition(accept(_node, 0, context), context)) {
1236: return accept(_node, 1, context);
1237: }
1238: } else if (_node.id == PnutsParserTreeConstants.JJTELSENODE) {
1239: return accept(_node, 0, context);
1240: }
1241: }
1242: return null;
1243: }
1244:
1245: static boolean condition(Object cond, Context context) {
1246: if (cond instanceof Boolean) {
1247: return ((Boolean) cond).booleanValue();
1248: } else {
1249: return (Runtime.toBoolean(cond)).booleanValue();
1250: }
1251: }
1252:
1253: public Object doStatement(SimpleNode node, Context context) {
1254: Object last = null;
1255: try {
1256: while (true) {
1257: try {
1258: last = accept(node, 0, context);
1259: Object cond = accept(node, 1, context);
1260: if (!(cond instanceof Boolean)) {
1261: cond = Runtime.toBoolean(cond);
1262: }
1263: boolean b = ((Boolean) cond).booleanValue();
1264: if (!b) {
1265: return last;
1266: }
1267: } catch (Runtime.Continue cont) {
1268: }
1269: }
1270: } catch (Runtime.Break brk) {
1271: return brk.getValue();
1272: }
1273: }
1274:
1275: public Object whileStatement(SimpleNode node, Context context) {
1276: Object last = null;
1277: try {
1278: while (true) {
1279: Object cond = accept(node, 0, context);
1280: if (!(cond instanceof Boolean)) {
1281: cond = Runtime.toBoolean(cond);
1282: }
1283: try {
1284: boolean b = ((Boolean) cond).booleanValue();
1285: if (b) {
1286: last = accept(node, 1, context);
1287: } else {
1288: return last;
1289: }
1290: } catch (Runtime.Continue cont) {
1291: }
1292: }
1293: } catch (Runtime.Break brk) {
1294: return brk.getValue();
1295: }
1296: }
1297:
1298: public Object forStatement(SimpleNode node, final Context context) {
1299: SimpleNode initNode = null;
1300: SimpleNode condNode = null;
1301: SimpleNode updateNode = null;
1302: SimpleNode blockNode = null;
1303: int j = 0;
1304: SimpleNode n = node.children[j];
1305: if (n.id == PnutsParserTreeConstants.JJTFORENUM) {
1306: int nc = n.jjtGetNumChildren();
1307: SimpleNode node0 = n.children[0];
1308: String[] vars;
1309: Object n0;
1310: if (node0.id == PnutsParserTreeConstants.JJTMULTIASSIGNLHS) {
1311: int nc2 = node0.jjtGetNumChildren();
1312: vars = new String[nc2];
1313: for (int i = 0; i < nc2; i++) {
1314: vars[i] = node0.jjtGetChild(i).str;
1315: }
1316: n0 = n.children[1].accept(this , context);
1317: } else {
1318: vars = new String[] { n.str };
1319: n0 = node0.accept(this , context);
1320: }
1321: blockNode = node.children[1];
1322: if (node0.id == PnutsParserTreeConstants.JJTMULTIASSIGNLHS
1323: || nc == 1) {
1324: return doForeach(vars, n0, blockNode, context);
1325: } else if (nc == 2) {
1326: Object n1 = n.children[1].accept(this , context);
1327: int start = ((Number) n0).intValue();
1328: int end = ((Number) n1).intValue();
1329: return doForeach(n.str, start, end, blockNode, context);
1330: } else {
1331: throw new IllegalArgumentException();
1332: }
1333: } else if (n.id == PnutsParserTreeConstants.JJTFORINIT) {
1334: initNode = n;
1335: j++;
1336: }
1337: n = node.children[j];
1338: if (n.id != PnutsParserTreeConstants.JJTFORUPDATE
1339: && n.id != PnutsParserTreeConstants.JJTBLOCK) {
1340: condNode = n;
1341: j++;
1342: }
1343: n = node.children[j];
1344: if (n.id == PnutsParserTreeConstants.JJTFORUPDATE) {
1345: updateNode = n;
1346: j++;
1347: }
1348:
1349: blockNode = node.children[j];
1350:
1351: Object last = null;
1352:
1353: if (initNode != null) {
1354: int num = initNode.jjtGetNumChildren();
1355: String[] env = new String[num];
1356: for (int i = 0; i < env.length; i++) {
1357: SimpleNode sn = initNode.children[i];
1358: env[i] = sn.str;
1359: }
1360: context.openLocal(env);
1361: for (int i = 0; i < env.length; i++) {
1362: SimpleNode sn = initNode.children[i];
1363: context.bind(env[i], accept(sn, 0, context));
1364: }
1365: } else {
1366: context.openLocal(new String[] {});
1367: }
1368:
1369: Object c = null;
1370: if (condNode != null) {
1371: c = condNode.accept(this , context);
1372: } else {
1373: c = Boolean.TRUE;
1374: }
1375: try {
1376: while (true) {
1377: if (!(c instanceof Boolean)) {
1378: c = Runtime.toBoolean(c);
1379: }
1380: if (!((Boolean) c).booleanValue()) {
1381: break;
1382: }
1383: try {
1384: last = blockNode.accept(this , context);
1385: } catch (Runtime.Continue cont) {
1386: }
1387: if (updateNode != null) {
1388: expressionList(updateNode, context);
1389: }
1390: if (condNode != null) {
1391: c = condNode.accept(this , context);
1392: }
1393: }
1394: } catch (Runtime.Break brk) {
1395: last = brk.getValue();
1396: } finally {
1397: context.closeLocal();
1398: }
1399: return last;
1400: }
1401:
1402: private Object doForeach(String var, int start, int end,
1403: SimpleNode blockNode, Context context) {
1404: Object last = null;
1405: context.openLocal(new String[] { var });
1406: int delta;
1407: try {
1408: if (start < end) {
1409: for (int i = start; i <= end; i++) {
1410: try {
1411: context.bind(var, new Integer(i));
1412: last = blockNode.accept(this , context);
1413: } catch (Runtime.Continue cont) {
1414: }
1415: }
1416: } else {
1417: for (int i = start; i >= end; i--) {
1418: try {
1419: context.bind(var, new Integer(i));
1420: last = blockNode.accept(this , context);
1421: } catch (Runtime.Continue cont) {
1422: }
1423: }
1424: }
1425: } catch (Runtime.Break brk) {
1426: last = brk.getValue();
1427: } finally {
1428: context.closeLocal();
1429: }
1430: return last;
1431: }
1432:
1433: private Object doForeach(final String[] vars, Object array,
1434: SimpleNode blockNode, final Context context) {
1435: if (array == null) {
1436: return null;
1437: }
1438: if (array instanceof Generator) {
1439: final String tmpVar = "_tmp".intern();
1440: if (vars.length > 1) {
1441: blockNode = GeneratorHelper.expandMultiAssign(vars,
1442: tmpVar, blockNode);
1443: }
1444: Function f = new Function(null,
1445: vars.length > 1 ? new String[] { tmpVar } : vars,
1446: 1, false, blockNode, context.getCurrentPackage(),
1447: context) {
1448: protected Object exec(Object[] args, Context context) {
1449: boolean inGeneratorClosure = context.inGeneratorClosure;
1450: try {
1451: context.inGeneratorClosure = true;
1452: return super .exec(args, context);
1453: } finally {
1454: context.inGeneratorClosure = inGeneratorClosure;
1455: }
1456: }
1457: };
1458: return Runtime.applyGenerator((Generator) array, f
1459: .register(null), context);
1460: }
1461:
1462: Enumeration e = Runtime.toEnumeration(array, context);
1463: if (e == null) {
1464: throw new PnutsException("illegal.type.foreach",
1465: new Object[] { Pnuts.format(array) }, context);
1466: }
1467: Object last = null;
1468: context.openLocal(vars);
1469: try {
1470: if (vars.length == 1) {
1471: while (e.hasMoreElements()) {
1472: try {
1473: context.bind(vars[0], e.nextElement());
1474: last = blockNode.accept(this , context);
1475: } catch (Runtime.Continue cont) {
1476: }
1477: }
1478: } else {
1479: while (e.hasMoreElements()) {
1480: try {
1481: Object elem = e.nextElement();
1482: for (int i = 0; i < vars.length; i++) {
1483: context.bind(vars[i], Runtime.getElementAt(
1484: elem, i, context));
1485: }
1486: last = blockNode.accept(this , context);
1487: } catch (Runtime.Continue cont) {
1488: }
1489: }
1490: }
1491: } catch (Runtime.Break brk) {
1492: last = brk.getValue();
1493: } finally {
1494: context.closeLocal();
1495: }
1496: return last;
1497: }
1498:
1499: public Object foreachStatement(SimpleNode node, Context context) {
1500: SimpleNode n1 = node.children[0];
1501: SimpleNode n2 = node.children[1];
1502: String var = node.str;
1503:
1504: return doForeach(new String[] { var },
1505: n1.accept(this , context), n2, context);
1506: }
1507:
1508: public Object switchStatement(SimpleNode node, Context context) {
1509: int n = node.jjtGetNumChildren();
1510: Object target = accept(node, 0, context);
1511: Object last = null;
1512: boolean matched = false;
1513: try {
1514: for (int i = 1; i < n; i++) {
1515: SimpleNode _node = node.children[i];
1516: if (_node.jjtGetNumChildren() == 1) { // case
1517: Object o = accept(_node, 0, context);
1518: i++;
1519: if (matched || eq(target, o, context)) {
1520: last = accept(node, i, context);
1521: matched = true;
1522: }
1523: } else { // default
1524: matched = true;
1525: last = accept(node, ++i, context);
1526: }
1527: }
1528: } catch (Runtime.Break brk) {
1529: last = brk.getValue();
1530: }
1531: return last;
1532: }
1533:
1534: public Object switchBlock(SimpleNode node, Context context) {
1535: int n = node.jjtGetNumChildren();
1536: Object last = null;
1537: for (int i = 0; i < n; i++) {
1538: last = accept(node, i, context);
1539: }
1540: return last;
1541: }
1542:
1543: public Object functionStatement(SimpleNode node, Context context) {
1544: SimpleNode param = node.jjtGetChild(0);
1545: int nargs = param.jjtGetNumChildren();
1546: String[] locals = new String[nargs];
1547: SimpleNode n0 = null;
1548: SimpleNode block = node.jjtGetChild(1);
1549:
1550: synchronized (node) {
1551: if (node.getAttribute("type") == null) {
1552: if (Runtime.isGenerator(block)) {
1553: node.setAttribute("type", GENERATOR);
1554: } else {
1555: node.setAttribute("type", FUNCTION);
1556: }
1557: }
1558: }
1559:
1560: boolean varargs = "[".equals(param.str);
1561:
1562: for (int j = 0; j < nargs; j++) {
1563: locals[j] = param.children[j].str;
1564: }
1565:
1566: String symbol = node.str;
1567: StackFrame stackFrame = context.stackFrame;
1568: Package pkg = context.getCurrentPackage();
1569:
1570: Function f;
1571: if (node.getAttribute("type") == GENERATOR) {
1572: f = new Generator.GeneratorFunction(symbol, locals, nargs,
1573: block, pkg, context);
1574: } else {
1575: f = new Function(symbol, locals, nargs, varargs, block,
1576: pkg, context);
1577: }
1578: // String name = f.getName();
1579: PnutsFunction ht = null;
1580:
1581: if (symbol != null) {
1582: if (stackFrame.parent != null) {
1583: Object o = null;
1584: Binding b = (Binding) stackFrame.lookup(symbol);
1585: boolean found = false;
1586: if (b != null) {
1587: o = b.value;
1588: if (o instanceof PnutsFunction) {
1589: ht = f.register((PnutsFunction) o);
1590: } else {
1591: ht = Runtime.defineUnboundFunction(f, symbol,
1592: pkg);
1593: }
1594: found = true;
1595: } else {
1596: Function ff = context.frame;
1597: while (ff != null) {
1598: SymbolTable ls = ff.lexicalScope;
1599: if (ls != null) {
1600: Binding bb = ls.lookup0(symbol);
1601: if (bb != null) {
1602: o = ((Binding) bb.value).value;
1603: if (o instanceof PnutsFunction) {
1604: ht = f.register((PnutsFunction) o,
1605: true);
1606: } else {
1607: ht = Runtime.defineUnboundFunction(
1608: f, symbol, pkg);
1609: }
1610: found = true;
1611: break;
1612: }
1613: }
1614: ff = ff.outer;
1615: }
1616: }
1617: if (!found) {
1618: ht = Runtime.defineUnboundFunction(f, symbol, pkg);
1619: }
1620:
1621: if (b != null) {
1622: b.set(ht);
1623: } else {
1624: stackFrame.assign(symbol, ht);
1625: }
1626: } else {
1627: ht = Runtime.defineTopLevelFunction(f, symbol, pkg,
1628: context);
1629: }
1630: } else {
1631: ht = f.register(null);
1632: }
1633: return ht;
1634: }
1635:
1636: public Object ternary(SimpleNode node, Context context) {
1637: if (condition(accept(node, 0, context), context)) {
1638: return accept(node, 1, context);
1639: } else {
1640: return accept(node, 2, context);
1641: }
1642: }
1643:
1644: protected Object accept(SimpleNode node, int idx, Context context) {
1645: return node.children[idx].accept(this , context);
1646: }
1647:
1648: static String getClassName(SimpleNode node) {
1649: int n = node.jjtGetNumChildren();
1650: if (n > 1) {
1651: StringBuffer sbuf = new StringBuffer();
1652: sbuf.append(node.children[0].str);
1653: for (int i = 1; i < n; i++) {
1654: sbuf.append('.');
1655: sbuf.append(node.children[i].str);
1656: }
1657: return sbuf.toString().intern();
1658: } else {
1659: return node.children[0].str;
1660: }
1661: }
1662:
1663: static Class resolveTypeNode(SimpleNode typeNode, Context context) {
1664: Class type = null;
1665: if (typeNode.id == PnutsParserTreeConstants.JJTARRAYTYPE) {
1666: SimpleNode n = typeNode;
1667: int count = 0;
1668: while (n != null
1669: && n.id == PnutsParserTreeConstants.JJTARRAYTYPE) {
1670: count++;
1671: n = n.jjtGetChild(0);
1672: }
1673: if (n != null
1674: && n.id == PnutsParserTreeConstants.JJTCLASSNAME) {
1675: type = Runtime.arrayType(resolveClassNameNode(n,
1676: context), count);
1677: }
1678: } else if (typeNode.id == PnutsParserTreeConstants.JJTCLASSNAME) {
1679: type = resolveClassNameNode(typeNode, context);
1680: } else {
1681: throw new RuntimeException();
1682: }
1683: return type;
1684: }
1685:
1686: static Class resolveClassNameNode(SimpleNode node, Context context) {
1687: int n = node.jjtGetNumChildren();
1688: if (n == 1) {
1689: String sym = node.children[0].str;
1690: if (sym == INT_SYMBOL) {
1691: return Integer.TYPE;
1692: } else if (sym == SHORT_SYMBOL) {
1693: return Short.TYPE;
1694: } else if (sym == CHAR_SYMBOL) {
1695: return Character.TYPE;
1696: } else if (sym == BYTE_SYMBOL) {
1697: return Byte.TYPE;
1698: } else if (sym == LONG_SYMBOL) {
1699: return Long.TYPE;
1700: } else if (sym == FLOAT_SYMBOL) {
1701: return Float.TYPE;
1702: } else if (sym == DOUBLE_SYMBOL) {
1703: return Double.TYPE;
1704: } else if (sym == BOOLEAN_SYMBOL) {
1705: return Boolean.TYPE;
1706: } else if (sym == VOID_SYMBOL) {
1707: return Void.TYPE;
1708: }
1709: }
1710: String name = getClassName(node);
1711: Class cls = context.resolveClass(name);
1712: if (cls == null) {
1713: throw new PnutsException("class.notFound",
1714: new Object[] { name }, context);
1715: }
1716: return cls;
1717: }
1718:
1719: public Class resolveType(SimpleNode typeNode, Context context) {
1720: Class type = null;
1721: if (typeNode.id == PnutsParserTreeConstants.JJTARRAYTYPE) {
1722: SimpleNode n = typeNode;
1723: int count = 0;
1724: while (n != null
1725: && n.id == PnutsParserTreeConstants.JJTARRAYTYPE) {
1726: count++;
1727: n = n.jjtGetChild(0);
1728: }
1729: if (n != null
1730: && n.id != PnutsParserTreeConstants.JJTCLASSNAME) {
1731: throw new RuntimeException();
1732: }
1733: return Runtime.arrayType(resolveClassNameNode(n, context),
1734: count);
1735: } else if (typeNode.id == PnutsParserTreeConstants.JJTCLASSNAME) {
1736: return resolveClassNameNode(typeNode, context);
1737: } else {
1738: throw new PnutsException("class.expected", NO_PARAM,
1739: context);
1740: }
1741: }
1742:
1743: public Object beanDef(SimpleNode node, Context context) {
1744: SimpleNode classNameNode = node.jjtGetChild(0);
1745: Configuration config = context.getConfiguration();
1746:
1747: boolean marked = (node.info != null); /* experimental BIND feature */
1748: Map table = new HashMap(); // temporary hashtable to collect listeners
1749: try {
1750: Class cls = (Class) classNameNode.accept(this , context);
1751: Object target = config.callConstructor(context, cls,
1752: NO_PARAM, null);
1753:
1754: for (int i = 1; i < node.jjtGetNumChildren(); i++) {
1755: SimpleNode c = node.jjtGetChild(i);
1756: boolean bound = "::".equals(c.info);
1757:
1758: String propertyName = c.str;
1759: SimpleNode valueNode = c.jjtGetChild(0);
1760: if (bound && !marked) { /* experimental BIND feature */
1761: List memberNodes = new ArrayList();
1762: c.info = memberNodes;
1763: markMemberNodeInBeanDef(c, target, table, valueNode);
1764: }
1765: Object value = valueNode.accept(this , context);
1766: config.putField(context, target, propertyName, value);
1767: }
1768: if (!marked) {
1769: Runtime.setupPropertyChangeListeners(table, context);/* experimental BIND feature */
1770: node.info = target;
1771: }
1772: return target;
1773: } catch (Exception e) {
1774: throw new PnutsException(e, context);
1775: }
1776: }
1777:
1778: static void markMemberNodeInBeanDef(SimpleNode beanPropertyDef,
1779: Object target, Map table, SimpleNode node) {
1780: if (node.id == PnutsParserTreeConstants.JJTMEMBERNODE) {
1781: node.info = new Object[] { target, beanPropertyDef, table };
1782: } else if (node.id != PnutsParserTreeConstants.JJTFUNCTIONSTATEMENT) {
1783: for (int i = 0; i < node.jjtGetNumChildren(); i++) {
1784: markMemberNodeInBeanDef(beanPropertyDef, target, table,
1785: node.jjtGetChild(i));
1786: }
1787: }
1788: }
1789:
1790: }
|