2017-04-14 2 views
0

ich die folgenden vereinfachten Definition einer Additionsoperation über ein Feld habe:definiert Infixoperator in Welder

import inox._ 
import inox.trees.{forall => _, _} 
import inox.trees.dsl._ 

object Field { 

    val element = FreshIdentifier("element") 
    val zero = FreshIdentifier("zero") 
    val one = FreshIdentifier("one") 

    val elementADT = mkSort(element)()(Seq(zero, one)) 
    val zeroADT = mkConstructor(zero)()(Some(element)) {_ => Seq()} 
    val oneADT = mkConstructor(one)()(Some(element)) {_ => Seq()} 

    val addID = FreshIdentifier("add") 

    val addFunction = mkFunDef(addID)("element") { case Seq(eT) => 
    val args: Seq[ValDef] = Seq("f1" :: eT, "f2" :: eT) 
    val retType: Type = eT 
    val body: Seq[Variable] => Expr = { case Seq(f1,f2) => 
     //do the addition for this field 
     f1 //do something better... 
    } 
    (args, retType, body) 
    } 

    //-------Helper functions for arithmetic operations and zero element of field---------------- 
    implicit class ExprOperands(private val lhs: Expr) extends AnyVal{ 
    def +(rhs: Expr): Expr = E(addID)(T(element)())(lhs, rhs) 
    } 

} 

ich diese Operation möchte mit Infixschreibweise und der aktuellen Lösung, die wir finden verwendet werden, um so in Scala ist gegeben here. Deshalb schließe ich die implizite Klasse ganz unten ein.

Sagen Sie jetzt ich diese Definition hinaus verwenden möchten:

import inox._ 
import inox.trees.{forall => _, _} 
import inox.trees.dsl._ 

import welder._ 

object Curve{ 

    val affinePoint = FreshIdentifier("affinePoint") 
    val infinitePoint = FreshIdentifier("infinitePoint") 
    val finitePoint = FreshIdentifier("finitePoint") 
    val first = FreshIdentifier("first") 
    val second = FreshIdentifier("second") 
    val affinePointADT = mkSort(affinePoint)("F")(Seq(infinitePoint,finitePoint)) 
    val infiniteADT = mkConstructor(infinitePoint)("F")(Some(affinePoint))(_ => Seq()) 
    val finiteADT = mkConstructor(finitePoint)("F")(Some(affinePoint)){ case Seq(fT) => 
    Seq(ValDef(first, fT), ValDef(second, fT)) 
    } 

    val F = T(Field.element)() 
    val affine = T(affinePoint)(F) 
    val infinite = T(infinitePoint)(F) 
    val finite = T(finitePoint)(F) 

    val onCurveID = FreshIdentifier("onCurve") 

    val onCurveFunction = mkFunDef(onCurveID)() { case Seq() => 
    val args: Seq[ValDef] = Seq("p" :: affine, "a" :: F, "b" :: F) 
    val retType: Type = BooleanType 
    val body: Seq[Variable] => Expr = { case Seq(p,a,b) => 
     if_(p.isInstOf(finite)){ 
     val x: Expr = p.asInstOf(finite).getField(first) 
     val y: Expr = p.asInstOf(finite).getField(second) 
     x === y+y 
     } else_ { 
     BooleanLiteral(true) 
     } 
    } 
    (args, retType, body) 
    } 

    //---------------------------Registering elements----------------------------------- 

    val symbols = NoSymbols 
    .withADTs(Seq(affinePointADT, 
        infiniteADT, 
        finiteADT, 
        Field.zeroADT, 
        Field.oneADT, 
        Field.elementADT)) 
    .withFunctions(Seq(Field.addFunction, 

         onCurveFunction)) 

    val program = InoxProgram(Context.empty, symbols) 
    val theory = theoryOf(program) 
    import theory._ 

    val expr = (E(BigInt(1)) + E(BigInt(1))) === E(BigInt(2)) 

    val theorem: Theorem = prove(expr) 

} 

Dies wird nicht kompilieren, wird folgende Fehler geben:

java.lang.ExceptionInInitializerError 
    at Main$.main(Main.scala:4) 
    at Main.main(Main.scala) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:498) 
Caused by: inox.ast.TypeOps$TypeErrorException: Type error: if (p.isInstanceOf[finitePoint[element]]) { 
    p.asInstanceOf[finitePoint[element]].first == p.asInstanceOf[finitePoint[element]].second + p.asInstanceOf[finitePoint[element]].second 
} else { 
    true 
}, expected Boolean, found <untyped> 
    at inox.ast.TypeOps$TypeErrorException$.apply(TypeOps.scala:24) 
    at inox.ast.TypeOps$class.typeCheck(TypeOps.scala:264) 
    at inox.ast.SimpleSymbols$SimpleSymbols.typeCheck(SimpleSymbols.scala:12) 
    at inox.ast.Definitions$AbstractSymbols$$anonfun$ensureWellFormed$2.apply(Definitions.scala:166) 
    at inox.ast.Definitions$AbstractSymbols$$anonfun$ensureWellFormed$2.apply(Definitions.scala:165) 
    at scala.collection.TraversableLike$WithFilter$$anonfun$foreach$1.apply(TraversableLike.scala:733) 
    at scala.collection.immutable.Map$Map2.foreach(Map.scala:137) 
    at scala.collection.TraversableLike$WithFilter.foreach(TraversableLike.scala:732) 
    at inox.ast.Definitions$AbstractSymbols$class.ensureWellFormed(Definitions.scala:165) 
    at inox.ast.SimpleSymbols$SimpleSymbols.ensureWellFormed$lzycompute(SimpleSymbols.scala:12) 
    at inox.ast.SimpleSymbols$SimpleSymbols.ensureWellFormed(SimpleSymbols.scala:12) 
    at inox.solvers.unrolling.AbstractUnrollingSolver$class.assertCnstr(UnrollingSolver.scala:129) 
    at inox.solvers.SolverFactory$$anonfun$getFromName$1$$anon$1.inox$tip$TipDebugger$$super$assertCnstr(SolverFactory.scala:115) 
    at inox.tip.TipDebugger$class.assertCnstr(TipDebugger.scala:52) 
    at inox.solvers.SolverFactory$$anonfun$getFromName$1$$anon$1.assertCnstr(SolverFactory.scala:115) 
    at inox.solvers.SolverFactory$$anonfun$getFromName$1$$anon$1.assertCnstr(SolverFactory.scala:115) 
    at welder.Solvers$class.prove(Solvers.scala:51) 
    at welder.package$$anon$1.prove(package.scala:10) 
    at welder.Solvers$class.prove(Solvers.scala:23) 
    at welder.package$$anon$1.prove(package.scala:10) 
    at Curve$.<init>(curve.scala:61) 
    at Curve$.<clinit>(curve.scala) 
    at Main$.main(Main.scala:4) 
    at Main.main(Main.scala) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:498) 

In der Tat, was passiert ist, dass in dem Ausdruck x === y + y Das + wird nicht korrekt angewendet, so dass es nicht typisiert ist. Ich erinnere mich, dass man in den Objekten von Welder Proofs verschachtelte Objekte oder Klassen, die ich nicht weiß, nicht definieren kann, wenn dies damit zusammenhängt.

Wie auch immer, muss ich die Verwendung von Infix-Notation in meinem Code für Welder vergessen oder gibt es eine Lösung?

Antwort

1

Das Problem hier ist, dass die von Ihnen definierte implizite Klasse nicht sichtbar ist, wenn Sie y+y erstellen (Sie müssten Field._ importieren, damit es sichtbar ist).

Ich erinnere mich nicht genau, wie implizite Auflösung erfolgt in Scala, vielleicht import Field._ Zugabe innerhalb das Curve-Objekt der + außer Kraft gesetzt werden, die von der inox DSL kommt (das ist derjenige angewandt werden, wenn Sie y+y schreiben, was Sie haben einen arithmetischen Plusausdruck, der ganzzahlige Argumente erwartet, daher der Typfehler. Sonst haben Sie leider eine Zweideutigkeit in der impliziten Auflösung, und ich bin mir nicht sicher, ob es möglich ist, den Infix + Operator in diesem Fall zu verwenden, ohne die gesamte dsl aufzugeben.

Verwandte Themen