diff --git a/src/main/scala/leon/codegen/CodeGeneration.scala b/src/main/scala/leon/codegen/CodeGeneration.scala index dcea1804a8fcfe99214510334247ac01c8551aa4..7712ab0853b191cacc9ada6068c9db22c9e44d85 100644 --- a/src/main/scala/leon/codegen/CodeGeneration.scala +++ b/src/main/scala/leon/codegen/CodeGeneration.scala @@ -49,6 +49,7 @@ trait CodeGeneration { private[codegen] val BoxedIntClass = "java/lang/Integer" private[codegen] val BoxedBoolClass = "java/lang/Boolean" + private[codegen] val BoxedCharClass = "java/lang/Character" private[codegen] val BoxedArrayClass = "leon/codegen/runtime/ArrayBox" private[codegen] val TupleClass = "leon/codegen/runtime/Tuple" @@ -73,6 +74,8 @@ trait CodeGeneration { case BooleanType => "Z" + case CharType => "C" + case UnitType => "Z" case c : ClassType => @@ -100,6 +103,7 @@ trait CodeGeneration { def typeToJVMBoxed(tpe : TypeTree) : String = tpe match { case Int32Type => s"L$BoxedIntClass;" case BooleanType | UnitType => s"L$BoxedBoolClass;" + case CharType => s"L$BoxedCharClass;" case other => typeToJVM(other) } @@ -190,7 +194,7 @@ trait CodeGeneration { case Variable(id) => val slot = slotFor(id) val instr = id.getType match { - case Int32Type | BooleanType | UnitType => ILoad(slot) + case Int32Type | CharType | BooleanType | UnitType => ILoad(slot) case _ => ALoad(slot) } ch << instr @@ -205,7 +209,7 @@ trait CodeGeneration { mkExpr(d, ch) val slot = ch.getFreshVar val instr = i.getType match { - case Int32Type | BooleanType | UnitType => IStore(slot) + case Int32Type | CharType | BooleanType | UnitType => IStore(slot) case _ => AStore(slot) } ch << instr @@ -221,7 +225,7 @@ trait CodeGeneration { ch << InvokeVirtual(TupleClass, "get", "(I)Ljava/lang/Object;") mkUnbox(i.getType, ch) val instr = i.getType match { - case Int32Type | BooleanType | UnitType => IStore(s) + case Int32Type | CharType | BooleanType | UnitType => IStore(s) case _ => AStore(s) } ch << instr @@ -233,6 +237,9 @@ trait CodeGeneration { case IntLiteral(v) => ch << Ldc(v) + case CharLiteral(v) => + ch << Ldc(v) + case BooleanLiteral(v) => ch << Ldc(if(v) 1 else 0) @@ -512,6 +519,7 @@ trait CodeGeneration { mkExpr(i, ch) ch << (as.getType match { case Untyped => throw CompilationException("Cannot compile untyped array access.") + case CharType => CALOAD case Int32Type => IALOAD case BooleanType => BALOAD case _ => AALOAD @@ -522,6 +530,7 @@ trait CodeGeneration { ch << DUP ch << ARRAYLENGTH val storeInstr = a.getType match { + case ArrayType(CharType) => ch << NewArray.primitive("T_CHAR"); CASTORE case ArrayType(Int32Type) => ch << NewArray.primitive("T_INT"); IASTORE case ArrayType(BooleanType) => ch << NewArray.primitive("T_BOOLEAN"); BASTORE case ArrayType(other) => ch << NewArray(typeToJVM(other)); AASTORE @@ -544,6 +553,7 @@ trait CodeGeneration { case a @ FiniteArray(es) => ch << Ldc(es.size) val storeInstr = a.getType match { + case ArrayType(CharType) => ch << NewArray.primitive("T_CHAR"); CASTORE case ArrayType(Int32Type) => ch << NewArray.primitive("T_INT"); IASTORE case ArrayType(BooleanType) => ch << NewArray.primitive("T_BOOLEAN"); BASTORE case ArrayType(other) => ch << NewArray(typeToJVM(other)); AASTORE @@ -611,6 +621,11 @@ trait CodeGeneration { mkExpr(e, ch) ch << InvokeSpecial(BoxedBoolClass, constructorName, "(Z)V") + case CharType => + ch << New(BoxedCharClass) << DUP + mkExpr(e, ch) + ch << InvokeSpecial(BoxedCharClass, constructorName, "(C)V") + case at @ ArrayType(et) => ch << New(BoxedArrayClass) << DUP mkExpr(e, ch) @@ -631,6 +646,9 @@ trait CodeGeneration { case BooleanType | UnitType => ch << New(BoxedBoolClass) << DUP_X1 << SWAP << InvokeSpecial(BoxedBoolClass, constructorName, "(Z)V") + case CharType => + ch << New(BoxedCharClass) << DUP_X1 << SWAP << InvokeSpecial(BoxedCharClass, constructorName, "(C)V") + case at @ ArrayType(et) => ch << New(BoxedArrayClass) << DUP_X1 << SWAP << InvokeSpecial(BoxedArrayClass, constructorName, "(%s)V".format(typeToJVM(at))) case _ => @@ -646,6 +664,9 @@ trait CodeGeneration { case BooleanType | UnitType => ch << CheckCast(BoxedBoolClass) << InvokeVirtual(BoxedBoolClass, "booleanValue", "()Z") + case CharType => + ch << CheckCast(BoxedCharClass) << InvokeVirtual(BoxedCharClass, "charValue", "()C") + case ct : ClassType => val (cn, _) = leonClassToJVMInfo(ct.classDef).getOrElse { throw new CompilationException("Unsupported class type : " + ct) @@ -705,7 +726,7 @@ trait CodeGeneration { mkExpr(l, ch) mkExpr(r, ch) l.getType match { - case Int32Type | BooleanType | UnitType => + case Int32Type | BooleanType | UnitType | CharType => ch << If_ICmpEq(thenn) << Goto(elze) case _ => @@ -834,7 +855,7 @@ trait CodeGeneration { ch << Label(initLabel) // return lzy //newValue lzy.returnType match { - case Int32Type | BooleanType | UnitType => + case Int32Type | BooleanType | UnitType | CharType => // Since the underlying field only has boxed types, we have to unbox them to return them mkUnbox(lzy.returnType, ch)(NoLocals(isStatic)) ch << IRETURN diff --git a/src/main/scala/leon/purescala/TreeOps.scala b/src/main/scala/leon/purescala/TreeOps.scala index 7b70def5ddc490c87234e79c73e2edb2627ea512..a98519e19f742899d8c95bf85dd6091ba6278a85 100644 --- a/src/main/scala/leon/purescala/TreeOps.scala +++ b/src/main/scala/leon/purescala/TreeOps.scala @@ -790,6 +790,7 @@ object TreeOps { */ def simplestValue(tpe: TypeTree) : Expr = tpe match { case Int32Type => IntLiteral(0) + case CharType => CharLiteral('a') case BooleanType => BooleanLiteral(false) case SetType(baseType) => FiniteSet(Set()).setType(tpe) case MapType(fromType, toType) => FiniteMap(Seq()).setType(tpe)