From fa6e5ee1b5bbbd87212105c8ffba289ce7f7896f Mon Sep 17 00:00:00 2001 From: Etienne Kneuss <etienne.kneuss@epfl.ch> Date: Thu, 9 Oct 2014 13:44:54 +0200 Subject: [PATCH] List literals --- library/collection/List.scala | 5 +++ .../leon/frontends/scalac/ASTExtractors.scala | 11 +++++++ .../frontends/scalac/CodeExtraction.scala | 9 ++++++ .../scala/leon/purescala/PrettyPrinter.scala | 31 +++++++++++++------ src/main/scala/leon/purescala/TreeOps.scala | 12 +++---- 5 files changed, 52 insertions(+), 16 deletions(-) diff --git a/library/collection/List.scala b/library/collection/List.scala index 521a573a1..26355f8e7 100644 --- a/library/collection/List.scala +++ b/library/collection/List.scala @@ -287,6 +287,11 @@ sealed abstract class List[T] { } +@ignore +object List { + def apply[T](elems: T*): List[T] = ??? +} + @library object ListOps { def flatten[T](ls: List[List[T]]): List[T] = ls match { diff --git a/src/main/scala/leon/frontends/scalac/ASTExtractors.scala b/src/main/scala/leon/frontends/scalac/ASTExtractors.scala index 559dc93a0..00f039d29 100644 --- a/src/main/scala/leon/frontends/scalac/ASTExtractors.scala +++ b/src/main/scala/leon/frontends/scalac/ASTExtractors.scala @@ -164,6 +164,17 @@ trait ASTExtractors { } } + object ExListLiteral { + def unapply(tree: Apply): Option[(Type, List[Tree])] = tree match { + case Apply( + TypeApply(ExSelected("leon", "collection", "List", "apply"), tpe :: Nil), + args) => + Some((tpe.tpe, args)) + case _ => + None + } + } + object ExAssertExpression { /** Extracts the 'assert' contract from an expression (only if it's the * first call in the block). */ diff --git a/src/main/scala/leon/frontends/scalac/CodeExtraction.scala b/src/main/scala/leon/frontends/scalac/CodeExtraction.scala index 40e3a6117..b79616a39 100644 --- a/src/main/scala/leon/frontends/scalac/CodeExtraction.scala +++ b/src/main/scala/leon/frontends/scalac/CodeExtraction.scala @@ -1378,6 +1378,15 @@ trait CodeExtraction extends ASTExtractors { ArrayUpdated(rar, rk, rv) + case l @ ExListLiteral(tpe, elems) => + val rtpe = extractType(l) + val cons = CaseClassType(libraryCaseClass(l.pos, "leon.collection.Cons"), Seq(rtpe)); + val nil = CaseClassType(libraryCaseClass(l.pos, "leon.collection.Nil"), Seq(rtpe)); + + elems.foldRight(CaseClass(nil, Seq())) { + case (e, ls) => CaseClass(cons, Seq(extractTree(e), ls)) + } + case chr @ ExCharLiteral(c) => CharLiteral(c) diff --git a/src/main/scala/leon/purescala/PrettyPrinter.scala b/src/main/scala/leon/purescala/PrettyPrinter.scala index a00e2d245..fca74d262 100644 --- a/src/main/scala/leon/purescala/PrettyPrinter.scala +++ b/src/main/scala/leon/purescala/PrettyPrinter.scala @@ -13,7 +13,8 @@ import utils._ import java.lang.StringBuffer import PrinterHelpers._ -import TreeOps.isStringLiteral +import TreeOps.{isStringLiteral, isListLiteral} +import TypeTreeOps.leastUpperBound case class PrinterContext( current: Tree, @@ -230,17 +231,27 @@ class PrettyPrinter(opts: PrinterOptions, val sb: StringBuffer = new StringBuffe p"""|?($es)""" } case e @ CaseClass(cct, args) => - - isStringLiteral(e) match { - case Some(str) => - val q = '"'; - p"$q$str$q" + isListLiteral(e) match { + case Some((tpe, elems)) => + val elemTps = leastUpperBound(elems.map(_.getType)) + if (elemTps == Some(tpe)) { + p"List($elems)" + } else { + p"List[$tpe]($elems)" + } case None => - if (cct.classDef.isCaseObject) { - p"$cct" - } else { - p"$cct($args)" + isStringLiteral(e) match { + case Some(str) => + val q = '"'; + p"$q$str$q" + + case None => + if (cct.classDef.isCaseObject) { + p"$cct" + } else { + p"$cct($args)" + } } } diff --git a/src/main/scala/leon/purescala/TreeOps.scala b/src/main/scala/leon/purescala/TreeOps.scala index a98519e19..8e8b831ec 100644 --- a/src/main/scala/leon/purescala/TreeOps.scala +++ b/src/main/scala/leon/purescala/TreeOps.scala @@ -1995,8 +1995,8 @@ object TreeOps { val lib = inProgram(cct.classDef).library if (Some(cct.classDef) == lib.String) { - listLiteralToList(args(0)) match { - case Some(chars) => + isListLiteral(args(0)) match { + case Some((_, chars)) => val str = chars.map { case CharLiteral(c) => Some(c) case _ => None @@ -2018,15 +2018,15 @@ object TreeOps { None } - def listLiteralToList(e: Expr): Option[List[Expr]] = e match { + def isListLiteral(e: Expr): Option[(TypeTree, List[Expr])] = e match { case CaseClass(cct, args) => val lib = inProgram(cct.classDef).library if (Some(cct.classDef) == lib.Nil) { - Some(Nil) + Some((cct.tps.head, Nil)) } else if (Some(cct.classDef) == lib.Cons) { - listLiteralToList(args(1)).map { t => - args(0) :: t + isListLiteral(args(1)).map { case (_, t) => + (cct.tps.head, args(0) :: t) } } else { None -- GitLab