Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added ir.EGetItems with expected Nt #112

Merged
merged 2 commits into from
Nov 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions src/main/scala/esmeta/analyzer/AbsTransfer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -345,16 +345,18 @@ class AbsTransfer(sem: AbsSemantics) extends Optimized {
case ENt(name, params) => AbsValue(Nt(name, params))
case ESourceText(expr) =>
for { v <- transfer(expr) } yield v.sourceText
case e @ EGetChildren(kindOpt, ast) =>
case e @ EGetChildren(ast) =>
val asite = AllocSite(e.asite, cp.view)
for {
kOpt <- id(st => {
kindOpt match
case Some(kind) => transfer(kind).map(Some(_))(st)
case None => (None, st)
})
av <- transfer(ast)
lv <- id(_.getChildren(asite, av, kOpt))
lv <- id(_.getChildren(asite, av))
} yield lv
case e @ EGetItems(nt, ast) =>
val asite = AllocSite(e.asite, cp.view)
for {
nv <- transfer(nt)
av <- transfer(ast)
lv <- id(_.getItems(asite, nv, av))
} yield lv
case EYet(msg) =>
if (YET_THROW) notSupported(msg)
Expand Down
25 changes: 16 additions & 9 deletions src/main/scala/esmeta/analyzer/domain/state/BasicDomain.scala
Original file line number Diff line number Diff line change
Expand Up @@ -216,17 +216,24 @@ object BasicDomain extends state.Domain {
def getChildren(
to: AllocSite,
ast: AbsValue,
kindOpt: Option[AbsValue],
): (AbsValue, Elem) = (kindOpt.map(_.getSingle), ast.getSingle) match
case (Some(Zero), _) | (_, Zero) => (AbsValue.Bot, Bot)
case (Some(Many), _) | (_, Many) => exploded("EGetChildren")
case (Some(One(Nt(name, _))), One(AstValue(ast))) =>
val vs = ast.getChildren(name).map(AbsValue(_))
allocList(to, vs)
case (None, One(AstValue(syn: Syntactic))) =>
): (AbsValue, Elem) = ast.getSingle match
case One(AstValue(syn: Syntactic)) =>
val vs = syn.children.flatten.map(AbsValue(_))
allocList(to, vs)
case _ => (AbsValue.Bot, Bot)
case Many => exploded("EGetChildren")
case _ => (AbsValue.Bot, Bot)

/** get items of AST */
def getItems(
to: AllocSite,
nt: AbsValue,
ast: AbsValue,
): (AbsValue, Elem) = (nt.getSingle, ast.getSingle) match
case (One(Nt(name, _)), One(AstValue(ast))) =>
val vs = ast.getItems(name).map(AbsValue(_))
allocList(to, vs)
case (Many, _) | (_, Many) => exploded("EGetItems")
case _ => (AbsValue.Bot, Bot)

/** allocation of map with address partitions */
def allocMap(
Expand Down
8 changes: 7 additions & 1 deletion src/main/scala/esmeta/analyzer/domain/state/Domain.scala
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,13 @@ trait Domain extends domain.Domain[State] {
def getChildren(
to: AllocSite,
ast: AbsValue,
kindOpt: Option[AbsValue],
): (AbsValue, Elem)

/** get items of AST */
def getItems(
to: AllocSite,
nt: AbsValue,
ast: AbsValue,
): (AbsValue, Elem)

/** allocation of map with address partitions */
Expand Down
8 changes: 7 additions & 1 deletion src/main/scala/esmeta/analyzer/domain/state/TypeDomain.scala
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,15 @@ object TypeDomain extends state.Domain {
def getChildren(
to: AllocSite,
ast: AbsValue,
kindOpt: Option[AbsValue],
): (AbsValue, Elem) = (AbsValue(ListT(AstT)), elem)

/** get items of AST */
def getItems(
to: AllocSite,
nt: AbsValue,
ast: AbsValue,
): (AbsValue, Elem) = (AbsValue(ListT(AstT)), elem) // TODO more precise

/** allocation of map with address partitions */
def allocMap(
to: AllocSite,
Expand Down
6 changes: 3 additions & 3 deletions src/main/scala/esmeta/compiler/Compiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ class Compiler(
val (list, listExpr) = fb.newTIdWithExpr
val (length, lengthExpr) = fb.newTIdWithExpr
fb.addInst(
IAssign(list, EGetChildren(None, compile(fb, expr))),
IAssign(list, EGetChildren(compile(fb, expr))),
IAssign(i, zero),
IAssign(length, toStrERef(list, "length")),
)
Expand Down Expand Up @@ -485,8 +485,8 @@ class Compiler(
ESourceText(compile(fb, expr))
case CoveredByExpression(code, rule) =>
EParse(compile(fb, code), compile(fb, rule))
case GetChildrenExpression(nt, expr) =>
EGetChildren(Some(compile(fb, nt)), compile(fb, expr))
case GetItemsExpression(nt, expr) =>
EGetItems(compile(fb, nt), compile(fb, expr))
case InvokeAbstractOperationExpression(name, args) =>
val as = args.map(compile(fb, _))
if simpleOps contains name then simpleOps(name)(as)
Expand Down
4 changes: 3 additions & 1 deletion src/main/scala/esmeta/error/InterpreterError.scala
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ case class InvalidTypeExpr(expr: Expr, v: Value)
case class InvalidExit(value: Value)
extends InterpreterError(s"return not undefined: $value")
case class InvalidASTChildren(ast: Ast)
extends InterpreterError(s"no children for lexical node: ${ast.name}")
extends InterpreterError(s"no children for lexical node: |${ast.name}|")
case class InvalidASTItem(ast: Ast, name: String)
extends InterpreterError(s"invalid item: |${ast.name}| (expected: |$name|)")
case class InvalidTypedValue(value: Value, ty: Ty)
extends InterpreterError(s"unexpected typed value: $value (expected: $ty)")

Expand Down
21 changes: 12 additions & 9 deletions src/main/scala/esmeta/es/Ast.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package esmeta.es

import esmeta.es.util.*
import esmeta.error.InvalidASTItem
import esmeta.ir.Type
import esmeta.spec.*
import esmeta.util.*
Expand Down Expand Up @@ -43,15 +44,17 @@ sealed trait Ast extends ESElem with Locational {
case child :: Nil => this :: child.chains
case _ => List(this)

/** children */
def getChildren(kind: String): List[Ast] = this match
case lex: Lexical => List()
case Syntactic(k, _, _, children) =>
val founded = (for {
child <- children.flatten
found <- child.getChildren(kind)
} yield found).toList
if (k == kind) this :: founded else founded
/** get items */
def getItems(name: String): List[Ast] = this match
case _: Lexical => Nil
case syn: Syntactic =>
for {
child <- syn.children.flatten
item <-
if (child.name == this.name) child.getItems(name)
else if (child.name == name) List(child)
else throw InvalidASTItem(child, name)
} yield item

/** types */
lazy val types: Set[String] =
Expand Down
20 changes: 9 additions & 11 deletions src/main/scala/esmeta/interpreter/Interpreter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -234,18 +234,16 @@ class Interpreter(
val ast = eval(expr).asAst
// XXX fix last space in ECMAScript stringifier
Str(ast.toString(grammar = Some(grammar)).trim)
case EGetChildren(kindOpt, ast) =>
val kOpt = kindOpt.map(kind =>
eval(kind) match
case Nt(name, _) => name
case v => throw NoNt(kind, v),
)
val a = eval(ast).asAst
(a, kOpt) match
case (_, Some(k)) => st.allocList(a.getChildren(k).map(AstValue(_)))
case (syn: Syntactic, None) =>
case EGetChildren(ast) =>
eval(ast).asAst match
case syn: Syntactic =>
st.allocList(syn.children.flatten.map(AstValue(_)))
case _ => throw InvalidASTChildren(a)
case ast => throw InvalidASTChildren(ast)
case EGetItems(nt, ast) =>
val name = eval(nt) match
case Nt(name, _) => name
case v => throw NoNt(nt, v)
st.allocList(eval(ast).asAst.getItems(name).map(AstValue(_)))
case EYet(msg) =>
throw NotSupported(msg)
case EContains(list, elem, field) =>
Expand Down
3 changes: 2 additions & 1 deletion src/main/scala/esmeta/ir/Expr.scala
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ case class EListConcat(exprs: List[Expr]) extends AllocExpr
case class ESymbol(desc: Expr) extends AllocExpr
case class ECopy(obj: Expr) extends AllocExpr
case class EKeys(map: Expr, intSorted: Boolean) extends AllocExpr
case class EGetChildren(kindOpt: Option[Expr], ast: Expr) extends AllocExpr
case class EGetChildren(ast: Expr) extends AllocExpr
case class EGetItems(nt: Expr, ast: Expr) extends AllocExpr

// literals
sealed trait LiteralExpr extends Expr
Expand Down
6 changes: 4 additions & 2 deletions src/main/scala/esmeta/ir/util/Parser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,10 @@ trait Parsers extends TyParsers {
case e => ECopy(e)
} | ("(" ~ "keys" ~> opt("-int") ~ expr <~ ")") ^^ {
case i ~ e => EKeys(e, i.isDefined)
} | "(" ~ "get-children" ~> opt(expr) ~ expr <~ ")" ^^ {
case k ~ a => EGetChildren(k, a)
} | "(" ~ "get-children" ~> expr <~ ")" ^^ {
case e => EGetChildren(e)
} | "(" ~ "get-items" ~> expr ~ expr <~ ")" ^^ {
case n ~ a => EGetItems(n, a)
},
)

Expand Down
8 changes: 4 additions & 4 deletions src/main/scala/esmeta/ir/util/Stringifier.scala
Original file line number Diff line number Diff line change
Expand Up @@ -222,10 +222,10 @@ class Stringifier(detail: Boolean, location: Boolean) {
case EKeys(map, intSorted) =>
app >> "(keys" >> (if (intSorted) "-int" else "") >> " "
app >> map >> ")"
case EGetChildren(kindOpt, ast) =>
app >> "(get-children "
kindOpt.foreach(kind => app >> kind >> " ")
app >> ast >> ")"
case EGetChildren(ast) =>
app >> "(get-children " >> ast >> ")"
case EGetItems(nt, ast) =>
app >> "(get-items " >> nt >> " " >> ast >> ")"
}
if (expr.asite == -1) app
else app >> "[#" >> expr.asite >> "]"
Expand Down
6 changes: 4 additions & 2 deletions src/main/scala/esmeta/ir/util/UnitWalker.scala
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,10 @@ trait UnitWalker extends BasicUnitWalker {
walk(obj)
case EKeys(map, intSorted) =>
walk(map); walk(intSorted)
case EGetChildren(kind, ast) =>
walkOpt(kind, walk); walk(ast)
case EGetChildren(ast) =>
walk(ast)
case EGetItems(nt, ast) =>
walk(nt); walk(ast)
}

// literals
Expand Down
6 changes: 4 additions & 2 deletions src/main/scala/esmeta/ir/util/Walker.scala
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,10 @@ trait Walker extends BasicWalker {
ECopy(walk(obj))
case EKeys(map, intSorted) =>
EKeys(walk(map), walk(intSorted))
case EGetChildren(kind, ast) =>
EGetChildren(walkOpt(kind, walk), walk(ast))
case EGetChildren(ast) =>
EGetChildren(walk(ast))
case EGetItems(nt, ast) =>
EGetItems(walk(nt), walk(ast))

// literals
def walk(lit: LiteralExpr): LiteralExpr = lit
Expand Down
8 changes: 3 additions & 5 deletions src/main/scala/esmeta/lang/Expression.scala
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,9 @@ case class SourceTextExpression(
case class CoveredByExpression(code: Expression, rule: Expression)
extends Expression

// get children ast expressions
case class GetChildrenExpression(
nonterminal: Expression,
expr: Expression,
) extends Expression
// get items ast expressions
case class GetItemsExpression(nt: Expression, expr: Expression)
extends Expression

// list expressions
case class ListExpression(entries: List[Expression]) extends Expression
Expand Down
8 changes: 4 additions & 4 deletions src/main/scala/esmeta/lang/util/Parser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ trait Parsers extends IndentParsers {
numberOfExpr |||
sourceTextExpr |||
coveredByExpr |||
getChildrenExpr |||
getItemsExpr |||
intrExpr |||
calcExpr |||
clampExpr |||
Expand Down Expand Up @@ -371,11 +371,11 @@ trait Parsers extends IndentParsers {
case r ~ c => CoveredByExpression(c, r)
}

// get children ast expressions
lazy val getChildrenExpr: PL[GetChildrenExpression] =
// get items ast expressions
lazy val getItemsExpr: PL[GetItemsExpression] =
("the List of" ~> expr <~ "items") ~
("in" ~> expr <~ "," ~ "in source text order") ^^ {
case t ~ e => GetChildrenExpression(t, e)
case t ~ e => GetItemsExpression(t, e)
}

// abstract closure expressions
Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/esmeta/lang/util/Stringifier.scala
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ class Stringifier(detail: Boolean, location: Boolean) {
app >> "the source text matched by " >> expr
case CoveredByExpression(code, rule) =>
app >> "the " >> rule >> " that is covered by " >> code
case GetChildrenExpression(nt, expr) =>
case GetItemsExpression(nt, expr) =>
app >> "the List of " >> nt >> " items in " >> expr
app >> ", in source text order"
case IntrinsicExpression(intr) =>
Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/esmeta/lang/util/UnitWalker.scala
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ trait UnitWalker extends BasicUnitWalker {
walk(expr)
case CoveredByExpression(from, to) =>
walk(from); walk(to)
case GetChildrenExpression(nt, expr) =>
case GetItemsExpression(nt, expr) =>
walk(nt); walk(expr)
case IntrinsicExpression(intr) =>
walk(intr)
Expand Down
4 changes: 2 additions & 2 deletions src/main/scala/esmeta/lang/util/Walker.scala
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,8 @@ trait Walker extends BasicWalker {
SourceTextExpression(walk(expr))
case CoveredByExpression(code, rule) =>
CoveredByExpression(walk(code), walk(rule))
case GetChildrenExpression(nt, expr) =>
GetChildrenExpression(walk(nt), walk(expr))
case GetItemsExpression(nt, expr) =>
GetItemsExpression(walk(nt), walk(expr))
case IntrinsicExpression(intr) =>
IntrinsicExpression(walk(intr))
case expr: CalcExpression =>
Expand Down
8 changes: 8 additions & 0 deletions src/test/scala/esmeta/ir/StringifyTinyTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -190,13 +190,17 @@ class StringifyTinyTest extends IRTest {
lazy val copy = ECopy(xExpr)
lazy val keys = EKeys(xExpr, false)
lazy val keysInt = EKeys(xExpr, true)
lazy val getChildren = EGetChildren(xExpr)
lazy val getItems = EGetItems(xExpr, xExpr)
def assignASite(e: AllocExpr, k: Int): AllocExpr = { e.asite = k; e }
lazy val recASite = assignASite(rec.copy(), 3)
lazy val listASite = assignASite(list.copy(), 1)
lazy val symbolASite = assignASite(symbol.copy(), 7)
lazy val copyASite = assignASite(copy.copy(), 42)
lazy val keysASite = assignASite(keys.copy(), 5)
lazy val keysIntASite = assignASite(keysInt.copy(), 6)
lazy val getChildrenASite = assignASite(getChildren.copy(), 9)
lazy val getItemsASite = assignASite(getItems.copy(), 10)
// literals
lazy val normal = EConst("normal")
lazy val empty = EConst("empty")
Expand Down Expand Up @@ -242,13 +246,17 @@ class StringifyTinyTest extends IRTest {
copy -> "(copy x)",
keys -> "(keys x)",
keysInt -> "(keys-int x)",
getChildren -> "(get-children x)",
getItems -> "(get-items x x)",
// allocation expressions with allocation sites
recASite -> "(new T(undefined -> true, null -> absent))[#3]",
listASite -> "(new [undefined, null, absent])[#1]",
symbolASite -> "(new 'null)[#7]",
copyASite -> "(copy x)[#42]",
keysASite -> "(keys x)[#5]",
keysIntASite -> "(keys-int x)[#6]",
getChildrenASite -> "(get-children x)[#9]",
getItemsASite -> "(get-items x x)[#10]",
// literals
EMathVal(4) -> "4",
ENumber(3.0) -> "3.0f",
Expand Down
4 changes: 2 additions & 2 deletions src/test/scala/esmeta/lang/StringifyTinyTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ class StringifyTinyTest extends LangTest {
lazy val numberOfExpr = NumberOfExpression(refExpr)
lazy val sourceTextExpr = SourceTextExpression(nt)
lazy val coveredByExpr = CoveredByExpression(nt, nt)
lazy val getChildrenExpr = GetChildrenExpression(nt, refExpr)
lazy val getItemsExpr = GetItemsExpression(nt, refExpr)
lazy val intrExpr = IntrinsicExpression(intr)
lazy val invokeAOExpr =
InvokeAbstractOperationExpression("ToObject", List(addExpr, unExpr))
Expand Down Expand Up @@ -274,7 +274,7 @@ class StringifyTinyTest extends LangTest {
numberOfExpr -> "the number of elements in _x_",
sourceTextExpr -> "the source text matched by |Identifier|",
coveredByExpr -> "the |Identifier| that is covered by |Identifier|",
getChildrenExpr -> "the List of |Identifier| items in _x_, in source text order",
getItemsExpr -> "the List of |Identifier| items in _x_, in source text order",
intrExpr -> "%Array%",
invokeAOExpr -> "ToObject(_x_ + _x_, -_x_)",
invokeNumericExpr -> "Number::add(_x_, _x_)",
Expand Down