50
50
public class CodeExpression implements Serializable {
51
51
// Variable flags in C Electric
52
/** variable is interpreted code (with VCODE2) */ private static final int VCODE1 = 040;
53
/** variable is interpreted code (with VCODE1) */ private static final int VCODE2 = 04000000000;
54
/** variable is LISP */ private static final int VSPICE = VCODE1;
55
/** variable is TCL */ private static final int VTCL = VCODE2;
56
/** variable is Java */ private static final int VJAVA = (VCODE1|VCODE2);
58
private static final HashMap <String,CodeExpression> javaExpressions = new HashMap<String,CodeExpression>();
59
private static final HashMap <String,CodeExpression> spiceExpressions = new HashMap<String,CodeExpression>();
60
private static final HashMap <String,CodeExpression> tclExpressions = new HashMap<String,CodeExpression>();
53
/** variable is interpreted code (with VCODE2) */
54
private static final int VCODE1 = 040;
55
/** variable is interpreted code (with VCODE1) */
56
private static final int VCODE2 = 04000000000;
57
/** variable is LISP */
58
private static final int VSPICE = VCODE1;
59
/** variable is TCL */
60
private static final int VTCL = VCODE2;
61
/** variable is Java */
62
private static final int VJAVA = (VCODE1 | VCODE2);
63
private static final HashMap<String, CodeExpression> javaExpressions = new HashMap<String, CodeExpression>();
64
private static final HashMap<String, CodeExpression> spiceExpressions = new HashMap<String, CodeExpression>();
65
private static final HashMap<String, CodeExpression> tclExpressions = new HashMap<String, CodeExpression>();
61
66
private static long numValueOfs;
62
/** For replacing @variable */ private static final Pattern pPat = Pattern.compile("P\\(\"(\\w+)\"\\)");
67
/** For replacing @variable */
68
private static final Pattern pPat = Pattern.compile("P\\(\"(\\w+)\"\\)");
64
69
private final Code code;
65
70
private final String expr;
66
71
private final Set<Variable.Key> depends;
75
80
* value should be evaluated. If NONE, no evaluation is done.
77
82
public static enum Code {
78
/** Indicator that code is in Java. */ JAVA("Java", VJAVA),
79
/** Indicator that code is in Lisp. */ SPICE("Spice", VSPICE),
80
/** Indicator that code is in TCL. */ TCL("TCL (not avail.)", VTCL),
81
/** Indicator that this is not code. */ NONE("Not Code", 0);
84
/** Indicator that code is in Java. */
86
/** Indicator that code is in Lisp. */
87
SPICE("Spice", VSPICE),
88
/** Indicator that code is in TCL. */
89
TCL("TCL (not avail.)", VTCL),
90
/** Indicator that this is not code. */
83
92
private final String name;
84
93
private final int cFlags;
85
94
private static final Code[] allCodes = Code.class.getEnumConstants();
89
98
this.cFlags = cFlags;
93
* Method to return the bits value of this code type.
94
* This is used in I/O.
95
* @return the bits value of this code type.
97
public int getCFlags() { return cFlags; }
102
* Method to return the bits value of this code type.
103
* This is used in I/O.
104
* @return the bits value of this code type.
106
public int getCFlags() {
100
* Method to return a printable version of this Code.
101
* @return a printable version of this Code.
103
public String toString() { return name; }
111
* Method to return a printable version of this Code.
112
* @return a printable version of this Code.
114
public String toString() {
106
119
* Method to get an iterator over all Code types.
108
public static Iterator<Code> getCodes() { return ArrayIterator.iterator(allCodes); }
121
public static Iterator<Code> getCodes() {
122
return ArrayIterator.iterator(allCodes);
111
* Method to convert a bits value to a Code object.
112
* @param cBits the bits value (from I/O).
113
* @return the Code associated with those bits.
115
public static Code getByCBits(int cBits)
117
switch (cBits & (VCODE1|VCODE2))
119
case VJAVA: return JAVA;
120
case VSPICE: return SPICE;
121
case VTCL: return TCL;
122
default: return NONE;
126
* Method to convert a bits value to a Code object.
127
* @param cBits the bits value (from I/O).
128
* @return the Code associated with those bits.
130
public static Code getByCBits(int cBits) {
131
switch (cBits & (VCODE1 | VCODE2)) {
127
* Method to get a Code constant by its ordinal number.
128
* @param ordinal the ordinal number of this Code constant ( as returned by ordinal()
129
* @return the Code associated with this ordinal number.
131
public static Code getByOrdinal(int ordinal)
144
* Method to get a Code constant by its ordinal number.
145
* @param ordinal the ordinal number of this Code constant ( as returned by ordinal()
146
* @return the Code associated with this ordinal number.
148
public static Code getByOrdinal(int ordinal) {
133
149
return allCodes[ordinal];
216
public Code getCode() { return code; }
217
public boolean isJava() { return code == Code.JAVA; }
218
public String getExpr() { return expr; }
219
public Set<Variable.Key> dependsOn() { return depends; }
220
public EvalSpice.ParseException getParseException() { return parseException; }
221
public String getSpiceText() { return spiceText; }
251
public Code getCode() {
255
public boolean isJava() {
256
return code == Code.JAVA;
259
public String getExpr() {
263
public Set<Variable.Key> dependsOn() {
267
public EvalSpice.ParseException getParseException() {
268
return parseException;
271
public String getSpiceText() {
222
275
public String getHSpiceText(boolean inPar) {
223
276
return dependsOnEverything ? null : inPar ? spiceTextPar : spiceText;
225
public String getVerilogText() { return spiceText; }
279
public String getVerilogText() {
226
283
public Object eval() {
227
if (parseException != null)
284
if (parseException != null) {
228
285
return parseException.getMessage();
229
287
return exprTree.eval(new EvalContext());
275
335
* @param verbose print all CodeExpressions
277
337
public static void printStatistics(boolean verbose) {
278
System.out.println((javaExpressions.size() + spiceExpressions.size() + tclExpressions.size()) +
279
" CodeExpressions after " + numValueOfs + " valueOf calls");
280
if (!verbose) return;
338
System.out.println((javaExpressions.size() + spiceExpressions.size() + tclExpressions.size())
339
+ " CodeExpressions after " + numValueOfs + " valueOf calls");
282
344
System.out.println(javaExpressions.size() + " java strings");
283
for (CodeExpression ce: new TreeMap<String,CodeExpression>(javaExpressions).values())
345
for (CodeExpression ce : new TreeMap<String, CodeExpression>(javaExpressions).values()) {
285
348
System.out.println(spiceExpressions.size() + " spice strings");
286
for (CodeExpression ce: new TreeMap<String,CodeExpression>(spiceExpressions).values())
349
for (CodeExpression ce : new TreeMap<String, CodeExpression>(spiceExpressions).values()) {
288
352
System.out.println(tclExpressions.size() + " tcl strings");
289
for (CodeExpression ce: new TreeMap<String,CodeExpression>(tclExpressions).values())
353
for (CodeExpression ce : new TreeMap<String, CodeExpression>(tclExpressions).values()) {
293
358
private static void printCE(CodeExpression ce) {
294
359
System.out.print("\"" + ce.getExpr() + "\"\t");
295
if (ce.dependsOnEverything)
360
if (ce.dependsOnEverything) {
296
361
System.out.print(" ALL");
297
for (Variable.Key varKey: ce.dependsOn())
363
for (Variable.Key varKey : ce.dependsOn()) {
298
364
System.out.print(" " + varKey);
299
if (ce.parseException != null)
366
if (ce.parseException != null) {
300
367
System.out.print(" ? " + ce.parseException.getMessage());
302
369
System.out.print(" -> \"" + ce.spiceText + "\"");
303
371
System.out.println();
306
374
private static class EvalContext {
307
private Object getDrive() { return null; }
308
private Object subDrive(String instName, String varName) { return null; }
309
private Object get(Variable.Key varKey) { return null; }
376
private Object getDrive() {
380
private Object subDrive(String instName, String varName) {
384
private Object get(Variable.Key varKey) {
312
389
private static abstract class Expr {
313
391
static final int MIN_PRECEDENCE = 1;
314
392
static final int MAX_PRECEDENCE = EvalSpice.Op.COND.precedence;
315
int numSubExprs() { return 0; }
316
Expr getSubExpr(int i) { throw new IndexOutOfBoundsException(); }
398
Expr getSubExpr(int i) {
399
throw new IndexOutOfBoundsException();
317
402
void appendText(StringBuilder sb, int outerPrecedence) {
318
403
if (outerPrecedence < precedence()) {
326
412
abstract void appendText(StringBuilder sb);
327
int precedence() { return MIN_PRECEDENCE; }
415
return MIN_PRECEDENCE;
328
418
boolean dependsOnEverything() {
329
419
for (int i = 0; i < numSubExprs(); i++) {
330
if (getSubExpr(i).dependsOnEverything())
420
if (getSubExpr(i).dependsOnEverything()) {
335
427
abstract Object eval(EvalContext context);
336
static boolean bool(double d) { return d != 0; }
429
static boolean bool(double d) {
339
434
private static class ConstExpr extends Expr {
340
436
private final Object value;
341
ConstExpr(Object value) { this.value = value; }
438
ConstExpr(Object value) {
342
442
void appendText(StringBuilder sb) {
343
String s = TextUtils.formatDoublePostFix(((Double)value).doubleValue());
443
String s = TextUtils.formatDoublePostFix(((Double) value).doubleValue());
346
Object eval(EvalContext context) { return value; }
447
Object eval(EvalContext context) {
349
452
private static class VarExpr extends Expr {
410
516
private static abstract class UnaryExpr extends Expr {
412
UnaryExpr(Expr s) { this.s = s; }
413
int numSubExprs() { return 1; }
414
528
Expr getSubExpr(int i) {
415
if (i == 0) return s;
416
532
return super.getSubExpr(i);
418
535
Object eval(EvalContext context) {
419
double v = ((Number)s.eval(context)).doubleValue();
536
double v = ((Number) s.eval(context)).doubleValue();
420
537
return Double.valueOf(apply(v));
422
540
abstract double apply(double v);
425
543
private static class UnaryOpExpr extends UnaryExpr {
426
545
private static final String opName = EvalSpice.Op.MINUS.name;
427
546
private static final int opPrecedence = MIN_PRECEDENCE;
428
548
UnaryOpExpr(Expr s) {
431
552
void appendText(StringBuilder sb) {
432
553
sb.append(opName);
433
554
s.appendText(sb, opPrecedence);
435
int precedence() { return opPrecedence; }
436
561
double apply(double v) {
441
566
private static class UnaryFunExpr extends UnaryExpr {
442
enum Fun { sin, abs, sqrt, int_;
443
@Override public String toString() {
570
sin, abs, sqrt, int_;
573
public String toString() {
444
574
return this == int_ ? "int" : super.toString();
447
577
private final Fun fun;
448
579
UnaryFunExpr(Fun fun, Expr s) {
452
584
void appendText(StringBuilder sb) {
455
587
s.appendText(sb, MAX_PRECEDENCE);
458
591
double apply(double v) {
460
case sin: return Math.sin(v);
461
case abs: return Math.abs(v);
462
case sqrt: return Math.sqrt(v);
463
case int_: return (int)v;
465
602
throw new AssertionError();
469
606
private static abstract class BinaryExpr extends Expr {
470
608
final Expr ls, rs;
471
BinaryExpr(Expr ls, Expr rs) { this.ls = ls; this.rs = rs; }
472
int numSubExprs() { return 2; }
610
BinaryExpr(Expr ls, Expr rs) {
473
619
Expr getSubExpr(int i) {
474
if (i == 0) return ls;
475
if (i == 1) return rs;
476
626
return super.getSubExpr(i);
478
629
Object eval(EvalContext context) {
479
double lv = ((Double)ls.eval(context)).doubleValue();
480
double rv = ((Double)rs.eval(context)).doubleValue();
630
double lv = ((Double) ls.eval(context)).doubleValue();
631
double rv = ((Double) rs.eval(context)).doubleValue();
481
632
return Double.valueOf(apply(lv, rv));
483
635
abstract double apply(double lv, double rv);
486
638
private static class BinaryOpExpr extends BinaryExpr {
487
640
private final EvalSpice.Op op;
488
642
BinaryOpExpr(Expr ls, EvalSpice.Op op, Expr rs) {
492
647
void appendText(StringBuilder sb) {
493
648
ls.appendText(sb, op.precedence);
494
649
sb.append(op.name);
495
650
rs.appendText(sb, op.precedence - 1);
497
int precedence() { return op.precedence; }
654
return op.precedence;
498
657
double apply(double lv, double rv) {
499
if (op == EvalSpice.Op.MULT) return lv * rv;
500
if (op == EvalSpice.Op.DIV) return lv / rv;
501
if (op == EvalSpice.Op.PLUS) return lv + rv;
502
if (op == EvalSpice.Op.MINUS) return lv - rv;
503
if (op == EvalSpice.Op.LT) return valueOf(lv < rv);
504
if (op == EvalSpice.Op.LTOE) return valueOf(lv <= rv);
505
if (op == EvalSpice.Op.GT) return valueOf(lv > rv);
506
if (op == EvalSpice.Op.GTOE) return valueOf(lv >= rv);
507
if (op == EvalSpice.Op.EQ) return valueOf(lv == rv);
508
if (op == EvalSpice.Op.NE) return valueOf(lv != rv);
509
if (op == EvalSpice.Op.LAND) return valueOf(bool(lv) && bool(rv));
510
if (op == EvalSpice.Op.LOR) return valueOf(bool(lv) || bool(rv));
658
if (op == EvalSpice.Op.MULT) {
661
if (op == EvalSpice.Op.DIV) {
664
if (op == EvalSpice.Op.PLUS) {
667
if (op == EvalSpice.Op.MINUS) {
670
if (op == EvalSpice.Op.LT) {
671
return valueOf(lv < rv);
673
if (op == EvalSpice.Op.LTOE) {
674
return valueOf(lv <= rv);
676
if (op == EvalSpice.Op.GT) {
677
return valueOf(lv > rv);
679
if (op == EvalSpice.Op.GTOE) {
680
return valueOf(lv >= rv);
682
if (op == EvalSpice.Op.EQ) {
683
return valueOf(lv == rv);
685
if (op == EvalSpice.Op.NE) {
686
return valueOf(lv != rv);
688
if (op == EvalSpice.Op.LAND) {
689
return valueOf(bool(lv) && bool(rv));
691
if (op == EvalSpice.Op.LOR) {
692
return valueOf(bool(lv) || bool(rv));
511
694
throw new AssertionError();
513
private static double valueOf(boolean b) { return b ? 1 : 0; }
697
private static double valueOf(boolean b) {
516
702
private static class BinaryFunExpr extends BinaryExpr {
517
enum Fun { min, max };
518
708
private final Fun fun;
519
710
BinaryFunExpr(Fun fun, Expr ls, Expr rs) {
523
715
void appendText(StringBuilder sb) {
528
720
rs.appendText(sb, MAX_PRECEDENCE);
531
724
double apply(double lv, double rv) {
533
case min: return Math.min(lv, rv);
534
case max: return Math.max(lv, rv);
727
return Math.min(lv, rv);
729
return Math.max(lv, rv);
536
731
throw new AssertionError();
540
735
private static class IfThenElseExpr extends Expr {
541
737
private static final int precedence = MAX_PRECEDENCE;
542
738
final Expr condS, thenS, elseS;
543
740
IfThenElseExpr(Expr condS, Expr thenS, Expr elseS) {
544
741
this.condS = condS;
545
742
this.thenS = thenS;
546
743
this.elseS = elseS;
548
int numSubExprs() { return 3; }
549
750
Expr getSubExpr(int i) {
550
if (i == 0) return condS;
551
if (i == 1) return thenS;
552
if (i == 2) return elseS;
553
760
return super.getSubExpr(i);
555
763
void appendText(StringBuilder sb) {
556
764
condS.appendText(sb, precedence - 1);