Skip to content

Commit

Permalink
Fixed model of ETrim (#238)
Browse files Browse the repository at this point in the history
Co-authored-by: tmdghks <tmdghks12@korea.ac.kr>
  • Loading branch information
d01c2 and tmdghks committed Jul 23, 2024
1 parent 0029b9c commit e3b173f
Show file tree
Hide file tree
Showing 15 changed files with 51 additions and 53 deletions.
4 changes: 2 additions & 2 deletions src/main/scala/esmeta/analyzer/AbsTransfer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -385,10 +385,10 @@ trait AbsTransferDecl { self: Analyzer =>
f <- transfer(from)
t <- transfer(to)
} yield v.substring(f, t)
case ETrim(expr, leading, trailing) =>
case ETrim(expr, isStarting) =>
for {
v <- transfer(expr)
} yield v.trim(leading, trailing)
} yield v.trim(isStarting)
case ERef(ref) =>
for {
rv <- transfer(ref)
Expand Down
14 changes: 4 additions & 10 deletions src/main/scala/esmeta/analyzer/domain/value/ValueBasicDomain.scala
Original file line number Diff line number Diff line change
Expand Up @@ -418,16 +418,10 @@ trait ValueBasicDomainDecl { self: Self =>
else if (t.isValidInt) apply(s.substring(f.toInt, t.toInt))
else Bot
case _ => Bot
def trim(leading: Boolean, trailing: Boolean): Elem = elem.getSingle match
case Many => exploded("ETrim")
case One(Str(s)) =>
apply(
if (leading && trailing) s.trim
else if (leading) s.replaceAll("^\\s+", "")
else if (trailing) s.replaceAll("\\s+$", "")
else s,
)
case _ => Bot
def trim(isStarting: Boolean): Elem = elem.getSingle match
case Many => exploded("ETrim")
case One(Str(s)) => apply(trimString(s, isStarting, cfg.esParser))
case _ => Bot
def clamp(lower: Elem, upper: Elem): Elem =
(elem.getSingle, lower.getSingle, upper.getSingle) match
case (Zero, _, _) | (_, Zero, _) | (_, _, Zero) => Bot
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ trait ValueDomainDecl { self: Self =>
def duplicated(st: AbsState): Elem
def substring(from: Elem): Elem
def substring(from: Elem, to: Elem): Elem
def trim(leading: Boolean, trailing: Boolean): Elem
def trim(isStarting: Boolean): Elem
def clamp(lower: Elem, upper: Elem): Elem
def isArrayIndex: Elem

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@ trait ValueTypeDomainDecl { self: Self =>
def duplicated(st: AbsState): Elem = boolTop
def substring(from: Elem): Elem = strTop
def substring(from: Elem, to: Elem): Elem = strTop
def trim(leading: Boolean, trailing: Boolean): Elem = strTop
def trim(isStarting: Boolean): Elem = strTop
def clamp(lower: Elem, upper: Elem): Elem =
val xty = elem.ty.math
val lowerTy = lower.ty.math
Expand Down
7 changes: 6 additions & 1 deletion src/main/scala/esmeta/compiler/Compiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,12 @@ class Compiler(
to.map(compile(fb, _)),
)
case TrimExpression(expr, leading, trailing) =>
ETrim(compile(fb, expr), leading, trailing)
(leading, trailing) match {
case (false, false) => compile(fb, expr)
case (true, false) => ETrim(compile(fb, expr), true)
case (false, true) => ETrim(compile(fb, expr), false)
case (true, true) => ETrim(ETrim(compile(fb, expr), true), false)
}
case NumberOfExpression(ReferenceExpression(ref)) =>
toStrERef(compile(fb, ref), "length")
case NumberOfExpression(expr) =>
Expand Down
14 changes: 2 additions & 12 deletions src/main/scala/esmeta/interpreter/Interpreter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -252,18 +252,8 @@ class Interpreter(
case Math(n) if s.length < n => s.substring(f)
case v => s.substring(f, v.asInt),
))
case ETrim(expr, leading, trailing) =>
val sb = new java.lang.StringBuilder
val arr = eval(expr).asStr.codePoints.toArray
val cps = esParser.WhiteSpaceCPs ++ esParser.LineTerminatorCPs
def find(i: Int, next: Int => Int): Int =
if (i < 0 || i >= arr.length) i
else if (cps contains arr(i)) find(next(i), next)
else i
val start = if (leading) find(0, _ + 1) else 0
val end = if (trailing) find(arr.length - 1, _ - 1) else arr.length
arr.slice(start, end + 1).foreach(sb.appendCodePoint)
Str(sb.toString)
case ETrim(expr, isStarting) =>
Str(trimString(eval(expr).asStr, isStarting, esParser))
case ERef(ref) =>
st(eval(ref))
case EUnary(uop, expr) =>
Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/esmeta/ir/Expr.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ case class ESourceText(expr: Expr) extends Expr
case class EYet(msg: String) extends Expr
case class EContains(list: Expr, expr: Expr) extends Expr
case class ESubstring(expr: Expr, from: Expr, to: Option[Expr]) extends Expr
case class ETrim(expr: Expr, leading: Boolean, trailing: Boolean) extends Expr
case class ETrim(expr: Expr, isStarting: Boolean) extends Expr
case class ERef(ref: Ref) extends Expr
case class EUnary(uop: UOp, expr: Expr) extends Expr
case class EBinary(bop: BOp, left: Expr, right: Expr) extends Expr
Expand Down
10 changes: 4 additions & 6 deletions src/main/scala/esmeta/ir/util/Parser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -130,12 +130,10 @@ trait Parsers extends TyParsers {
case l ~ e => EContains(l, e)
} | "(" ~ "substring" ~> expr ~ expr ~ opt(expr) <~ ")" ^^ {
case e ~ f ~ t => ESubstring(e, f, t)
} | "(" ~ "trim-start" ~> expr <~ ")" ^^ {
case e => ETrim(e, true, false)
} | "(" ~ "trim-end" ~> expr <~ ")" ^^ {
case e => ETrim(e, false, true)
} | "(" ~ "trim" ~> expr <~ ")" ^^ {
case e => ETrim(e, true, true)
} | "(" ~ "trim" ~ ">" ~> expr <~ ")" ^^ {
case e => ETrim(e, true)
} | "(" ~ "trim" ~> expr <~ "<" ~ ")" ^^ {
case e => ETrim(e, false)
} | "(" ~> uop ~ expr <~ ")" ^^ {
case u ~ e => EUnary(u, e)
} | "(" ~> bop ~ expr ~ expr <~ ")" ^^ {
Expand Down
9 changes: 3 additions & 6 deletions src/main/scala/esmeta/ir/util/Stringifier.scala
Original file line number Diff line number Diff line change
Expand Up @@ -141,12 +141,9 @@ class Stringifier(detail: Boolean, location: Boolean) {
app >> "(substring " >> expr >> " " >> from
to.map(app >> " " >> _)
app >> ")"
case ETrim(expr, leading, trailing) =>
(leading, trailing) match
case (true, true) => app >> "(trim " >> expr >> ")"
case (true, false) => app >> "(trim-start " >> expr >> ")"
case (false, true) => app >> "(trim-end " >> expr >> ")"
case (false, false) => app >> expr
case ETrim(expr, isStarting) =>
if (isStarting) app >> "(trim > " >> expr >> ")"
else app >> "(trim " >> expr >> " <)"
case ERef(ref) =>
app >> ref
case EUnary(uop, expr) =>
Expand Down
4 changes: 2 additions & 2 deletions src/main/scala/esmeta/ir/util/UnitWalker.scala
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ trait UnitWalker extends BasicUnitWalker {
walk(list); walk(elem)
case ESubstring(expr, from, to) =>
walk(expr); walk(from); walkOpt(to, walk)
case ETrim(expr, leading, trailing) =>
walk(expr); walk(leading); walk(trailing)
case ETrim(expr, isStarting) =>
walk(expr); walk(isStarting)
case ERef(ref) =>
walk(ref)
case EUnary(uop, expr) =>
Expand Down
4 changes: 2 additions & 2 deletions src/main/scala/esmeta/ir/util/Walker.scala
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ trait Walker extends BasicWalker {
EContains(walk(list), walk(elem))
case ESubstring(expr, from, to) =>
ESubstring(walk(expr), walk(from), walkOpt(to, walk))
case ETrim(expr, leading, trailing) =>
ETrim(walk(expr), walk(leading), walk(trailing))
case ETrim(expr, isStarting) =>
ETrim(walk(expr), walk(isStarting))
case ERef(ref) =>
ERef(walk(ref))
case EUnary(uop, expr) =>
Expand Down
14 changes: 14 additions & 0 deletions src/main/scala/esmeta/state/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package esmeta.state
import esmeta.state.util.*
import esmeta.util.BaseUtils.*
import esmeta.ir.Global
import esmeta.parser.ESParser
import java.math.MathContext.{UNLIMITED, DECIMAL128}

/** IR state elements */
Expand Down Expand Up @@ -65,6 +66,19 @@ val NEG_INF = Infinity(pos = false)
val NUMBER_POS_INF = Number(Double.PositiveInfinity)
val NUMBER_NEG_INF = Number(Double.NegativeInfinity)

def trimString(x: String, isStarting: Boolean, esParser: ESParser): String =
val sb = new java.lang.StringBuilder
val arr = x.codePoints.toArray
val cps = esParser.WhiteSpaceCPs ++ esParser.LineTerminatorCPs
def find(i: Int, next: Int => Int): Int =
if (i < 0 || i >= arr.length) i
else if (cps contains arr(i)) find(next(i), next)
else i
val start = if (isStarting) find(0, _ + 1) else 0
val end = if (isStarting) arr.length else find(arr.length - 1, _ - 1)
arr.slice(start, end + 1).foreach(sb.appendCodePoint)
sb.toString

/** conversion number to string */
def toStringHelper(x: Double, radix: Int = 10): String = {
// get sign
Expand Down
6 changes: 3 additions & 3 deletions src/test/scala/esmeta/ir/IRTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,9 @@ object IRTest {
lazy val contains = EContains(xExpr, xExpr)
lazy val substring = ESubstring(xExpr, xExpr, None)
lazy val substringTo = ESubstring(xExpr, xExpr, Some(xExpr))
lazy val trim = ETrim(xExpr, true, true)
lazy val trimStart = ETrim(xExpr, true, false)
lazy val trimEnd = ETrim(xExpr, false, true)
lazy val trim = ETrim(ETrim(xExpr, true), false)
lazy val trimStart = ETrim(xExpr, true)
lazy val trimEnd = ETrim(xExpr, false)
lazy val xExpr = ERef(x)
lazy val yExpr = ERef(y)
lazy val unary = EUnary(UOp.Neg, xExpr)
Expand Down
6 changes: 3 additions & 3 deletions src/test/scala/esmeta/ir/JsonTinyTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,9 @@ class JsonTinyTest extends IRTest {
contains -> "(contains x x)",
substring -> "(substring x x)",
substringTo -> "(substring x x x)",
trim -> "(trim x)",
trimStart -> "(trim-start x)",
trimEnd -> "(trim-end x)",
trim -> "(trim (trim > x) <)",
trimStart -> "(trim > x)",
trimEnd -> "(trim x <)",
xExpr -> "x",
unary -> "(- x)",
binary -> "(+ x x)",
Expand Down
6 changes: 3 additions & 3 deletions src/test/scala/esmeta/ir/StringifyTinyTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,9 @@ class StringifyTinyTest extends IRTest {
contains -> "(contains x x)",
substring -> "(substring x x)",
substringTo -> "(substring x x x)",
trim -> "(trim x)",
trimStart -> "(trim-start x)",
trimEnd -> "(trim-end x)",
trim -> "(trim (trim > x) <)",
trimStart -> "(trim > x)",
trimEnd -> "(trim x <)",
xExpr -> "x",
unary -> "(- x)",
binary -> "(+ x x)",
Expand Down

0 comments on commit e3b173f

Please sign in to comment.