diff --git a/src/main/scala/leon/codegen/CompilationUnit.scala b/src/main/scala/leon/codegen/CompilationUnit.scala index 1cba6447720086c5560e5c7366b4d1b37dd48528..1a56b8cfa3921576e57c7a2a5667e335937bc783 100644 --- a/src/main/scala/leon/codegen/CompilationUnit.scala +++ b/src/main/scala/leon/codegen/CompilationUnit.scala @@ -12,6 +12,8 @@ import cafebabe.ByteCodes._ import cafebabe.ClassFileTypes._ import cafebabe.Flags._ +import scala.collection.JavaConverters._ + import CodeGeneration._ class CompilationUnit(val program: Program, val classes: Map[Definition, ClassFile], implicit val env: CompilationEnvironment) { @@ -33,8 +35,19 @@ class CompilationUnit(val program: Program, val classes: Map[Definition, ClassFi _nextExprId } - private[codegen] def valueToJVM(e: Expr): Any = { - compileExpression(e, Seq()).evalToJVM(Seq()) + // Currently, this method is only used to prepare arguments to reflective calls. + // This means it is safe to return AnyRef (and never native values), because + // reflection needs this anyway. + private[codegen] def valueToJVM(e: Expr): AnyRef = e match { + case IntLiteral(v) => + new java.lang.Integer(v) + + case BooleanLiteral(v) => + new java.lang.Boolean(v) + + // just slightly overkill... + case _ => + compileExpression(e, Seq()).evalToJVM(Seq()) } private[codegen] def jvmToValue(e: AnyRef): Expr = e match { @@ -58,10 +71,12 @@ class CompilationUnit(val program: Program, val classes: Map[Definition, ClassFi val elems = for (i <- 0 until tpl.getArity) yield { jvmToValue(tpl.get(i)) } - Tuple(elems) - case _ => + case set : runtime.Set => + FiniteSet(set.getElements().asScala.map(jvmToValue).toSeq) + + case _ => throw CompilationException("MEH Unsupported return value : " + e.getClass) } @@ -103,7 +118,7 @@ class CompilationUnit(val program: Program, val classes: Map[Definition, ClassFi case Int32Type | BooleanType => ch << IRETURN - case UnitType | TupleType(_) | SetType(_) | MapType(_, _) | AbstractClassType(_) | CaseClassType(_) => + case UnitType | TupleType(_) | SetType(_) | MapType(_, _) | AbstractClassType(_) | CaseClassType(_) => ch << ARETURN case other => @@ -130,7 +145,7 @@ object CompilationUnit { for (c <- children) { classes += c -> compileCaseClassDef(p, c) } - } + } val mainClassName = defToJVMName(p, p.mainObject) val cf = new ClassFile(mainClassName, None) @@ -160,7 +175,7 @@ object CompilationUnit { METHOD_ACC_FINAL | METHOD_ACC_STATIC ).asInstanceOf[U2]) - + compileFunDef(funDef, m.codeHandler) } diff --git a/src/test/scala/leon/test/codegen/CodeGenEvaluation.scala b/src/test/scala/leon/test/codegen/CodeGenEvaluation.scala index 0e31b07532ea585f807434d75c4bc47e132d0ce9..20f41f6412721f236f03ee7b703187004c71b9c1 100644 --- a/src/test/scala/leon/test/codegen/CodeGenEvaluation.scala +++ b/src/test/scala/leon/test/codegen/CodeGenEvaluation.scala @@ -145,4 +145,48 @@ object Prog002 { assert(javaEval(unit)(expr1) === CaseClass(ccCons, Seq(IntLiteral(0), CaseClass(ccCons, Seq(IntLiteral(1), CaseClass(ccNil, Seq())))))) } + forProgram("Set Evaluation")( + """ +object Sets { + def s0() : Set[Int] = Set() + def s1() : Set[Int] = Set(1, 2, 3) + def s2() : Set[Int] = Set(2, 4, 6) + def s3() : Set[Int] = s1() ++ s2() + def s4() : Set[Int] = s2() ++ s1() + def s5() : Set[Int] = s1() ** s2() + def s6() : Set[Int] = s2() ** s1() + def s7() : Set[Int] = s1() -- s2() + def s8() : Set[Int] = s2() -- s1() +} + """ + ){ out => + assert(out.result.isDefined === true) + val unit = out.result.get + + def asIntSet(e : Expr) : Option[Set[Int]] = e match { + case EmptySet(_) => Some(Set.empty) + case FiniteSet(es) => + val ois = es.map(_ match { + case IntLiteral(v) => Some(v) + case _ => None + }) + if(ois.forall(_.isDefined)) + Some(ois.map(_.get).toSet) + else + None + case _ => None + } + + def eval(f : String) : Option[Set[Int]] = asIntSet(javaEval(unit)(FunctionInvocation(getFunction(unit, f), Seq()))) + + assert(eval("s0") === Some(Set.empty[Int])) + assert(eval("s1") === Some(Set(1, 2, 3))) + assert(eval("s2") === Some(Set(2, 4, 6))) + assert(eval("s3") === Some(Set(1, 2, 3, 4, 6))) + assert(eval("s4") === Some(Set(2, 4, 6, 1, 3))) + assert(eval("s5") === Some(Set(2))) + assert(eval("s6") === Some(Set(2))) + assert(eval("s7") === Some(Set(1, 3))) + assert(eval("s8") === Some(Set(4, 6))) + } }