From 25a5d2c76c533527244471595b06e6fd08559450 Mon Sep 17 00:00:00 2001 From: ravi <ravi.kandhadai@epfl.ch> Date: Tue, 19 Apr 2016 17:31:32 +0200 Subject: [PATCH] Fixing extraction of lambda applications with zero arguments --- .../leon/frontends/scalac/ASTExtractors.scala | 89 +++++++++---------- .../frontends/scalac/CodeExtraction.scala | 32 +++---- 2 files changed, 54 insertions(+), 67 deletions(-) diff --git a/src/main/scala/leon/frontends/scalac/ASTExtractors.scala b/src/main/scala/leon/frontends/scalac/ASTExtractors.scala index 1d107703b..45ddea6ad 100644 --- a/src/main/scala/leon/frontends/scalac/ASTExtractors.scala +++ b/src/main/scala/leon/frontends/scalac/ASTExtractors.scala @@ -53,7 +53,7 @@ trait ASTExtractors { protected lazy val bigIntSym = classFromName("scala.math.BigInt") protected lazy val stringSym = classFromName("java.lang.String") protected def functionTraitSym(i:Int) = { - require(1 <= i && i <= 22) + require(0 <= i && i <= 22) classFromName("scala.Function" + i) } @@ -64,7 +64,7 @@ trait ASTExtractors { def isBigIntSym(sym : Symbol) : Boolean = getResolvedTypeSym(sym) == bigIntSym - def isStringSym(sym : Symbol) : Boolean = getResolvedTypeSym(sym) match { case `stringSym` => true case _ => false } + def isStringSym(sym : Symbol) : Boolean = getResolvedTypeSym(sym) match { case `stringSym` => true case _ => false } def isByNameSym(sym : Symbol) : Boolean = getResolvedTypeSym(sym) == byNameSym @@ -101,28 +101,26 @@ trait ASTExtractors { getResolvedTypeSym(sym) == scalaMapSym } - def isOptionClassSym(sym : Symbol) : Boolean = { sym == optionClassSym || sym == someClassSym } def isFunction(sym : Symbol, i: Int) : Boolean = - 1 <= i && i <= 22 && sym == functionTraitSym(i) - + 0 <= i && i <= 22 && sym == functionTraitSym(i) def isArrayClassSym(sym: Symbol): Boolean = sym == arraySym - def hasIntType(t : Tree) = { + def hasIntType(t : Tree) = { val tpe = t.tpe.widen tpe =:= IntClass.tpe } def hasBigIntType(t : Tree) = isBigIntSym(t.tpe.typeSymbol) - + def hasStringType(t : Tree) = isStringSym(t.tpe.typeSymbol) def hasRealType(t : Tree) = isRealSym(t.tpe.typeSymbol) - + /** A set of helpers for extracting trees.*/ object ExtractorHelpers { /** Extracts the identifier as `"Ident(name)"` (who needs this?!) */ @@ -215,8 +213,7 @@ trait ASTExtractors { case _ => None } } - - + /** Matches the `A computes B` expression at the end of any expression A, and returns (A, B).*/ object ExComputesExpression { def unapply(tree: Apply) : Option[(Tree, Tree)] = tree match { @@ -227,7 +224,7 @@ trait ASTExtractors { case _ => None } } - + /** Matches the `O ask I` expression at the end of any expression O, and returns (I, O).*/ object ExAskExpression { def unapply(tree: Apply) : Option[(Tree, Tree)] = tree match { @@ -238,7 +235,7 @@ trait ASTExtractors { case _ => None } } - + object ExByExampleExpression { def unapply(tree: Apply) : Option[(Tree, Tree)] = tree match { case Apply(TypeApply(ExSelected("leon", "lang", "package", "byExample"), List(_, _)), input :: res_output :: Nil) @@ -246,19 +243,19 @@ trait ASTExtractors { case _ => None } } - + /** Extracts the `(input, output) passes { case In => Out ...}` and returns (input, output, list of case classes) */ - object ExPasses { + object ExPasses { def unapply(tree : Apply) : Option[(Tree, Tree, List[CaseDef])] = tree match { case Apply( Select( Apply( TypeApply( - ExSelected("leon", "lang", "package", "Passes"), + ExSelected("leon", "lang", "package", "Passes"), List(_, _) ), List(ExpressionExtractors.ExTuple(_, Seq(in,out))) - ), + ), ExNamed("passes") ), List(Function( @@ -271,11 +268,10 @@ trait ASTExtractors { } } - /** Returns a string literal from a constant string literal. */ object ExStringLiteral { def unapply(tree: Tree): Option[String] = tree match { - case Literal(c @ Constant(i)) if c.tpe == StringClass.tpe => + case Literal(c @ Constant(i)) if c.tpe == StringClass.tpe => Some(c.stringValue) case _ => None @@ -312,7 +308,7 @@ trait ASTExtractors { None } } - + /** Matches Real(x) when n is an integer and returns x */ object ExRealIntLiteral { def unapply(tree: Tree): Option[Tree] = tree match { @@ -409,8 +405,8 @@ trait ASTExtractors { //impl.children foreach println val symbols = impl.children.collect { - case df@DefDef(_, name, _, _, _, _) if - df.symbol.isAccessor && df.symbol.isParamAccessor + case df@DefDef(_, name, _, _, _, _) if + df.symbol.isAccessor && df.symbol.isParamAccessor && !name.endsWith("_$eq") => df.symbol } //println("symbols: " + symbols) @@ -439,16 +435,16 @@ trait ASTExtractors { } } } - + object ExCompanionObjectSynthetic { def unapply(cd : ClassDef) : Option[(String, Symbol, Template)] = { - val sym = cd.symbol + val sym = cd.symbol cd match { case ClassDef(_, name, tparams, impl) if sym.isModule && sym.isSynthetic => //FIXME flags? Some((name.toString, sym, impl)) case _ => None } - + } } @@ -477,7 +473,7 @@ trait ASTExtractors { } object ExFunctionDef { - /** Matches a function with a single list of arguments, + /** Matches a function with a single list of arguments, * and regardless of its visibility. */ def unapply(dd: DefDef): Option[(Symbol, Seq[Symbol], Seq[ValDef], Type, Tree)] = dd match { @@ -501,7 +497,7 @@ trait ASTExtractors { object ExLazyAccessorFunction { def unapply(dd: DefDef): Option[(Symbol, Type, Tree)] = dd match { case DefDef(_, name, tparams, vparamss, tpt, rhs) if( - vparamss.size <= 1 && name != nme.CONSTRUCTOR && + vparamss.size <= 1 && name != nme.CONSTRUCTOR && !dd.symbol.isSynthetic && dd.symbol.isAccessor && dd.symbol.isLazy ) => Some((dd.symbol, tpt.tpe, rhs)) @@ -512,7 +508,7 @@ trait ASTExtractors { object ExMutatorAccessorFunction { def unapply(dd: DefDef): Option[(Symbol, Seq[Symbol], Seq[ValDef], Type, Tree)] = dd match { case DefDef(_, name, tparams, vparamss, tpt, rhs) if( - vparamss.size <= 1 && name != nme.CONSTRUCTOR && + vparamss.size <= 1 && name != nme.CONSTRUCTOR && !dd.symbol.isSynthetic && dd.symbol.isAccessor && name.endsWith("_$eq") ) => Some((dd.symbol, tparams.map(_.symbol), vparamss.flatten, tpt.tpe, rhs)) @@ -527,7 +523,7 @@ trait ASTExtractors { vd match { // Implemented fields case ValDef(mods, name, tpt, rhs) if ( - !sym.isCaseAccessor && !sym.isParamAccessor && + !sym.isCaseAccessor && !sym.isParamAccessor && !sym.isLazy && !sym.isSynthetic && !sym.isAccessor && sym.isVar ) => println("matched a var accessor field: sym is: " + sym) @@ -538,7 +534,7 @@ trait ASTExtractors { } } } - + object ExFieldDef { /** Matches a definition of a strict field inside a class constructor */ def unapply(vd: SymTree) : Option[(Symbol, Type, Tree)] = { @@ -546,7 +542,7 @@ trait ASTExtractors { vd match { // Implemented fields case ValDef(mods, name, tpt, rhs) if ( - !sym.isCaseAccessor && !sym.isParamAccessor && + !sym.isCaseAccessor && !sym.isParamAccessor && !sym.isLazy && !sym.isSynthetic && !sym.isAccessor && !sym.isVar ) => // Since scalac uses the accessor symbol all over the place, we pass that instead: @@ -561,10 +557,10 @@ trait ASTExtractors { } } } - + object ExLazyFieldDef { /** Matches lazy field definitions. - * WARNING: Do NOT use this as extractor for lazy fields, + * WARNING: Do NOT use this as extractor for lazy fields, * as it does not contain the body of the lazy definition. * It is here just to signify a Definition acceptable by Leon */ @@ -572,16 +568,16 @@ trait ASTExtractors { val sym = vd.symbol vd match { case ValDef(mods, name, tpt, rhs) if ( - sym.isLazy && !sym.isCaseAccessor && !sym.isParamAccessor && - !sym.isSynthetic && !sym.isAccessor - ) => + sym.isLazy && !sym.isCaseAccessor && !sym.isParamAccessor && + !sym.isSynthetic && !sym.isAccessor + ) => // Since scalac uses the accessor symbol all over the place, we pass that instead: true case _ => false } } } - + object ExFieldAccessorFunction{ /** Matches the accessor function of a field * WARNING: This is not meant to be used for any useful purpose, @@ -589,7 +585,7 @@ trait ASTExtractors { */ def unapply(dd: DefDef): Boolean = dd match { case DefDef(_, name, tparams, vparamss, tpt, rhs) if( - vparamss.size <= 1 && name != nme.CONSTRUCTOR && + vparamss.size <= 1 && name != nme.CONSTRUCTOR && dd.symbol.isAccessor && !dd.symbol.isLazy ) => true @@ -603,8 +599,8 @@ trait ASTExtractors { val sym = dd.symbol dd match { case DefDef(_, name, tparams, vparamss, tpt, rhs) if( - vparamss.size <= 1 && name != nme.CONSTRUCTOR && sym.isSynthetic - ) => + vparamss.size <= 1 && name != nme.CONSTRUCTOR && sym.isSynthetic + ) => // Split the name into pieces, to find owner of the parameter + param.index // Form has to be <owner name>$default$<param index> @@ -617,13 +613,13 @@ trait ASTExtractors { Some((sym, tparams.map(_.symbol), vparamss.headOption.getOrElse(Nil), tpt.tpe, ownerString, index, rhs)) } catch { case _ : NumberFormatException | _ : IllegalArgumentException | _ : ArrayIndexOutOfBoundsException => - None + None } - + case _ => None } } - } + } } @@ -714,7 +710,6 @@ trait ASTExtractors { } } - object ExValDef { /** Extracts val's in the head of blocks. */ def unapply(tree: ValDef): Option[(Symbol,Tree,Tree)] = tree match { @@ -928,7 +923,7 @@ trait ASTExtractors { case _ => None } } - + object ExOr { def unapply(tree: Apply): Option[(Tree,Tree)] = tree match { case Apply(s @ Select(lhs, _), List(rhs)) if s.symbol == Boolean_or => @@ -936,14 +931,14 @@ trait ASTExtractors { case _ => None } } - + object ExNot { def unapply(tree: Select): Option[Tree] = tree match { case Select(t, n) if n == nme.UNARY_! => Some(t) case _ => None } } - + object ExEquals { def unapply(tree: Apply): Option[(Tree,Tree)] = tree match { case Apply(Select(lhs, n), List(rhs)) if n == nme.EQ => Some((lhs,rhs)) @@ -1079,7 +1074,7 @@ trait ASTExtractors { } } - object ExCall { + object ExCall { def unapply(tree: Tree): Option[(Tree, Symbol, Seq[Tree], Seq[Tree])] = tree match { // foo / foo[T] case ExParameterLessCall(t, s, tps) => diff --git a/src/main/scala/leon/frontends/scalac/CodeExtraction.scala b/src/main/scala/leon/frontends/scalac/CodeExtraction.scala index 4efc43706..dfab2acc8 100644 --- a/src/main/scala/leon/frontends/scalac/CodeExtraction.scala +++ b/src/main/scala/leon/frontends/scalac/CodeExtraction.scala @@ -304,7 +304,6 @@ trait CodeExtraction extends ASTExtractors { case d if d.symbol.isVar => None - // Everything else is unexpected case tree => println(tree) @@ -455,10 +454,8 @@ trait CodeExtraction extends ASTExtractors { } } - private var paramsToDefaultValues = Map[Symbol,FunDef]() - def getClassDef(sym: Symbol, pos: Position): LeonClassDef = { classesToClasses.get(sym) match { case Some(cd) => cd @@ -594,7 +591,7 @@ trait CodeExtraction extends ASTExtractors { def computeChains(tpe: LeonType): Map[TypeParameterDef, Set[LeonClassDef]] = { var seen: Set[LeonClassDef] = Set.empty var chains: Map[TypeParameterDef, Set[LeonClassDef]] = Map.empty - + def rec(tpe: LeonType): Set[LeonClassDef] = tpe match { case ct: ClassType => val root = ct.classDef.root @@ -651,7 +648,6 @@ trait CodeExtraction extends ASTExtractors { isMethod += fsym val fd = defineFunDef(fsym, Some(cd))(defCtx) - methodToClass += fd -> cd cd.registerMethod(fd) @@ -1031,7 +1027,7 @@ trait CodeExtraction extends ASTExtractors { case ExBooleanLiteral(b) => (LiteralPattern(binder, BooleanLiteral(b)), dctx) case ExUnitLiteral() => (LiteralPattern(binder, UnitLiteral()), dctx) case ExStringLiteral(s) => (LiteralPattern(binder, StringLiteral(s)), dctx) - + case up@ExUnapplyPattern(s, args) => implicit val p: Position = NoPosition val fd = getFunDef(s, up.pos) @@ -1133,27 +1129,27 @@ trait CodeExtraction extends ASTExtractors { case t @ ExComputesExpression(body, expected) => val b = extractTreeOrNoTree(body).setPos(body.pos) val expected_expr = extractTreeOrNoTree(expected).setPos(expected.pos) - + val resId = FreshIdentifier("res", b.getType).setPos(current.pos) val post = Lambda(Seq(LeonValDef(resId)), Equals(Variable(resId), expected_expr)).setPos(current.pos) Ensuring(b, post) - + case t @ ExByExampleExpression(input, output) => val input_expr = extractTreeOrNoTree(input).setPos(input.pos) val output_expr = extractTreeOrNoTree(output).setPos(output.pos) Passes(input_expr, output_expr, MatchCase(WildcardPattern(None), Some(BooleanLiteral(false)), NoTree(output_expr.getType))::Nil) - + case t @ ExAskExpression(input, output) => val input_expr = extractTreeOrNoTree(input).setPos(input.pos) val output_expr = extractTreeOrNoTree(output).setPos(output.pos) - + val resId = FreshIdentifier("res", output_expr.getType).setPos(current.pos) val post = Lambda(Seq(LeonValDef(resId)), Passes(input_expr, Variable(resId), MatchCase(WildcardPattern(None), Some(BooleanLiteral(false)), NoTree(output_expr.getType))::Nil)).setPos(current.pos) Ensuring(output_expr, post) - + case ExAssertExpression(contract, oerr) => val const = extractTree(contract) val b = rest.map(extractTreeOrNoTree).getOrElse(UnitLiteral()) @@ -1243,7 +1239,6 @@ trait CodeExtraction extends ASTExtractors { rest = None Let(newID, valTree, restTree) - case d @ ExFunctionDef(sym, tparams, params, ret, b) => val fd = defineFunDef(sym) @@ -1258,13 +1253,13 @@ trait CodeExtraction extends ASTExtractors { case None => UnitLiteral() } rest = None - + val oldCurrentFunDef = currentFunDef val funDefWithBody = extractFunBody(fd, params, b)(newDctx) currentFunDef = oldCurrentFunDef - + val (other_fds, block) = restTree match { case LetDef(fds, block) => (fds, block) @@ -1426,7 +1421,6 @@ trait CodeExtraction extends ASTExtractors { WithOracle(newOracles, cBody) - case chs @ ExChooseExpression(body) => val cBody = extractTree(body) Choose(cBody) @@ -1630,7 +1624,7 @@ trait CodeExtraction extends ASTExtractors { case ExImplies(lhs, rhs) => Implies(extractTree(lhs), extractTree(rhs)).setPos(current.pos) - + case c @ ExCall(rec, sym, tps, args) => // The object on which it is called is null if the symbol sym is a valid function in the scope and not a method. val rrec = rec match { @@ -1846,7 +1840,6 @@ trait CodeExtraction extends ASTExtractors { case (IsTyped(a1, at: ArrayType), "clone", Nil) => a1 - // Map methods case (IsTyped(a1, MapType(_, vt)), "apply", List(a2)) => MapApply(a1, a2) @@ -1900,7 +1893,6 @@ trait CodeExtraction extends ASTExtractors { case (IsTyped(a1, CharType), "<=", List(IsTyped(a2, CharType))) => LessEquals(a1, a2) - case (a1, name, a2) => val typea1 = a1.getType val typea2 = a2.map(_.getType).mkString(",") @@ -1951,7 +1943,7 @@ trait CodeExtraction extends ASTExtractors { case TypeRef(_, sym, _) if isRealSym(sym) => RealType - + case TypeRef(_, sym, _) if isStringSym(sym) => StringType @@ -1986,7 +1978,7 @@ trait CodeExtraction extends ASTExtractors { ArrayType(extractType(btt)) // TODO: What about Function0? - case TypeRef(_, sym, subs) if subs.size > 1 && isFunction(sym, subs.size - 1) => + case TypeRef(_, sym, subs) if subs.size >= 1 && isFunction(sym, subs.size - 1) => val from = subs.init val to = subs.last FunctionType(from map extractType, extractType(to)) -- GitLab