summaryrefslogtreecommitdiff
path: root/test/files
Commit message (Collapse)AuthorAgeFilesLines
...
* | | | | | Merge pull request #3806 from clhodapp/fix/SI-6967Adriaan Moors2014-06-253-31/+67
|\ \ \ \ \ \ | |_|_|/ / / |/| | | | | SI-6967 Fix ClassTag unapply for primitives
| * | | | | SI-6967 Fix ClassTag unapply for primitivesclhodapp2014-06-103-31/+67
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This commit fixes the behavior of ClassTag's Any-accepting unapply overload. Previously, ClassTag had overloads of unapply that accepted all of the Java primitive aliases (language-supported magic classes extending AnyVal), as well as an implementation that accepted an Any. All of the AnyVal-accepting (more specific) versions of the methods worked correctly. However, the Any-accepting version incorrectly handled these types. For example, ClassTag.Int.unapply(3) would return Some(3) (through the Int-accepting overload), while ClassTag.Int.unapply(3: Any) would return None (through the Any-accepting overload). This commit unifies these behaviors, making ClassTag.Int.unapply(3: Any) return Some(3). It accomplishes this by adding a pattern match on the type of that method's argument, which will delegate to one of the more-specifically-typed overloads if possible. It also improves the formatting of the code a bit. One thing to note (though I doubt anyone will ever do this based on this message) is that the AnyVal-subtype-accepting overloads should be removed in Scala 2.12, as they are unneeded. I placed a note to this effect into the code.
* | | | | | Merge pull request #3797 from retronym/topic/exhaust-compoundJason Zaugg2014-06-113-0/+45
|\ \ \ \ \ \ | | | | | | | | | | | | | | SI-8631 Treat `A with Sealed` as enumerable for pattern matching
| * | | | | | SI-8631 Treat `A with Sealed` as enumerable for pattern matchingJason Zaugg2014-06-103-0/+45
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Enumerate the subtypes of sealed parent types of refinement types, and filter those that conform to the refinement type. Such types can crop up easily when LUB-bing case classes which add `Product with Serializable` to the mix.
* | | | | | | Merge pull request #3781 from retronym/topic/8611Jason Zaugg2014-06-116-0/+94
|\ \ \ \ \ \ \ | | | | | | | | | | | | | | | | SI-8611 Avoid accidental patmat unification with refinement types
| * | | | | | | SI-8611 Avoid accidental patmat unification with refinement typesJason Zaugg2014-06-106-0/+94
| |/ / / / / / | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | In the enclosed test, t8611a.scala, the patterns `O.{A, B}` were incorrect treated as equivelent by the combination of `uniqueTpForTree` and `Const.uniqueTpForTree`. `uniqueTpForTree` used `Type#narrow` to try to create a distinct type for each new pattern tree it encountered. However, narrowing a `RefinedType` does not create a distinct type as we are used to when narrowing, e.g. a class type. // Type def narrow: Type = if (phase.erasedTypes) this else { val cowner = commonOwner(this) refinedType(this :: Nil, cowner, EmptyScope, cowner.pos).narrow } // CompoundType override def narrow: Type = typeSymbol.thisType This commit creates a fresh existential type symbol rather than trying to use `narrow`. I've included a unit test to show the sublteties of narrowing refinment types.
* | | | | | | Merge pull request #3777 from som-snytt/issue/5905-testJason Zaugg2014-06-101-3/+5
|\ \ \ \ \ \ \ | |/ / / / / / |/| | | | | | SI-5905 Clarify test case
| * | | | | | SI-5905 Clarify test caseSom Snytt2014-05-221-3/+5
| | |_|_|_|/ | |/| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The language feature options are discovered reflectively, but it is nice to enforce that expected options are supplied. Short of that, the code string includes a rowdy postfix operator. It still does enforce that at least one option was discovered.
* | | | | | Merge pull request #3815 from retronym/topic/java8-support-2Adriaan Moors2014-06-104-104/+31
|\ \ \ \ \ \ | | | | | | | | | | | | | | Java 8 agnostism for our test suite
| * | | | | | Support Java 8 in the checkfile for neg/t6289Jason Zaugg2014-06-041-1/+1
| | | | | | |
| * | | | | | Java 6-8 agnosticism for a testJason Zaugg2014-06-043-103/+30
| | |_|/ / / | |/| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Under Java 8, the output contains newly added methods in j.u.Iterator. I've created cut down, test-local versions of the relevant types to decouple.
* | | | | | Merge pull request #3818 from som-snytt/issue/repl-javap-app8Adriaan Moors2014-06-101-1/+24
|\ \ \ \ \ \ | | | | | | | | | | | | | | Java 8 support for run/repl-javap-app.check
| * | | | | | Java 8 support for run/repl-javap-app.checkSom Snytt2014-06-051-1/+24
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Just adding the java 8 output. No attempt to finesse anything. But the partest mechanism does still need auto-update of these conditional check files, plus expression evaluation of the condition.
* | | | | | | Merge pull request #3812 from retronym/merge/2.10.x-to-2.11.x-20140604Adriaan Moors2014-06-104-1/+31
|\ \ \ \ \ \ \ | |/ / / / / / |/| | | | | | Merge 2.10.x to 2.11.x
| * | | | | | Merge remote-tracking branch 'origin/2.10.x' into ↵Jason Zaugg2014-06-044-1/+31
| |\ \ \ \ \ \ | | |/ / / / / | |/| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | merge/2.10.x-to-2.11.x-20140604 Conflicts: src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
| | * | | | | SI-8596 Fix rangepos crasher with defaults, poly methodsJason Zaugg2014-05-294-1/+31
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Regressed in SI-7915 / 3009a525b5 We should be deriving the position of the synthetic `Select` from `basefun1`, rather than `basefun`. In the new, enclosed test, the difference amounts to: new Container().typeParamAndDefaultArg[Any]() `------------ basefun1 --------------' `----------------- basefun ---------------' For monomorphic methods, these are one and the same, which is why `presentation/t7915` was working. I've extended that test to a polymorphic method to check that hyperlink resolution works.
* | | | | | | Test: classfile reading during inlining works if there is dead codeLukas Rytz2014-06-052-0/+101
| | | | | | |
* | | | | | | Make test repl-javap-app independent of precise constant pool indicesLukas Rytz2014-06-042-6/+19
| | | | | | | | | | | | | | | | | | | | | | | | | | | | Allows the test to pass on both backends
* | | | | | | Tone down the noise in the output of t7974Lukas Rytz2014-06-042-30/+1
|/ / / / / / | | | | | | | | | | | | | | | | | | This makes it pass under -Ybackend:GenBCode
* | | | | | Merge pull request #3803 from xeno-by/ticket/8637Adriaan Moors2014-06-032-0/+9
|\ \ \ \ \ \ | | | | | | | | | | | | | | SI-8637 fixes toolbox phase corruption
| * | | | | | SI-8637 fixes toolbox phase corruptionEugene Burmako2014-05-302-0/+9
| | |_|_|_|/ | |/| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | It turns out, Toolbox.typecheck hasn't been properly re-initializing its state between requests. In particular, globalPhase was left untouched, which made the compiler think that it's past typer, and that in turn disabled implicits. This commit applies a symptomatic fix to this problem.
* | | | | | Merge pull request #3796 from som-snytt/issue/8630Adriaan Moors2014-06-032-0/+8
|\ \ \ \ \ \ | |_|_|_|/ / |/| | | | | SI-8630 lineToString no longer long by one at eof
| * | | | | SI-8630 lineToString no longer long by one at eofSom Snytt2014-05-272-0/+8
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | One more EOL crasher, or lack-of-EOL crasher, when the text is at EOF. It was not caught by the last round of excellent and thorough tests because ``` // If non-whitespace tokens run all the way up to EOF, // positions go wrong because the correct end of the last // token cannot be used as an index into the char array. // The least painful way to address this was to add a // newline to the array. ```
* | | | | | Merge pull request #3770 from retronym/ticket/8607Grzegorz Kossakowski2014-05-292-8/+41
|\ \ \ \ \ \ | | | | | | | | | | | | | | SI-8607 Fix erasure for value class inheriting from private class
| * | | | | | SI-8607 Generalize previous change to preEraseJason Zaugg2014-05-211-8/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | In the previous commit, we avoided an awkward chain of casts by exploiting the knowledge that Scala defined classes will by JVM accessible, and as such immune to `LinkageError`s when used as the target of a cast. This commit generalized this to the entire fix for SI-4283, rather than just for derived value classes.
| * | | | | | SI-8607 Fix erasure for value class inheriting from private classJason Zaugg2014-05-211-0/+36
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The fix for SI-4283 added a pre-emptive cast of the qualifier of a selection `qual.a` to avoid later casting to the owner of `a` if that owner might be inaccessible at the call site. This fixed a `LinkageError`. In the enclosed test, this cast led to the following diff in the tree shapes (with respect to a version with a public base class). [erasure] - new p1.C.<init>(c.$asInstanceOf[scala.this.Int]()).a(); + new p1.C.<init>(new p1.C.<init>(c.$asInstanceOf[scala.this.Int]()).$asInstanceOf[ErasedValueType( class C, scala.this.Int)]().$asInstanceOf[scala.this.Int]()).a(); [posterasure] - new p1.C.<init>(c).a(); + new p1.C.<init>(new p1.C.<init>(c).$asInstanceOf[scala.this.Int]().$asInstanceOf[scala.this.Int]()) .a(); () What we really wanted to end up with is: new p1.C.<init>(c).$asInstanceOf[C]().a(); The stray cast leads to the crash: error: should have been unboxed by erasure: new p1.C.<init>(c).$asInstanceOf[scala.this.Int]() Rather than trying to fix this in erasure/posterasure, this commit instead relies on the fact the owner of `a` cannot be Java defined if `qual`s type is a derived value class. This follows from the restrictions we place on value classes. With this knowledge, we elide the cast altogether in this case.
* | | | | | | Merge pull request #3791 from S11001001/ticket/8346Ichoran2014-05-292-0/+40
|\ \ \ \ \ \ \ | |_|/ / / / / |/| | | | | | SI-8346 Rebuild invariant sets in #toSet, avoiding CCE
| * | | | | | SI-8346: Rebuild invariant sets in #toSet, avoiding CCE.Stephen Compall2014-05-242-0/+40
| | |_|_|/ / | |/| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | SI-3953 caused several types of sets' operations to trivially throw `ClassCastException` after using inherited covariant #toSet method, by doing an unchecked cast that is only safe for intrinsically covariant set data structures like `HashSet`, but totally unsafe for others like `TreeSet` or `Enumeration.ValueSet`. This change moves the cast to the leaves of the class hierarchy where that is safe, and incidentally undeprecates overriding Set#toSet.
* | | | | | Merge pull request #3794 from lrytz/t8625Jason Zaugg2014-05-271-0/+5
|\ \ \ \ \ \ | | | | | | | | | | | | | | SI-8625 fix unreachability analysis for boolean expressions
| * | | | | | SI-8625 fix unreachability analysis for boolean expressionsLukas Rytz2014-05-271-0/+5
| | | | | | |
* | | | | | | Merge pull request #3782 from retronym/topic/opt-scopeJason Zaugg2014-05-275-0/+17
|\ \ \ \ \ \ \ | |/ / / / / / |/| | | | | | Compiler optimizations for Scopes, checkDoubleDefs, Namer
| * | | | | | Eliminate some N^2 performance in type checkingJason Zaugg2014-05-265-0/+17
| |/ / / / / | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Where N is the number of members of the enclosing package. Double definition errors for top level classes/objects are issued elsewhere, as demonstrated by the enclosed test. So we can omit the call to `checkNoDoubleDefs` in this content. We can't omit the call to `addSynthetics` for package class owners (case- and value-class synthetic companions are added here), but we can make the process cheaper by moving the expensive-but-usually-true call to `shouldAdd`. Here's an example of the improvement. % rm -rf /tmp/pkg; (for i in {1..50}; do for j in {1..100}; do echo "package pkg { class A_${i}_${j}___(val a: Int, val b: Int) }"; done; done) > sandbox/A1.scala && time scalac-hash v2.11.0 -Ybackend:GenASM -J-Xmx1G -J-XX:MaxPermSize=400M -d /tmp sandbox/A1.scala; real 0m49.762s user 1m12.376s sys 0m2.371s % rm -rf /tmp/pkg; (for i in {1..50}; do for j in {1..100}; do echo "package pkg { class A_${i}_${j}___(val a: Int, val b: Int) }"; done; done) > sandbox/A1.scala && time qbin/scalac -Ybackend:GenASM -J-Xmx1G -J-XX:MaxPermSize=400M -d /tmp sandbox/A1.scala; real 0m35.662s user 0m58.275s sys 0m2.355s We've still got another source of pathological performance in creating nested scopes that I'll fix in the next commit.
* / / / / / SI-8617 Avoid rangepos crash for OptManifest materializerJason Zaugg2014-05-242-0/+11
|/ / / / / | | | | | | | | | | | | | | | The tree to create a `NoManifest` was unpositioned.
* / / / / Upgrade ASM to 5.0.2Lukas Rytz2014-05-203-7/+37
|/ / / / | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This commit is a squashed version of all commits in PR #3747. For future upgrades, consult the README and check the commits in https://github.com/scala/scala/pull/3747/commits There's one bug in ASM 5.0.2 that breaks scalac: http://forge.ow2.org/tracker/?func=detail&aid=317200&group_id=23&atid=100023 This bug is fixed in ASM trunk, the patch has been merged into this commit. A future upgrade of ASM should contain the fix.
* | | | SI-8601 Test that static LOAD_FIELD is not eliminatedJason Zaugg2014-05-204-0/+21
| | | | | | | | | | | | | | | | | | | | This test fails under 2.11.0, and works now that DCE treats static loads as useful instructions.
* | | | SI-8601 Test that `null.synchronized` NPEs under -optimizeJason Zaugg2014-05-192-0/+9
| | | | | | | | | | | | | | | | As part of my sweep through the side-effecting byte code instructions.
* | | | SI-8601 Don't treat newarray as dead codeJason Zaugg2014-05-191-0/+3
| | | | | | | | | | | | | | | | Otherwise we lose the side effect of a `NegativeArraySizeException`.
* | | | Add a test for array loadJason Zaugg2014-05-191-1/+3
| | | |
* | | | SI-8601 Avoid over-eager optimization of LOAD_FIELDJason Zaugg2014-05-194-0/+40
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | It can NPE or trigger static class initilization, we can't elimiate it without changing semantics. To make sure we don't thwart closure elimination, I've allowed DCE to eliminate a non-static LOAD_FIELD of a member of a closure class. It would be more general to track nullity of the reciever (e.g, `this` or `new Foo` cannot be null), but that would require more infrastructure in this phase. I've added a test for closure inlining based on a a suggestion by @dragos. This actually passes if we remove the (LOAD_FIELD, DROP) peephole optimization for `closelim` altogether. But I chose to adapt that optimization (only allow it for non-static, closure fields), rather then remove it alogether, in the interests of treading lightly.
* | | | SI-8601 Don't treat int/long division, or arraylength, as dead-codeJason Zaugg2014-05-194-0/+26
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | `{i, l}div` and `{i, l}rem` throw an `ArithmeticException` if the divisor is 0. `arraylength` throws a `NullPointerException` on a null reference. JVM Spec: > The only integer operations that can throw an exception are the > integer divide instructions (idiv and ldiv) and the integer > remainder instructions (irem and lrem), which throw an > ArithmeticException if the divisor is zero. > The Java virtual machine's floating-point operators do not throw > runtime exceptions > If the arrayref is null, the arraylength instruction throws a > NullPointerException. I checked the other primitives in `ICode` to see if anything else should be considered as live code. Pure: // jvm : {i, l, f, d}neg case class Negation(kind: TypeKind) extends Primitive // jvm : if{eq, ne, lt, ge, le, gt}, if{null, nonnull} // if_icmp{eq, ne, lt, ge, le, gt}, if_acmp{eq,ne} case class Test(op: TestOp, kind: TypeKind, zero: Boolean) extends Primitive // jvm : lcmp, {f, d}cmp{l, g} case class Comparison(op: ComparisonOp, kind: TypeKind) extends Primitive Impure: {i, l}{div, rem}, otherwise pure // jvm : {i, l, f, d}{add, sub, mul, div, rem} case class Arithmetic(op: ArithmeticOp, kind: TypeKind) extends Primitive Pure (overflow is silent, NaN.toInt is defined): // jvm : {i, l}{and, or, xor} case class Logical(op: LogicalOp, kind: TypeKind) extends Primitive // jvm : {i, l}{shl, ushl, shr} case class Shift(op: ShiftOp, kind: TypeKind) extends Primitive // jvm : i2{l, f, d}, l2{i, f, d}, f2{i, l, d}, d2{i, l, f}, i2{b, c, s} case class Conversion(src: TypeKind, dst: TypeKind) extends Primitive Impure! May NPE! // jvm : arraylength case class ArrayLength(kind: TypeKind) extends Primitive Pure (we know that StringBuilder.{<init>, append, toString} are pure and `append` is null safe.) // jvm : It should call the appropiate 'append' method on StringBuffer case class StringConcat(el: TypeKind) extends Primitive // jvm: it should create a new StringBuffer case object StartConcat extends Primitive // jvm: convert StringBuffer to a String case object EndConcat extends Primitive
* | | | Revert "SI-8601 Don't treat int/long division, or arraylength, as dead-code"Adriaan Moors2014-05-194-26/+0
| | | | | | | | | | | | | | | | This reverts commit ee611cd76c29fedd416162e482c7ab3f15b831ca.
* | | | Revert "SI-8601 Avoid over-eager optimization of LOAD_FIELD"Adriaan Moors2014-05-192-13/+0
| | | | | | | | | | | | | | | | This reverts commit 0b432f9cd22b6e9770852e5b331a15f0534a312c.
* | | | Revert "Add a test for array load"Adriaan Moors2014-05-191-3/+1
| | | | | | | | | | | | | | | | This reverts commit 99b4ef8d8472f154d73160f5fe72daf081abb24e.
* | | | Revert "SI-8601 Don't treat newarray as dead code"Adriaan Moors2014-05-191-3/+0
| | | | | | | | | | | | | | | | This reverts commit 70b912a87433c9589af33e4f8b33dca39abb66e5.
* | | | Revert "SI-8601 Test that `null.synchronized` NPEs under -optimize"Adriaan Moors2014-05-192-9/+0
| | | | | | | | | | | | | | | | This reverts commit dcade51d751b389fb5137040f7e1006b4bc633c6.
* | | | SI-8601 Test that `null.synchronized` NPEs under -optimizeJason Zaugg2014-05-182-0/+9
| | | | | | | | | | | | | | | | As part of my sweep through the side-effecting byte code instructions.
* | | | SI-8601 Don't treat newarray as dead codeJason Zaugg2014-05-181-0/+3
| | | | | | | | | | | | | | | | Otherwise we lose the side effect of a `NegativeArraySizeException`.
* | | | Add a test for array loadJason Zaugg2014-05-181-1/+3
| | | |
* | | | SI-8601 Avoid over-eager optimization of LOAD_FIELDJason Zaugg2014-05-182-0/+13
| | | | | | | | | | | | | | | | | | | | It can NPE or trigger static class initilization, we can't elimiate it without changing semantics.
* | | | SI-8601 Don't treat int/long division, or arraylength, as dead-codeJason Zaugg2014-05-184-0/+26
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | `{i, l}div` and `{i, l}rem` throw an `ArithmeticException` if the divisor is 0. `arraylength` throws a `NullPointerException` on a null reference. JVM Spec: > The only integer operations that can throw an exception are the > integer divide instructions (idiv and ldiv) and the integer > remainder instructions (irem and lrem), which throw an > ArithmeticException if the divisor is zero. > The Java virtual machine's floating-point operators do not throw > runtime exceptions > If the arrayref is null, the arraylength instruction throws a > NullPointerException. I checked the other primitives in `ICode` to see if anything else should be considered as live code. Pure: // jvm : {i, l, f, d}neg case class Negation(kind: TypeKind) extends Primitive // jvm : if{eq, ne, lt, ge, le, gt}, if{null, nonnull} // if_icmp{eq, ne, lt, ge, le, gt}, if_acmp{eq,ne} case class Test(op: TestOp, kind: TypeKind, zero: Boolean) extends Primitive // jvm : lcmp, {f, d}cmp{l, g} case class Comparison(op: ComparisonOp, kind: TypeKind) extends Primitive Impure: {i, l}{div, rem}, otherwise pure // jvm : {i, l, f, d}{add, sub, mul, div, rem} case class Arithmetic(op: ArithmeticOp, kind: TypeKind) extends Primitive Pure (overflow is silent, NaN.toInt is defined): // jvm : {i, l}{and, or, xor} case class Logical(op: LogicalOp, kind: TypeKind) extends Primitive // jvm : {i, l}{shl, ushl, shr} case class Shift(op: ShiftOp, kind: TypeKind) extends Primitive // jvm : i2{l, f, d}, l2{i, f, d}, f2{i, l, d}, d2{i, l, f}, i2{b, c, s} case class Conversion(src: TypeKind, dst: TypeKind) extends Primitive Impure! May NPE! // jvm : arraylength case class ArrayLength(kind: TypeKind) extends Primitive Pure (we know that StringBuilder.{<init>, append, toString} are pure and `append` is null safe.) // jvm : It should call the appropiate 'append' method on StringBuffer case class StringConcat(el: TypeKind) extends Primitive // jvm: it should create a new StringBuffer case object StartConcat extends Primitive // jvm: convert StringBuffer to a String case object EndConcat extends Primitive