Skip to content

Commit

Permalink
Scope holes to paren invocation exprs
Browse files Browse the repository at this point in the history
  • Loading branch information
mdr committed Jun 22, 2016
1 parent 7747329 commit 1db83a8
Show file tree
Hide file tree
Showing 13 changed files with 47 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,13 @@ class BareStringificationContext {
MemberExpr(bareStringify(expr, bindings), name, isNullSafe, sourceInfoOpt)
case LookupExpr(expr, index, sourceInfoOpt)
LookupExpr(bareStringify(expr, bindings), bareStringify(index, bindings), sourceInfoOpt)
case InvocationExpr(function, arguments, sourceInfoOpt)
case InvocationExpr(function, arguments, isParenInvocation, sourceInfoOpt)
val newArguments = arguments.map {
case Argument.PositionArg(expr, sourceInfoOpt) Argument.PositionArg(bareStringify(expr, bindings), sourceInfoOpt)
case arg @ Argument.ShortFlag(_, sourceInfoOpt) arg
case Argument.LongFlag(flag, valueOpt, sourceInfoOpt) Argument.LongFlag(flag, valueOpt.map(bareStringify(_, bindings)), sourceInfoOpt)
}
InvocationExpr(bareStringify(function, bindings), newArguments, sourceInfoOpt)
InvocationExpr(bareStringify(function, bindings), newArguments, isParenInvocation, sourceInfoOpt)
case BinOpExpr(left, op @ BinaryOperator.Sequence, right, sourceInfoOpt)
val extraGlobals = left.findAll {
case AssignmentExpr(left @ Identifier(name, _), _, _, _) name
Expand Down
29 changes: 23 additions & 6 deletions src/main/scala/com/github/mdr/mash/compiler/DesugarHoles.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,19 @@ object DesugarHoles {
newExpr
}

private def addLambdaIfNeeded(argument: Argument.PositionArg): Argument.PositionArg = {
val Result(newArgument, hasHole) = desugarHoles_(argument)
if (hasHole)
Argument.PositionArg(LambdaExpr(VariableName, newArgument.expr, None), newArgument.sourceInfoOpt)
else
newArgument
}

private def desugarHoles_(argument: Argument.PositionArg): Result[Argument.PositionArg] =
desugarHoles_(argument.expr).map(Argument.PositionArg(_, argument.sourceInfoOpt))

private def desugarHoles_(argument: Argument): Result[Argument] = argument match {
case Argument.PositionArg(expr, sourceInfoOpt) desugarHoles_(expr).map(Argument.PositionArg(_, sourceInfoOpt))
case posArg @ Argument.PositionArg(_, _) desugarHoles_(posArg)
case Argument.ShortFlag(_, sourceInfoOpt) Result(argument)
case Argument.LongFlag(flag, None, sourceInfoOpt) Result(Argument.LongFlag(flag, None, sourceInfoOpt))
case Argument.LongFlag(flag, Some(expr), sourceInfoOpt) desugarHoles_(expr).map(e Argument.LongFlag(flag, Some(e), sourceInfoOpt))
Expand Down Expand Up @@ -58,11 +69,17 @@ object DesugarHoles {
newExpr desugarHoles_(expr)
newIndex desugarHoles_(index)
} yield LookupExpr(newExpr, newIndex, sourceInfoOpt)
case InvocationExpr(function, args, sourceInfoOpt)
for {
newFunction desugarHoles_(function)
newArgs sequence(args.map(desugarHoles_))
} yield InvocationExpr(newFunction, newArgs, sourceInfoOpt)
case InvocationExpr(function, args, isParenInvocation, sourceInfoOpt)
if (isParenInvocation)
for {
newFunction desugarHoles_(function)
newArgs = args.collect { case arg: Argument.PositionArg arg }.map(addLambdaIfNeeded)
} yield InvocationExpr(newFunction, newArgs, isParenInvocation, sourceInfoOpt)
else
for {
newFunction desugarHoles_(function)
newArgs sequence(args.map(desugarHoles_))
} yield InvocationExpr(newFunction, newArgs, isParenInvocation, sourceInfoOpt)
case ListExpr(items, sourceInfoOpt)
for (newItems sequence(items.map(desugarHoles_)))
yield ListExpr(newItems, sourceInfoOpt)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import com.github.mdr.mash.parser.AbstractSyntax._
object DesugarPipes {

def desugarPipes(expr: Expr): Expr = expr.transform {
case PipeExpr(left, InvocationExpr(function: Expr, args, _), sourceInfoOpt)
InvocationExpr(function, args :+ Argument.PositionArg(left, left.sourceInfoOpt), sourceInfoOpt)
case PipeExpr(left, InvocationExpr(function: Expr, args, _, _), sourceInfoOpt)
InvocationExpr(function, args :+ Argument.PositionArg(left, left.sourceInfoOpt), isParenInvocation = false, sourceInfoOpt)
case PipeExpr(left, right, sourceInfoOpt)
InvocationExpr(right, Seq(Argument.PositionArg(left, left.sourceInfoOpt)), sourceInfoOpt)
InvocationExpr(right, Seq(Argument.PositionArg(left, left.sourceInfoOpt)), isParenInvocation = false, sourceInfoOpt)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ object InvocationFinder {
case ConcreteSyntax.LongArg(_, Some((_, ConcreteSyntax.Literal(`literalToken`)))) true
}
expr.find {
case iexpr @ InvocationExpr(_, _, Some(SourceInfo(_, ArgSite(args)))) if args.exists(isLiteralArg)
case iexpr @ InvocationExpr(_, _, _, Some(SourceInfo(_, ArgSite(args)))) if args.exists(isLiteralArg)
InvocationInfo(iexpr, args.indexWhere(isLiteralArg))
}
}
Expand All @@ -35,7 +35,7 @@ object InvocationFinder {
case ConcreteSyntax.ShortArg(`flagToken`) | ConcreteSyntax.LongArg(`flagToken`, _) true
}
expr.find {
case iexpr @ InvocationExpr(_, _, Some(SourceInfo(_, ArgSite(args)))) if args.exists(isFlagArg)
case iexpr @ InvocationExpr(_, _, _, Some(SourceInfo(_, ArgSite(args)))) if args.exists(isFlagArg)
InvocationInfo(iexpr, args.indexWhere(isFlagArg))
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import com.github.mdr.mash.functions.ArgumentException
object InvocationEvaluator extends EvaluatorHelper {

def evaluateInvocationExpr(invocationExpr: InvocationExpr)(implicit context: EvaluationContext) = {
val InvocationExpr(functionExpr, arguments, _) = invocationExpr
val InvocationExpr(functionExpr, arguments, _, _) = invocationExpr
val evaluatedArguments = Arguments(arguments.map(evaluateArgument(_)))
functionExpr match {
case memberExpr: MemberExpr
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ class TypeInferencer {
}

private def inferTypeInvocationExpr(invocationExpr: InvocationExpr, bindings: Map[String, Type]): Option[Type] = {
val InvocationExpr(f, args, _) = invocationExpr
val InvocationExpr(f, args, _, _) = invocationExpr

args.foreach(inferTypeArg(_, bindings))
val typedArgs = SimpleTypedArguments.from(invocationExpr)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@ object AbstractSyntax {
MemberExpr(expr.transform(f), name, isNullSafe, sourceInfoOpt)
case LookupExpr(expr, index, sourceInfoOpt)
LookupExpr(expr.transform(f), index.transform(f), sourceInfoOpt)
case InvocationExpr(function, arguments, sourceInfoOpt)
case InvocationExpr(function, arguments, isParenInvocation, sourceInfoOpt)
val newArguments = arguments.map(_.transform(f).asInstanceOf[Argument])
InvocationExpr(function.transform(f), newArguments, sourceInfoOpt)
InvocationExpr(function.transform(f), newArguments, isParenInvocation, sourceInfoOpt)
case BinOpExpr(left, op, right, sourceInfoOpt)
BinOpExpr(left.transform(f), op, right.transform(f), sourceInfoOpt)
case ChainedOpExpr(left, opRights, sourceInfoOpt)
Expand Down Expand Up @@ -235,6 +235,7 @@ object AbstractSyntax {
case class InvocationExpr(
function: Expr,
arguments: Seq[Argument],
isParenInvocation: Boolean,
sourceInfoOpt: Option[SourceInfo] = None) extends Expr {

def withSourceInfoOpt(sourceInfoOpt: Option[SourceInfo]) = copy(sourceInfoOpt = sourceInfoOpt)
Expand Down
4 changes: 2 additions & 2 deletions src/main/scala/com/github/mdr/mash/parser/Abstractifier.scala
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ class Abstractifier(source: String) {
case None
Seq()
}).map(arg Argument.PositionArg(arg, arg.sourceInfoOpt))
Abstract.InvocationExpr(abstractify(function), args, sourceInfo(invocationExpr))
Abstract.InvocationExpr(abstractify(function), args, isParenInvocation = true, sourceInfo(invocationExpr))
}

private def abstractifyInvocation(invocationExpr: Concrete.InvocationExpr): Abstract.InvocationExpr = {
Expand All @@ -160,7 +160,7 @@ class Abstractifier(source: String) {
case x
throw new RuntimeException("Unexpected argument: " + x)
}
Abstract.InvocationExpr(abstractify(function), abstractArgs, sourceInfo(invocationExpr))
Abstract.InvocationExpr(abstractify(function), abstractArgs, isParenInvocation = false, sourceInfo(invocationExpr))
}

private def abstractifyChainedComparision(chainedExpr: Concrete.ChainedOpExpr): Abstract.Expr = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ object PrettyPrinter {
case (op, right)
" " + pretty(op) + " " + parens(pretty(right), simpleOmitParens(right))
}.mkString
case InvocationExpr(function, args, _)
case InvocationExpr(function, args, _, _)
parens(pretty(function), simpleOmitParens(function)) + " " + args.map(arg
arg match {
case Argument.PositionArg(e, _)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ object TreePrettyPrinter {
println("LookupExpr" + typeDescription)
printTree(expr, depth + 1)
printTree(index, depth + 2)
case InvocationExpr(function, args, _)
case InvocationExpr(function, args, _, _)
println("InvocationExpr" + typeDescription)
printTree(function, depth + 1)
for (arg args)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -486,4 +486,7 @@ class EvaluatorTest extends AbstractEvaluatorTest {
// Block expressions
"{ a = 0; a = a + 1; a }" shouldEvaluateTo "1"

// Holes in paren invocation args
"[{foo: 42}].map(_.foo)" shouldEvaluateTo "[42]"

}
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,9 @@ class TypeInferencerTest extends FlatSpec with Matchers {

"()" shouldBeInferredAsHavingType (UnitClass)

"[{foo: 42}].map(_.foo)" shouldBeInferredAsHavingType Seq(NumberClass)


private implicit class RichString(s: String) {

def shouldBeInferredAsHavingType(expectedType: Type) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class AbstractifierTest extends FlatSpec with Matchers {
InvocationExpr(
Identifier("ls", Some(SourceInfo(s, function))),
Seq(Argument.PositionArg(Identifier("pwd", Some(SourceInfo(s, arg))), Some(SourceInfo(s, arg)))),
isParenInvocation = false,
sourceInfoOpt = Some(SourceInfo(s, concreteExpr))))
}

Expand All @@ -49,6 +50,7 @@ class AbstractifierTest extends FlatSpec with Matchers {
InvocationExpr(
Identifier("foo", Some(SourceInfo(s, function))),
Seq(Argument.LongFlag("bar", Some(Identifier("baz", Some(SourceInfo(s, arg)))), Some(SourceInfo(s, longArg)))),
isParenInvocation = false,
sourceInfoOpt = Some(SourceInfo(s, concreteExpr))))
}

Expand Down

0 comments on commit 1db83a8

Please sign in to comment.