Skip to content

Commit

Permalink
feat: add debug construct (#4647)
Browse files Browse the repository at this point in the history
  • Loading branch information
magnus-madsen authored Oct 7, 2022
1 parent 215b234 commit 61d7e00
Show file tree
Hide file tree
Showing 40 changed files with 217 additions and 51 deletions.
2 changes: 1 addition & 1 deletion main/src/ca/uwaterloo/flix/Main.scala
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ object Main {
}
} catch {
case ex: RuntimeException =>
Console.println(ex.getMessage)
ex.printStackTrace()
System.exit(1)
}
}
Expand Down
3 changes: 3 additions & 0 deletions main/src/ca/uwaterloo/flix/api/lsp/Indexer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,9 @@ object Indexer {

case Expression.ReifyEff(sym, exp1, exp2, exp3, _, _, _, _) =>
visitExp(exp1) ++ visitExp(exp2) ++ visitExp(exp3) ++ Index.occurrenceOf(sym, exp1.tpe) ++ Index.occurrenceOf(exp0)

case Expression.Debug(exp, _, _, _, _) =>
visitExp(exp)
}

/**
Expand Down
2 changes: 1 addition & 1 deletion main/src/ca/uwaterloo/flix/api/lsp/LocationLink.scala
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ object LocationLink {
* Returns a location link to the given symbol `sym`.
*/
def fromCaseSym(sym: Symbol.CaseSym, loc: SourceLocation)(implicit root: Root): LocationLink = {
val enumDecl = root.enums(sym.enum)
val enumDecl = root.enums(sym.enumSym)
val caseDecl = enumDecl.cases(sym)
val originSelectionRange = Range.from(loc)
val targetUri = sym.loc.source.name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ object FindReferencesProvider {
}

private def findCaseReferences(sym: Symbol.CaseSym)(implicit index: Index, root: Root): JObject = {
val defSite = Location.from(root.enums(sym.enum).cases(sym).loc)
val defSite = Location.from(root.enums(sym.enumSym).cases(sym).loc)
val useSites = index.usesOf(sym)
val locs = defSite :: useSites.toList.map(Location.from)
("status" -> "success") ~ ("result" -> locs.map(_.toJSON))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ object HighlightProvider {
}

private def highlightCase(sym: Symbol.CaseSym)(implicit index: Index, root: Root): JObject = {
val write = (root.enums(sym.enum).cases(sym).loc, DocumentHighlightKind.Write)
val write = (root.enums(sym.enumSym).cases(sym).loc, DocumentHighlightKind.Write)
val reads = index.usesOf(sym).toList.map(loc => (loc, DocumentHighlightKind.Read))
highlight(write :: reads)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,9 @@ object SemanticTokensProvider {
val o = getSemanticTokenType(sym, exp1.tpe)
val t = SemanticToken(o, Nil, sym.loc)
Iterator(t) ++ visitExp(exp1) ++ visitExp(exp2) ++ visitExp(exp3)

case Expression.Debug(exp, _, _, _, _) =>
visitExp(exp)
}

/**
Expand Down
2 changes: 2 additions & 0 deletions main/src/ca/uwaterloo/flix/language/ast/KindedAst.scala
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,8 @@ object KindedAst {

case class ReifyEff(sym: Symbol.VarSym, exp1: KindedAst.Expression, exp2: KindedAst.Expression, exp3: KindedAst.Expression, loc: SourceLocation) extends KindedAst.Expression

case class Debug(exp: KindedAst.Expression, loc: SourceLocation) extends KindedAst.Expression

}

sealed trait Pattern {
Expand Down
2 changes: 2 additions & 0 deletions main/src/ca/uwaterloo/flix/language/ast/NamedAst.scala
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,8 @@ object NamedAst {

case class ReifyEff(sym: Symbol.VarSym, exp1: NamedAst.Expression, exp2: NamedAst.Expression, exp3: NamedAst.Expression, loc: SourceLocation) extends NamedAst.Expression

case class Debug(exp: NamedAst.Expression, loc: SourceLocation) extends NamedAst.Expression

}

sealed trait Pattern {
Expand Down
17 changes: 13 additions & 4 deletions main/src/ca/uwaterloo/flix/language/ast/ParsedAst.scala
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ object ParsedAst {
*
* A collection of imports and declarations.
*
* @param sp1 the position of the first character in the source.
* @param usesOrImports the uses in the abstract syntax tree.
* @param decls the declarations in the abstract syntax tree.
* @param sp2 the position of the last character in the source.
* @param sp1 the position of the first character in the source.
* @param usesOrImports the uses in the abstract syntax tree.
* @param decls the declarations in the abstract syntax tree.
* @param sp2 the position of the last character in the source.
*/
case class CompilationUnit(sp1: SourcePosition, usesOrImports: Seq[ParsedAst.UseOrImport], decls: Seq[ParsedAst.Declaration], sp2: SourcePosition)

Expand Down Expand Up @@ -1214,6 +1214,15 @@ object ParsedAst {
*/
case class ReifyPurity(sp1: SourcePosition, exp1: ParsedAst.Expression, ident: Name.Ident, exp2: ParsedAst.Expression, exp3: ParsedAst.Expression, sp2: SourcePosition) extends ParsedAst.Expression

/**
* Debug expression.
*
* @param sp1 the position of the first character in the expression.
* @param exp the expression to print.
* @param sp2 the position of the last character in the expression.
*/
case class Debug(sp1: SourcePosition, exp: ParsedAst.Expression, sp2: SourcePosition) extends ParsedAst.Expression

}

/**
Expand Down
2 changes: 2 additions & 0 deletions main/src/ca/uwaterloo/flix/language/ast/ResolvedAst.scala
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,8 @@ object ResolvedAst {

case class ReifyEff(sym: Symbol.VarSym, exp1: ResolvedAst.Expression, exp2: ResolvedAst.Expression, exp3: ResolvedAst.Expression, loc: SourceLocation) extends ResolvedAst.Expression

case class Debug(exp: ResolvedAst.Expression, loc: SourceLocation) extends ResolvedAst.Expression

}

sealed trait Pattern {
Expand Down
21 changes: 20 additions & 1 deletion main/src/ca/uwaterloo/flix/language/ast/SourceLocation.scala
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,29 @@ case class SourceLocation(input: Option[ParserInput], source: Source, locationKi
}

/**
* Returns a formatted string representation of `this` source location.
* Returns a string representation of `this` source location with the line number.
*/
def formatWithLine: String = s"${source.name}:$beginLine"

/**
* Returns a string representation of `this` source location with the line and column numbers.
*/
def format: String = s"${source.name}:$beginLine:$beginCol"

/**
* Returns the source text of the source location.
*/
def text: Option[String] = {
if (isMultiLine) {
None
} else {
val line = lineAt(beginLine)
val b = Math.min(beginCol - 1, line.length)
val e = Math.min(endCol - 1, line.length)
Some(line.substring(b, e))
}
}

/**
* Returns the hashCode of `this` source location.
*/
Expand Down
12 changes: 6 additions & 6 deletions main/src/ca/uwaterloo/flix/language/ast/Symbol.scala
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,8 @@ object Symbol {
/**
* Returns the case symbol for the given name `ident` in the given `enum`.
*/
def mkCaseSym(enum: Symbol.EnumSym, ident: Ident): CaseSym = {
new CaseSym(enum, ident.name, ident.loc)
def mkCaseSym(sym: Symbol.EnumSym, ident: Ident): CaseSym = {
new CaseSym(sym, ident.name, ident.loc)
}

/**
Expand Down Expand Up @@ -411,24 +411,24 @@ object Symbol {
/**
* Enum Symbol.
*/
final class CaseSym(val enum: Symbol.EnumSym, val name: String, val loc: SourceLocation) {
final class CaseSym(val enumSym: Symbol.EnumSym, val name: String, val loc: SourceLocation) {
/**
* Returns `true` if this symbol is equal to `that` symbol.
*/
override def equals(obj: scala.Any): Boolean = obj match {
case that: CaseSym => this.enum == that.enum && this.name == that.name
case that: CaseSym => this.enumSym == that.enumSym && this.name == that.name
case _ => false
}

/**
* Returns the hash code of this symbol.
*/
override val hashCode: Int = Objects.hash(enum, name)
override val hashCode: Int = Objects.hash(enumSym, name)

/**
* Human readable representation.
*/
override def toString: String = enum.toString + "." + name
override def toString: String = enumSym.toString + "." + name
}

/**
Expand Down
2 changes: 2 additions & 0 deletions main/src/ca/uwaterloo/flix/language/ast/TypedAst.scala
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,8 @@ object TypedAst {

case class ReifyEff(sym: Symbol.VarSym, exp1: TypedAst.Expression, exp2: TypedAst.Expression, exp3: TypedAst.Expression, tpe: Type, pur: Type, eff: Type, loc: SourceLocation) extends TypedAst.Expression

case class Debug(exp: TypedAst.Expression, tpe: Type, pur: Type, eff: Type, loc: SourceLocation) extends TypedAst.Expression

}

sealed trait Pattern {
Expand Down
4 changes: 3 additions & 1 deletion main/src/ca/uwaterloo/flix/language/ast/WeededAst.scala
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ object WeededAst {
sealed trait Import

object Import {

case class Import(name: Name.JavaName, alias: Name.Ident, loc: SourceLocation) extends WeededAst.Import

}
Expand Down Expand Up @@ -241,6 +241,8 @@ object WeededAst {

case class ReifyEff(ident: Name.Ident, exp1: WeededAst.Expression, exp2: WeededAst.Expression, exp3: WeededAst.Expression, loc: SourceLocation) extends WeededAst.Expression

case class Debug(exp: WeededAst.Expression, loc: SourceLocation) extends WeededAst.Expression

}

sealed trait Pattern {
Expand Down
7 changes: 7 additions & 0 deletions main/src/ca/uwaterloo/flix/language/ast/ops/TypedAstOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,9 @@ object TypedAstOps {
case Expression.ReifyEff(_, exp1, exp2, exp3, _, _, _, _) =>
visitExp(exp1, env0) ++ visitExp(exp2, env0) ++ visitExp(exp3, env0)

case Expression.Debug(exp, _, _, _, _) =>
visitExp(exp, env0)

}

/**
Expand Down Expand Up @@ -450,6 +453,7 @@ object TypedAstOps {
case Expression.Reify(_, _, _, _, _) => Set.empty
case Expression.ReifyType(_, _, _, _, _, _) => Set.empty
case Expression.ReifyEff(_, exp1, exp2, exp3, _, _, _, _) => sigSymsOf(exp1) ++ sigSymsOf(exp2) ++ sigSymsOf(exp3)
case Expression.Debug(exp, _, _, _, _) => sigSymsOf(exp)
}

/**
Expand Down Expand Up @@ -735,6 +739,9 @@ object TypedAstOps {
case Expression.ReifyEff(sym, exp1, exp2, exp3, _, _, _, _) =>
(freeVars(exp1) ++ freeVars(exp2) ++ freeVars(exp3)) - sym

case Expression.Debug(exp, _, _, _, _) =>
freeVars(exp)

}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ object FormatExpression {
case TypedAst.Expression.Reify(t, _, _, _, _) => s"Reify($t)"
case TypedAst.Expression.ReifyType(t, k, _, _, _, _) => s"ReifyType($t, $k)"
case TypedAst.Expression.ReifyEff(sym, exp1, exp2, exp3, _, _, _, _) => s"ReifyEff($sym, $exp1, $exp2, $exp3)"
case TypedAst.Expression.Debug(exp, _, _, _, _) => s"Debug($exp)"
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,7 @@ object PrettyPrinter {
case Expression.Force(exp, tpe, loc) => "force " + visitExp(exp)

case Expression.HoleError(sym, tpe, loc) => formatter.red("HoleError")

case Expression.MatchError(tpe, loc) => formatter.red("MatchError")
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,9 @@ object EarlyTreeShaker {
case Expression.Without(exp, _, _, _, _, _) =>
visitExp(exp)

case Expression.Debug(exp, _, _, _, _) =>
visitExp(exp)

case Expression.FixpointConstraintSet(_, _, _, loc) =>
throw InternalCompilerException(s"Unexpected expression near: ${loc.format}.")

Expand Down
2 changes: 1 addition & 1 deletion main/src/ca/uwaterloo/flix/language/phase/Inliner.scala
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ object Inliner {

case OccurrenceAst.Expression.Is(sym, exp, purity, loc) =>
val e = visitExp(exp, subst0)
val enum0 = root.enums(sym.enum)
val enum0 = root.enums(sym.enumSym)
if (enum0.cases.size == 1 && e.purity == Pure)
LiftedAst.Expression.True(loc)
else
Expand Down
5 changes: 5 additions & 0 deletions main/src/ca/uwaterloo/flix/language/phase/Kinder.scala
Original file line number Diff line number Diff line change
Expand Up @@ -812,6 +812,11 @@ object Kinder {
case (e1, e2, e3) => KindedAst.Expression.ReifyEff(sym, e1, e2, e3, loc)
}

case ResolvedAst.Expression.Debug(exp, loc) =>
mapN(visitExp(exp, kenv0, senv, taenv, henv0, root)) {
case e => KindedAst.Expression.Debug(e, loc)
}

}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ object LateTreeShaker {

case Expression.MatchError(_, _) =>
Set.empty

}

/**
Expand Down
27 changes: 26 additions & 1 deletion main/src/ca/uwaterloo/flix/language/phase/Lowering.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import ca.uwaterloo.flix.language.ast.TypedAst.Expression.NewChannel
import ca.uwaterloo.flix.language.ast.TypedAst.Predicate.{Body, Head}
import ca.uwaterloo.flix.language.ast.TypedAst._
import ca.uwaterloo.flix.language.ast.ops.TypedAstOps
import ca.uwaterloo.flix.language.ast.{Ast, Kind, Name, Scheme, SourceLocation, SourcePosition, Symbol, Type, TypeConstructor}
import ca.uwaterloo.flix.language.ast.{Ast, Kind, Name, Scheme, SemanticOperator, SourceLocation, SourcePosition, Symbol, Type, TypeConstructor}
import ca.uwaterloo.flix.util.Validation.ToSuccess
import ca.uwaterloo.flix.util.{InternalCompilerException, ParOps, Validation}

Expand Down Expand Up @@ -56,6 +56,8 @@ object Lowering {
lazy val Lift4: Symbol.DefnSym = Symbol.mkDefnSym("Boxable.lift4")
lazy val Lift5: Symbol.DefnSym = Symbol.mkDefnSym("Boxable.lift5")

lazy val Debug: Symbol.DefnSym = Symbol.mkDefnSym("debug")

/**
* Returns the definition associated with the given symbol `sym`.
*/
Expand Down Expand Up @@ -675,6 +677,12 @@ object Lowering {
val e3 = visitExp(exp3)
Expression.ReifyEff(sym, e1, e2, e3, t, pur, eff, loc)

case Expression.Debug(exp, tpe, pur, eff, loc) =>
val line = s"[${loc.formatWithLine}] "
val e1 = Expression.Str(line, loc)
val e2 = visitExp(exp)
val concat = Expression.Binary(SemanticOperator.StringOp.Concat, e1, e2, Type.Str, e2.pur, e2.eff, loc)
mkApplyDebug(concat)
}

/**
Expand Down Expand Up @@ -1428,6 +1436,19 @@ object Lowering {
mkParChannels(tuple, chanSymsWithExps)
}

/**
* Applies the given expression `exp` to the `debug` function.
*/
private def mkApplyDebug(exp: Expression)(implicit root: Root, flix: Flix): Expression = {
//
// Note that we mark the call as impure (even though it may have been typed as pure!)
//
val loc = exp.loc
val tpe = Type.mkImpureArrow(exp.tpe, Type.Unit, loc)
val innerExp = Expression.Def(Defs.Debug, tpe, loc)
Expression.Apply(innerExp, List(exp), Type.Unit, Type.Impure, Type.Empty, loc)
}

/**
* Return a list of quantified variables in the given expression `exp0`.
*
Expand Down Expand Up @@ -1760,6 +1781,10 @@ object Lowering {
val e3 = substExp(exp3, subst)
Expression.ReifyEff(sym, e1, e2, e3, tpe, pur, eff, loc)

case Expression.Debug(exp, tpe, pur, eff, loc) =>
val e = substExp(exp, subst)
Expression.Debug(e, tpe, pur, eff, loc)

case Expression.FixpointConstraintSet(_, _, _, loc) => throw InternalCompilerException(s"Unexpected expression near ${loc.format}.")

}
Expand Down
4 changes: 4 additions & 0 deletions main/src/ca/uwaterloo/flix/language/phase/Monomorph.scala
Original file line number Diff line number Diff line change
Expand Up @@ -661,6 +661,10 @@ object Monomorph {
} else {
visitExp(exp3, env0)
}

case Expression.Debug(exp, tpe, pur, eff, loc) =>
val e = visitExp(exp, env0)
Expression.Debug(e, subst0(tpe), pur, eff, loc)
}

/**
Expand Down
Loading

0 comments on commit 61d7e00

Please sign in to comment.