mirror of
https://github.com/enso-org/enso.git
synced 2024-11-23 16:18:23 +03:00
Translate arith expressions using the new parser (#346)
This commit is contained in:
parent
d1796345a4
commit
b91ab25fdb
@ -645,6 +645,7 @@ object AST {
|
||||
}
|
||||
|
||||
object Text {
|
||||
val any = UnapplyByType[Text]
|
||||
|
||||
//// Definition ////
|
||||
|
||||
|
@ -0,0 +1,31 @@
|
||||
package org.enso.syntax.text
|
||||
|
||||
/** This object contains view patterns that allow matching on the parser AST for
|
||||
* more sophisticated constructs.
|
||||
*
|
||||
* These view patterns are implemented as custom unapply methods that only
|
||||
* return [[Some]] when more complex conditions are met.
|
||||
*/
|
||||
|
||||
object View {
|
||||
object Assignment {
|
||||
val assignmentOpSym = AST.Ident.Opr("=")
|
||||
|
||||
def unapply(ast: AST): Option[(AST, AST)] = {
|
||||
ast match {
|
||||
case AST.App.Infix.any(ast) => {
|
||||
val left = ast.larg
|
||||
val op = ast.opr
|
||||
val right = ast.rarg
|
||||
|
||||
if (op == assignmentOpSym) {
|
||||
Some((left, right))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
case _ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -14,7 +14,7 @@ class AtomFixtures extends InterpreterRunner {
|
||||
|}
|
||||
""".stripMargin
|
||||
|
||||
val generateList = eval(generateListCode)
|
||||
val generateList = evalOld(generateListCode)
|
||||
|
||||
val millionElementList = generateList.call(million)
|
||||
|
||||
@ -30,7 +30,7 @@ class AtomFixtures extends InterpreterRunner {
|
||||
|}
|
||||
""".stripMargin
|
||||
|
||||
val reverseList = eval(reverseListCode)
|
||||
val reverseList = evalOld(reverseListCode)
|
||||
|
||||
val reverseListMethodsCode =
|
||||
"""
|
||||
@ -43,7 +43,7 @@ class AtomFixtures extends InterpreterRunner {
|
||||
|{ |list| @reverse [list, @Nil] }
|
||||
|""".stripMargin
|
||||
|
||||
val reverseListMethods = eval(reverseListMethodsCode)
|
||||
val reverseListMethods = evalOld(reverseListMethodsCode)
|
||||
|
||||
val sumListCode =
|
||||
"""
|
||||
@ -57,7 +57,7 @@ class AtomFixtures extends InterpreterRunner {
|
||||
|}
|
||||
""".stripMargin
|
||||
|
||||
val sumList = eval(sumListCode)
|
||||
val sumList = evalOld(sumListCode)
|
||||
|
||||
val sumListLeftFoldCode =
|
||||
"""
|
||||
@ -72,7 +72,7 @@ class AtomFixtures extends InterpreterRunner {
|
||||
|}
|
||||
""".stripMargin
|
||||
|
||||
val sumListLeftFold = eval(sumListLeftFoldCode)
|
||||
val sumListLeftFold = evalOld(sumListLeftFoldCode)
|
||||
|
||||
val sumListFallbackCode =
|
||||
"""
|
||||
@ -86,7 +86,7 @@ class AtomFixtures extends InterpreterRunner {
|
||||
|}
|
||||
""".stripMargin
|
||||
|
||||
val sumListFallback = eval(sumListFallbackCode)
|
||||
val sumListFallback = evalOld(sumListFallbackCode)
|
||||
|
||||
val sumListMethodsCode =
|
||||
"""
|
||||
@ -98,7 +98,7 @@ class AtomFixtures extends InterpreterRunner {
|
||||
|{ |list| @sum [list, 0] }
|
||||
|""".stripMargin
|
||||
|
||||
val sumListMethods = eval(sumListMethodsCode)
|
||||
val sumListMethods = evalOld(sumListMethodsCode)
|
||||
|
||||
val mapReverseListCode =
|
||||
"""
|
||||
@ -110,7 +110,7 @@ class AtomFixtures extends InterpreterRunner {
|
||||
|{ |list| @mapReverse [list, { |x| x + 1 }, @Nil] }
|
||||
|""".stripMargin
|
||||
|
||||
val mapReverseList = eval(mapReverseListCode)
|
||||
val mapReverseList = evalOld(mapReverseListCode)
|
||||
|
||||
val mapReverseListCurryCode =
|
||||
"""
|
||||
@ -125,5 +125,5 @@ class AtomFixtures extends InterpreterRunner {
|
||||
|}
|
||||
|""".stripMargin
|
||||
|
||||
val mapReverseListCurry = eval(mapReverseListCurryCode)
|
||||
val mapReverseListCurry = evalOld(mapReverseListCurryCode)
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ class NamedDefaultedArgumentFixtures extends InterpreterRunner {
|
||||
|}
|
||||
""".stripMargin
|
||||
|
||||
val sumTCOWithNamedArguments = eval(sumTCOWithNamedArgumentsCode)
|
||||
val sumTCOWithNamedArguments = evalOld(sumTCOWithNamedArgumentsCode)
|
||||
|
||||
val sumTCOWithDefaultedArgumentsCode =
|
||||
"""
|
||||
@ -29,6 +29,6 @@ class NamedDefaultedArgumentFixtures extends InterpreterRunner {
|
||||
|}
|
||||
""".stripMargin
|
||||
|
||||
val sumTCOWithDefaultedArguments = eval(sumTCOWithDefaultedArgumentsCode)
|
||||
val sumTCOWithDefaultedArguments = evalOld(sumTCOWithDefaultedArgumentsCode)
|
||||
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ class RecursionFixtures extends InterpreterRunner {
|
||||
|}
|
||||
|""".stripMargin
|
||||
|
||||
val sumTCOFoldLike = eval(sumTCOFoldLikeCode)
|
||||
val sumTCOFoldLike = evalOld(sumTCOFoldLikeCode)
|
||||
|
||||
val sumRecursiveCode =
|
||||
"""
|
||||
@ -82,7 +82,7 @@ class RecursionFixtures extends InterpreterRunner {
|
||||
|}
|
||||
|""".stripMargin
|
||||
|
||||
val sumStateTCO = eval(sumStateTCOCode)
|
||||
val sumStateTCO = evalOld(sumStateTCOCode)
|
||||
|
||||
val sumTCOWithEvalCode =
|
||||
"""
|
||||
@ -94,5 +94,5 @@ class RecursionFixtures extends InterpreterRunner {
|
||||
| res
|
||||
|}
|
||||
|""".stripMargin
|
||||
val sumTCOWithEval = eval(sumTCOWithEvalCode)
|
||||
val sumTCOWithEval = evalOld(sumTCOWithEvalCode)
|
||||
}
|
||||
|
@ -20,4 +20,9 @@ public class Constants {
|
||||
public static final String THUNK_EXECUTOR_NODE = "10";
|
||||
public static final String EVAL_NODE = "10";
|
||||
}
|
||||
|
||||
/** Constants used for debugging only. */
|
||||
public static class Debug {
|
||||
public static final String MIME_TYPE = "application/x-enso-old";
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ import org.graalvm.options.OptionDescriptors;
|
||||
implementationName = Constants.IMPL_NAME,
|
||||
version = Constants.LANGUAGE_VERSION,
|
||||
defaultMimeType = Constants.MIME_TYPE,
|
||||
characterMimeTypes = Constants.MIME_TYPE,
|
||||
characterMimeTypes = {Constants.MIME_TYPE, Constants.Debug.MIME_TYPE},
|
||||
contextPolicy = TruffleLanguage.ContextPolicy.SHARED,
|
||||
fileTypeDetectors = FileDetector.class)
|
||||
@ProvidedTags({
|
||||
|
@ -26,7 +26,8 @@ public final class FileDetector implements TruffleFile.FileTypeDetector {
|
||||
public String findMimeType(TruffleFile file) throws IOException {
|
||||
String name = file.getName();
|
||||
if (name != null && name.endsWith(Constants.FILE_EXTENSION)) {
|
||||
return Constants.MIME_TYPE;
|
||||
// TODO [AA] Once the new connection is complete remove this
|
||||
return Constants.Debug.MIME_TYPE;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -2,13 +2,10 @@ package org.enso.compiler
|
||||
|
||||
import com.oracle.truffle.api.TruffleFile
|
||||
import com.oracle.truffle.api.source.Source
|
||||
import org.enso.compiler.generate.AstToIr
|
||||
import org.enso.compiler.generate.AstToAstExpression
|
||||
import org.enso.compiler.core.IR
|
||||
import org.enso.flexer.Reader
|
||||
import org.enso.interpreter.AstExpression
|
||||
import org.enso.interpreter.Constants
|
||||
import org.enso.interpreter.EnsoParser
|
||||
import org.enso.interpreter.Language
|
||||
import org.enso.interpreter.{AstExpression, AstModuleScope, Constants, EnsoParser, Language}
|
||||
import org.enso.interpreter.builder.ExpressionFactory
|
||||
import org.enso.interpreter.builder.ModuleScopeExpressionFactory
|
||||
import org.enso.interpreter.node.ExpressionNode
|
||||
@ -45,19 +42,18 @@ class Compiler(
|
||||
* executable functionality in the module corresponding to `source`.
|
||||
*/
|
||||
def run(source: Source, scope: ModuleScope): ExpressionNode = {
|
||||
/* TODO [AA] Introduce this next task
|
||||
* val parsedAST: AST = parse(source)
|
||||
* val convertedIR: ExpressionNode = translate(parsedAST)
|
||||
*/
|
||||
val mimeType = source.getMimeType
|
||||
|
||||
val parsed =
|
||||
val expr: AstModuleScope = if (mimeType == Constants.MIME_TYPE) {
|
||||
val parsedAST: AST = parse(source)
|
||||
translate(parsedAST)
|
||||
} else {
|
||||
new EnsoParser().parseEnso(source.getCharacters.toString)
|
||||
}
|
||||
|
||||
new ModuleScopeExpressionFactory(language, scope).run(parsed)
|
||||
new ModuleScopeExpressionFactory(language, scope).run(expr)
|
||||
}
|
||||
|
||||
// TODO [AA] This needs to evolve to support scope execution
|
||||
|
||||
/**
|
||||
* Processes the language sources in the provided file, registering any
|
||||
* bindings in the given scope.
|
||||
@ -166,5 +162,6 @@ class Compiler(
|
||||
* @return an IR representation with a 1:1 mapping to the parser AST
|
||||
* constructs
|
||||
*/
|
||||
def translate(sourceAST: AST): IR = AstToIr.process(sourceAST)
|
||||
def translate(sourceAST: AST): AstModuleScope =
|
||||
AstToAstExpression.translate(sourceAST)
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import org.enso.compiler.core.IR.Literal.Text
|
||||
import org.enso.syntax.text.AST
|
||||
import org.enso.syntax.text.ast.text.Escape
|
||||
|
||||
// TODO [AA] REMOVE THIS ENTIRE FILE ONCE WE HAVE NEW CORE
|
||||
/**
|
||||
* This is the compiler's high-level intermediate representation.
|
||||
*
|
||||
|
@ -0,0 +1,374 @@
|
||||
package org.enso.compiler.generate
|
||||
|
||||
import org.enso.compiler.exception.UnhandledEntity
|
||||
import org.enso.compiler.core.IR
|
||||
import org.enso.interpreter.{
|
||||
AstArithOp,
|
||||
AstExpression,
|
||||
AstImport,
|
||||
AstLong,
|
||||
AstModuleScope,
|
||||
AstModuleSymbol
|
||||
}
|
||||
import org.enso.syntax.text.{AST, Debug}
|
||||
|
||||
// TODO [AA] Please note that this entire translation is _very_ work-in-progress
|
||||
// and is hence quite ugly right now. It will be cleaned up as work progresses,
|
||||
// but it was thought best to land in increments where possible.
|
||||
|
||||
/**
|
||||
* This is a representation of the raw conversion from the Parser [[AST AST]]
|
||||
* to the internal [[IR IR]] used by the static transformation passes.
|
||||
*/
|
||||
object AstToAstExpression {
|
||||
|
||||
/**
|
||||
* Transforms the input [[AST]] into the compiler's high-level intermediate
|
||||
* representation.
|
||||
*
|
||||
* @param inputAST the AST to transform
|
||||
* @return a representation of the program construct represented by
|
||||
* `inputAST` in the compiler's [[IR IR]]
|
||||
*/
|
||||
def translate(inputAST: AST): AstModuleScope = {
|
||||
// println(Debug.pretty(inputAST.toString))
|
||||
// println("=========================================")
|
||||
|
||||
inputAST match {
|
||||
case AST.Module.any(inputAST) => translateModule(inputAST)
|
||||
case _ => {
|
||||
throw new UnhandledEntity(inputAST, "process")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def translateModuleSymbol(inputAST: AST): AstModuleSymbol = {
|
||||
???
|
||||
}
|
||||
|
||||
def translateLiteral(literal: AST.Literal): AstLong = {
|
||||
literal match {
|
||||
case AST.Literal.Number(base, number) => {
|
||||
if (base.isDefined && base.get != "10") {
|
||||
throw new RuntimeException("Only base 10 is currently supported")
|
||||
}
|
||||
|
||||
AstLong(number.toLong)
|
||||
}
|
||||
// case AST.Literal.Text.any(literal) =>
|
||||
case _ => throw new UnhandledEntity(literal, "processLiteral")
|
||||
}
|
||||
}
|
||||
|
||||
def translateApplication(application: AST): AstExpression = {
|
||||
application match {
|
||||
case AST.App.Infix(left, fn, right) => {
|
||||
// FIXME [AA] We should accept all ops when translating to core
|
||||
val validInfixOps = List("+", "/", "-", "*", "%")
|
||||
|
||||
if (validInfixOps.contains(fn.name)) {
|
||||
AstArithOp(
|
||||
fn.name,
|
||||
translateExpression(left),
|
||||
translateExpression(right)
|
||||
)
|
||||
} else {
|
||||
throw new RuntimeException(
|
||||
s"${fn.name} is not currently a valid infix operator"
|
||||
)
|
||||
}
|
||||
}
|
||||
// case AST.App.Prefix(fn, arg) =>
|
||||
// case AST.App.Section.any(application) => // TODO [AA] left, sides, right
|
||||
// case AST.Mixfix(application) => // TODO [AA] translate if
|
||||
case _ => throw new UnhandledEntity(application, "translateApplication")
|
||||
}
|
||||
}
|
||||
|
||||
def translateExpression(inputAST: AST): AstExpression = {
|
||||
inputAST match {
|
||||
case AST.App.any(inputAST) => translateApplication(inputAST)
|
||||
case AST.Literal.any(inputAST) => translateLiteral(inputAST)
|
||||
case AST.Group.any(inputAST) => translateGroup(inputAST)
|
||||
case _ =>
|
||||
throw new UnhandledEntity(inputAST, "translateExpression")
|
||||
}
|
||||
// inputAST match {
|
||||
// case AST.App.any(inputAST) => processApplication(inputAST)
|
||||
// case AST.Block.any(inputAST) => processBlock(inputAST)
|
||||
// case AST.Comment.any(inputAST) => processComment(inputAST)
|
||||
// case AST.Ident.any(inputAST) => processIdent(inputAST)
|
||||
// case AST.Import.any(inputAST) => processBinding(inputAST)
|
||||
// case AST.Invalid.any(inputAST) => processInvalid(inputAST)
|
||||
// case AST.Literal.any(inputAST) => processLiteral(inputAST)
|
||||
// case AST.Mixfix.any(inputAST) => processApplication(inputAST)
|
||||
// case AST.Group.any(inputAST) => processGroup(inputAST)
|
||||
// case AST.Def.any(inputAST) => processBinding(inputAST)
|
||||
// case AST.Foreign.any(inputAST) => processBlock(inputAST)
|
||||
// case _ =>
|
||||
// IR.Error.UnhandledAST(inputAST)
|
||||
// }
|
||||
}
|
||||
|
||||
def translateGroup(group: AST.Group): AstExpression = {
|
||||
group.body match {
|
||||
case Some(ast) => translateExpression(ast)
|
||||
case None => {
|
||||
// FIXME [AA] This should generate an error node in core
|
||||
throw new RuntimeException("Empty group")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO [AA] Fix the types
|
||||
def translateModule(module: AST.Module): AstModuleScope = {
|
||||
module match {
|
||||
case AST.Module(blocks) => {
|
||||
val presentBlocks = blocks.collect {
|
||||
case t if t.elem.isDefined => t.elem.get
|
||||
}
|
||||
|
||||
val imports = presentBlocks.collect {
|
||||
case AST.Import.any(list) => translateImport(list)
|
||||
}
|
||||
|
||||
val nonImportBlocks = presentBlocks.filter {
|
||||
case AST.Import.any(_) => false
|
||||
case _ => true
|
||||
}
|
||||
|
||||
if (nonImportBlocks.isEmpty) {
|
||||
// FIXME [AA] This is temporary, and should be moved to generate an
|
||||
// error node in Core.
|
||||
throw new RuntimeException("Cannot have no expressions")
|
||||
}
|
||||
|
||||
val statements = nonImportBlocks.dropRight(1).map(translateModuleSymbol)
|
||||
val expression = translateExpression(nonImportBlocks.last)
|
||||
AstModuleScope(imports, statements, expression)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def translateImport(imp: AST.Import): AstImport = {
|
||||
AstImport(imp.path.map(t => t.name).reduceLeft((l, r) => l + "." + r))
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms invalid entities from the parser AST.
|
||||
*
|
||||
* @param invalid the invalid entity
|
||||
* @return a representation of `invalid` in the compiler's [[IR IR]]
|
||||
*/
|
||||
def processInvalid(invalid: AST.Invalid): IR.Error = {
|
||||
???
|
||||
// invalid match {
|
||||
// case AST.Invalid.Unexpected(str, unexpectedTokens) =>
|
||||
// IR.Error.UnexpectedToken(str, unexpectedTokens.map(t => process(t.el)))
|
||||
// case AST.Invalid.Unrecognized(str) => IR.Error.UnrecognisedSymbol(str)
|
||||
// case AST.Ident.InvalidSuffix(identifier, suffix) =>
|
||||
// IR.Error.InvalidSuffix(processIdent(identifier), suffix)
|
||||
// case AST.Literal.Text.Unclosed(AST.Literal.Text.Line.Raw(text)) =>
|
||||
// IR.Error.UnclosedText(List(processLine(text)))
|
||||
// case AST.Literal.Text.Unclosed(AST.Literal.Text.Line.Fmt(text)) =>
|
||||
// IR.Error.UnclosedText(List(processLine(text)))
|
||||
// case _ =>
|
||||
// throw new RuntimeException(
|
||||
// "Fatal: Unhandled entity in processInvalid = " + invalid
|
||||
// )
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms identifiers from the parser AST.
|
||||
*
|
||||
* @param identifier the identifier
|
||||
* @return a representation of `identifier` in the compiler's [[IR IR]]
|
||||
*/
|
||||
def processIdent(identifier: AST.Ident): IR.Identifier = {
|
||||
???
|
||||
// identifier match {
|
||||
// case AST.Ident.Blank(_) => IR.Identifier.Blank()
|
||||
// case AST.Ident.Var(name) => IR.Identifier.Variable(name)
|
||||
// case AST.Ident.Cons.any(identifier) => processIdentConstructor(identifier)
|
||||
// case AST.Ident.Opr.any(identifier) => processIdentOperator(identifier)
|
||||
// case AST.Ident.Mod(name) => IR.Identifier.Module(name)
|
||||
// case _ =>
|
||||
// throw new RuntimeException(
|
||||
// "Fatal: Unhandled entity in processIdent = " + identifier
|
||||
// )
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms an operator identifier from the parser AST.
|
||||
*
|
||||
* @param operator the operator to transform
|
||||
* @return a representation of `operator` in the compiler's [[IR IR]]
|
||||
*/
|
||||
def processIdentOperator(
|
||||
operator: AST.Ident.Opr
|
||||
): IR.Identifier.Operator = {
|
||||
???
|
||||
// IR.Identifier.Operator(operator.name)
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a constructor identifier from the parser AST.
|
||||
*
|
||||
* @param constructor the constructor name to transform
|
||||
* @return a representation of `constructor` in the compiler's [[IR IR]]
|
||||
*/
|
||||
def processIdentConstructor(
|
||||
constructor: AST.Ident.Cons
|
||||
): IR.Identifier.Constructor = {
|
||||
???
|
||||
// IR.Identifier.Constructor(constructor.name)
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a line of a text literal from the parser AST.
|
||||
*
|
||||
* @param line the literal line to transform
|
||||
* @return a representation of `line` in the compiler's [[IR IR]]
|
||||
*/
|
||||
def processLine(
|
||||
line: List[AST.Literal.Text.Segment[AST]]
|
||||
): IR.Literal.Text.Line = {
|
||||
???
|
||||
// IR.Literal.Text.Line(line.map(processTextSegment))
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a segment of text from the parser AST.
|
||||
*
|
||||
* @param segment the text segment to transform
|
||||
* @return a representation of `segment` in the compiler's [[IR IR]]
|
||||
*/
|
||||
def processTextSegment(
|
||||
segment: AST.Literal.Text.Segment[AST]
|
||||
): IR.Literal.Text.Segment = {
|
||||
???
|
||||
// segment match {
|
||||
// case AST.Literal.Text.Segment._Plain(str) =>
|
||||
// IR.Literal.Text.Segment.Plain(str)
|
||||
// case AST.Literal.Text.Segment._Expr(expr) =>
|
||||
// IR.Literal.Text.Segment.Expression(expr.map(process))
|
||||
// case AST.Literal.Text.Segment._Escape(code) =>
|
||||
// IR.Literal.Text.Segment.EscapeCode(code)
|
||||
// case _ => throw new UnhandledEntity(segment, "processTextSegment")
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a function application from the parser AST.
|
||||
*
|
||||
* @param application the function application to transform
|
||||
* @return a representation of `application` in the compiler's [[IR IR]]
|
||||
*/
|
||||
def processApplication(application: AST): IR.Application = {
|
||||
???
|
||||
// application match {
|
||||
// case AST.App.Prefix(fn, arg) =>
|
||||
// IR.Application.Prefix(process(fn), process(arg))
|
||||
// case AST.App.Infix(leftArg, fn, rightArg) =>
|
||||
// IR.Application.Infix(
|
||||
// process(leftArg),
|
||||
// processIdentOperator(fn),
|
||||
// process(rightArg)
|
||||
// )
|
||||
// case AST.App.Section.Left(arg, fn) =>
|
||||
// IR.Application.Section.Left(process(arg), processIdentOperator(fn))
|
||||
// case AST.App.Section.Right(fn, arg) =>
|
||||
// IR.Application.Section.Right(processIdentOperator(fn), process(arg))
|
||||
// case AST.App.Section.Sides(fn) =>
|
||||
// IR.Application.Section.Sides(processIdentOperator(fn))
|
||||
// case AST.Mixfix(fnSegments, args) =>
|
||||
// IR.Application
|
||||
// .Mixfix(fnSegments.toList.map(processIdent), args.toList.map(process))
|
||||
// case _ =>
|
||||
// throw new UnhandledEntity(application, "processApplication")
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a source code block from the parser AST.
|
||||
*
|
||||
* This handles both blocks of Enso-native code, and blocks of foreign
|
||||
* language code.
|
||||
*
|
||||
* @param block the block to transform
|
||||
* @return a representation of `block` in the compiler's [[IR IR]]
|
||||
*/
|
||||
def processBlock(block: AST): IR.Block = {
|
||||
???
|
||||
// block match {
|
||||
// case AST.Block(_, _, firstLine, lines) =>
|
||||
// IR.Block
|
||||
// .Enso(
|
||||
// process(firstLine.elem) ::
|
||||
// lines.filter(t => t.elem.isDefined).map(t => process(t.elem.get))
|
||||
// )
|
||||
// case AST.Foreign(_, language, code) => IR.Block.Foreign(language, code)
|
||||
// case _ => throw new UnhandledEntity(block, "processBlock")
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a module top-level from the parser AST.
|
||||
*
|
||||
* @param module the module to transform
|
||||
* @return a representation of `module` in the compiler's [[IR IR]]
|
||||
*/
|
||||
def processModule(module: AST.Module): IR.Module = {
|
||||
???
|
||||
// module match {
|
||||
// case AST.Module(lines) =>
|
||||
// IR.Module(
|
||||
// lines.filter(t => t.elem.isDefined).map(t => process(t.elem.get))
|
||||
// )
|
||||
// case _ => throw new UnhandledEntity(module, "processModule")
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a comment from the parser AST.
|
||||
*
|
||||
* @param comment the comment to transform
|
||||
* @return a representation of `comment` in the compiler's [[IR IR]]
|
||||
*/
|
||||
def processComment(comment: AST): IR.Comment = {
|
||||
???
|
||||
// comment match {
|
||||
// case AST.Comment(lines) => IR.Comment(lines)
|
||||
// case _ => throw new UnhandledEntity(comment, "processComment")
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a binding from the parser AST.
|
||||
*
|
||||
* Bindings are any constructs that give some Enso language construct a name.
|
||||
* This includes type definitions, imports, assignments, and so on.
|
||||
*
|
||||
* @param binding the binding to transform
|
||||
* @return a representation of `binding` in the compiler's [[IR IR]]
|
||||
*/
|
||||
def processBinding(binding: AST): IR.Binding = {
|
||||
???
|
||||
// binding match {
|
||||
// case AST.Def(constructor, arguments, optBody) =>
|
||||
// IR.Binding.RawType(
|
||||
// processIdentConstructor(constructor),
|
||||
// arguments.map(process),
|
||||
// optBody.map(process)
|
||||
// )
|
||||
// case AST.Import(components) => {
|
||||
// IR.Binding.Import(
|
||||
// components.toList.map(t => processIdentConstructor(t))
|
||||
// )
|
||||
// }
|
||||
// case _ => throw new UnhandledEntity(binding, "processBinding")
|
||||
// }
|
||||
}
|
||||
}
|
@ -1,264 +0,0 @@
|
||||
package org.enso.compiler.generate
|
||||
|
||||
import org.enso.compiler.exception.UnhandledEntity
|
||||
import org.enso.compiler.core.IR
|
||||
import org.enso.syntax.text.AST
|
||||
|
||||
/**
|
||||
* This is a representation of the raw conversion from the Parser [[AST AST]]
|
||||
* to the internal [[IR IR]] used by the static transformation passes.
|
||||
*/
|
||||
object AstToIr {
|
||||
|
||||
/**
|
||||
* Transforms the input [[AST]] into the compiler's high-level intermediate
|
||||
* representation.
|
||||
*
|
||||
* @param inputAST the AST to transform
|
||||
* @return a representation of the program construct represented by
|
||||
* `inputAST` in the compiler's [[IR IR]]
|
||||
*/
|
||||
def process(inputAST: AST): IR = inputAST match {
|
||||
case AST.App.any(inputAST) => processApplication(inputAST)
|
||||
case AST.Block.any(inputAST) => processBlock(inputAST)
|
||||
case AST.Comment.any(inputAST) => processComment(inputAST)
|
||||
case AST.Ident.any(inputAST) => processIdent(inputAST)
|
||||
case AST.Import.any(inputAST) => processBinding(inputAST)
|
||||
case AST.Invalid.any(inputAST) => processInvalid(inputAST)
|
||||
case AST.Literal.any(inputAST) => processLiteral(inputAST)
|
||||
case AST.Mixfix.any(inputAST) => processApplication(inputAST)
|
||||
case AST.Module.any(inputAST) => processModule(inputAST)
|
||||
case AST.Group.any(inputAST) => processGroup(inputAST)
|
||||
case AST.Def.any(inputAST) => processBinding(inputAST)
|
||||
case AST.Foreign.any(inputAST) => processBlock(inputAST)
|
||||
case _ =>
|
||||
IR.Error.UnhandledAST(inputAST)
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms invalid entities from the parser AST.
|
||||
*
|
||||
* @param invalid the invalid entity
|
||||
* @return a representation of `invalid` in the compiler's [[IR IR]]
|
||||
*/
|
||||
def processInvalid(invalid: AST.Invalid): IR.Error = invalid match {
|
||||
case AST.Invalid.Unexpected(str, unexpectedTokens) =>
|
||||
IR.Error.UnexpectedToken(str, unexpectedTokens.map(t => process(t.el)))
|
||||
case AST.Invalid.Unrecognized(str) => IR.Error.UnrecognisedSymbol(str)
|
||||
case AST.Ident.InvalidSuffix(identifier, suffix) =>
|
||||
IR.Error.InvalidSuffix(processIdent(identifier), suffix)
|
||||
case AST.Literal.Text.Unclosed(AST.Literal.Text.Line.Raw(text)) =>
|
||||
IR.Error.UnclosedText(List(processLine(text)))
|
||||
case AST.Literal.Text.Unclosed(AST.Literal.Text.Line.Fmt(text)) =>
|
||||
IR.Error.UnclosedText(List(processLine(text)))
|
||||
case _ =>
|
||||
throw new RuntimeException(
|
||||
"Fatal: Unhandled entity in processInvalid = " + invalid
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms identifiers from the parser AST.
|
||||
*
|
||||
* @param identifier the identifier
|
||||
* @return a representation of `identifier` in the compiler's [[IR IR]]
|
||||
*/
|
||||
def processIdent(identifier: AST.Ident): IR.Identifier = identifier match {
|
||||
case AST.Ident.Blank(_) => IR.Identifier.Blank()
|
||||
case AST.Ident.Var(name) => IR.Identifier.Variable(name)
|
||||
case AST.Ident.Cons.any(identifier) => processIdentConstructor(identifier)
|
||||
case AST.Ident.Opr.any(identifier) => processIdentOperator(identifier)
|
||||
case AST.Ident.Mod(name) => IR.Identifier.Module(name)
|
||||
case _ =>
|
||||
throw new RuntimeException(
|
||||
"Fatal: Unhandled entity in processIdent = " + identifier
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms an operator identifier from the parser AST.
|
||||
*
|
||||
* @param operator the operator to transform
|
||||
* @return a representation of `operator` in the compiler's [[IR IR]]
|
||||
*/
|
||||
def processIdentOperator(
|
||||
operator: AST.Ident.Opr
|
||||
): IR.Identifier.Operator = IR.Identifier.Operator(operator.name)
|
||||
|
||||
/**
|
||||
* Transforms a constructor identifier from the parser AST.
|
||||
*
|
||||
* @param constructor the constructor name to transform
|
||||
* @return a representation of `constructor` in the compiler's [[IR IR]]
|
||||
*/
|
||||
def processIdentConstructor(
|
||||
constructor: AST.Ident.Cons
|
||||
): IR.Identifier.Constructor = IR.Identifier.Constructor(constructor.name)
|
||||
|
||||
/**
|
||||
* Transforms a literal from the parser AST.
|
||||
*
|
||||
* @param literal the literal to transform
|
||||
* @return a representation of `literal` in the compiler's [[IR IR]]
|
||||
*/
|
||||
def processLiteral(literal: AST.Literal): IR.Literal = {
|
||||
literal match {
|
||||
case AST.Literal.Number(base, number) => IR.Literal.Number(number, base)
|
||||
|
||||
// TODO [AA] Handle text properly
|
||||
// case AST.Literal.Text.Raw(body) =>
|
||||
// IR.Literal.Text.Raw(body.lines.toList.map(processLine))
|
||||
//
|
||||
// case AST.Literal.Text.Line.Fmt(lines) =>
|
||||
// IR.Literal.Text.Format(lines.toList.map(processLine))
|
||||
|
||||
case _ => throw new UnhandledEntity(literal, "processLiteral")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a line of a text literal from the parser AST.
|
||||
*
|
||||
* @param line the literal line to transform
|
||||
* @return a representation of `line` in the compiler's [[IR IR]]
|
||||
*/
|
||||
def processLine(
|
||||
line: List[AST.Literal.Text.Segment[AST]]
|
||||
): IR.Literal.Text.Line =
|
||||
IR.Literal.Text.Line(line.map(processTextSegment))
|
||||
|
||||
/**
|
||||
* Transforms a segment of text from the parser AST.
|
||||
*
|
||||
* @param segment the text segment to transform
|
||||
* @return a representation of `segment` in the compiler's [[IR IR]]
|
||||
*/
|
||||
def processTextSegment(
|
||||
segment: AST.Literal.Text.Segment[AST]
|
||||
): IR.Literal.Text.Segment = segment match {
|
||||
case AST.Literal.Text.Segment._Plain(str) =>
|
||||
IR.Literal.Text.Segment.Plain(str)
|
||||
case AST.Literal.Text.Segment._Expr(expr) =>
|
||||
IR.Literal.Text.Segment.Expression(expr.map(process))
|
||||
case AST.Literal.Text.Segment._Escape(code) =>
|
||||
IR.Literal.Text.Segment.EscapeCode(code)
|
||||
case _ => throw new UnhandledEntity(segment, "processTextSegment")
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a function application from the parser AST.
|
||||
*
|
||||
* @param application the function application to transform
|
||||
* @return a representation of `application` in the compiler's [[IR IR]]
|
||||
*/
|
||||
def processApplication(application: AST): IR.Application =
|
||||
application match {
|
||||
case AST.App.Prefix(fn, arg) =>
|
||||
IR.Application.Prefix(process(fn), process(arg))
|
||||
case AST.App.Infix(leftArg, fn, rightArg) =>
|
||||
IR.Application.Infix(
|
||||
process(leftArg),
|
||||
processIdentOperator(fn),
|
||||
process(rightArg)
|
||||
)
|
||||
case AST.App.Section.Left(arg, fn) =>
|
||||
IR.Application.Section.Left(process(arg), processIdentOperator(fn))
|
||||
case AST.App.Section.Right(fn, arg) =>
|
||||
IR.Application.Section.Right(processIdentOperator(fn), process(arg))
|
||||
case AST.App.Section.Sides(fn) =>
|
||||
IR.Application.Section.Sides(processIdentOperator(fn))
|
||||
case AST.Mixfix(fnSegments, args) =>
|
||||
IR.Application
|
||||
.Mixfix(fnSegments.toList.map(processIdent), args.toList.map(process))
|
||||
case _ =>
|
||||
throw new UnhandledEntity(application, "processApplication")
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a source code block from the parser AST.
|
||||
*
|
||||
* This handles both blocks of Enso-native code, and blocks of foreign
|
||||
* language code.
|
||||
*
|
||||
* @param block the block to transform
|
||||
* @return a representation of `block` in the compiler's [[IR IR]]
|
||||
*/
|
||||
def processBlock(block: AST): IR.Block = block match {
|
||||
case AST.Block(_, _, firstLine, lines) =>
|
||||
IR.Block
|
||||
.Enso(
|
||||
process(firstLine.elem) ::
|
||||
lines.filter(t => t.elem.isDefined).map(t => process(t.elem.get))
|
||||
)
|
||||
case AST.Foreign(_, language, code) => IR.Block.Foreign(language, code)
|
||||
case _ => throw new UnhandledEntity(block, "processBlock")
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a module top-level from the parser AST.
|
||||
*
|
||||
* @param module the module to transform
|
||||
* @return a representation of `module` in the compiler's [[IR IR]]
|
||||
*/
|
||||
def processModule(module: AST.Module): IR.Module = module match {
|
||||
case AST.Module(lines) =>
|
||||
IR.Module(
|
||||
lines.filter(t => t.elem.isDefined).map(t => process(t.elem.get))
|
||||
)
|
||||
case _ => throw new UnhandledEntity(module, "processModule")
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a comment from the parser AST.
|
||||
*
|
||||
* @param comment the comment to transform
|
||||
* @return a representation of `comment` in the compiler's [[IR IR]]
|
||||
*/
|
||||
def processComment(comment: AST): IR.Comment = comment match {
|
||||
case AST.Comment(lines) => IR.Comment(lines)
|
||||
case _ => throw new UnhandledEntity(comment, "processComment")
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a group from the parser AST.
|
||||
*
|
||||
* In [[IR]], groups are actually non-entities, as all grouping is handled
|
||||
* implicitly by the IR format. A valid group is replaced by its contents in
|
||||
* the IR, while invalid groups are replaced by error nodes.
|
||||
*
|
||||
* @param group the group to transform
|
||||
* @return a representation of `group` in the compiler's [[IR IR]]
|
||||
*/
|
||||
def processGroup(group: AST): IR = group match {
|
||||
case AST.Group(maybeAST) =>
|
||||
maybeAST match {
|
||||
case Some(ast) => process(ast)
|
||||
case None => IR.Error.EmptyGroup()
|
||||
}
|
||||
case _ => throw new UnhandledEntity(group, "processGroup")
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a binding from the parser AST.
|
||||
*
|
||||
* Bindings are any constructs that give some Enso language construct a name.
|
||||
* This includes type definitions, imports, assignments, and so on.
|
||||
*
|
||||
* @param binding the binding to transform
|
||||
* @return a representation of `binding` in the compiler's [[IR IR]]
|
||||
*/
|
||||
def processBinding(binding: AST): IR.Binding = binding match {
|
||||
case AST.Def(constructor, arguments, optBody) =>
|
||||
IR.Binding.RawType(
|
||||
processIdentConstructor(constructor),
|
||||
arguments.map(process),
|
||||
optBody.map(process)
|
||||
)
|
||||
case AST.Import(components) => {
|
||||
IR.Binding.Import(
|
||||
components.toList.map(t => processIdentConstructor(t))
|
||||
)
|
||||
}
|
||||
case _ => throw new UnhandledEntity(binding, "processBinding")
|
||||
}
|
||||
}
|
@ -59,21 +59,21 @@ trait AstModuleScopeVisitor[+T] {
|
||||
): T
|
||||
}
|
||||
|
||||
sealed trait AstGlobalSymbol
|
||||
sealed trait AstModuleSymbol
|
||||
|
||||
case class AstTypeDef(name: String, arguments: List[AstArgDefinition])
|
||||
extends AstGlobalSymbol {
|
||||
extends AstModuleSymbol {
|
||||
def getArguments: java.util.List[AstArgDefinition] = arguments.asJava
|
||||
}
|
||||
|
||||
case class AstMethodDef(typeName: String, methodName: String, fun: AstFunction)
|
||||
extends AstGlobalSymbol
|
||||
extends AstModuleSymbol
|
||||
|
||||
case class AstImport(name: String)
|
||||
|
||||
case class AstModuleScope(
|
||||
imports: List[AstImport],
|
||||
bindings: List[AstGlobalSymbol],
|
||||
bindings: List[AstModuleSymbol],
|
||||
expression: AstExpression
|
||||
) {
|
||||
|
||||
@ -330,7 +330,7 @@ class EnsoParserInternal extends JavaTokenParsers {
|
||||
|
||||
def statement: Parser[AstExpression] = assignment | expression
|
||||
|
||||
def typeDef: Parser[AstGlobalSymbol] =
|
||||
def typeDef: Parser[AstModuleSymbol] =
|
||||
"type" ~> ident ~ ((argDefinition | ("(" ~> argDefinition <~ ")")) *) <~ ";" ^^ {
|
||||
case name ~ args => AstTypeDef(name, args)
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
package org.enso.interpreter.test
|
||||
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.{ByteArrayOutputStream, StringReader}
|
||||
|
||||
import org.enso.interpreter.Constants
|
||||
import org.graalvm.polyglot.{Context, Source, Value}
|
||||
import org.enso.interpreter.instrument.ReplDebuggerInstrument
|
||||
import org.graalvm.polyglot.{Context, Value}
|
||||
import org.scalatest.{FlatSpec, Matchers}
|
||||
|
||||
trait InterpreterRunner {
|
||||
@ -17,9 +17,23 @@ trait InterpreterRunner {
|
||||
val output = new ByteArrayOutputStream()
|
||||
val ctx = Context.newBuilder(Constants.LANGUAGE_ID).out(output).build()
|
||||
|
||||
def eval(code: String): Value = {
|
||||
def evalGeneric(code: String, mimeType: String): Value = {
|
||||
output.reset()
|
||||
InterpreterException.rethrowPolyglot(ctx.eval(Constants.LANGUAGE_ID, code))
|
||||
|
||||
val source = Source
|
||||
.newBuilder(Constants.LANGUAGE_ID, new StringReader(code), "test")
|
||||
.mimeType(mimeType)
|
||||
.build()
|
||||
|
||||
InterpreterException.rethrowPolyglot(ctx.eval(source))
|
||||
}
|
||||
|
||||
def eval(code: String): Value = {
|
||||
evalGeneric(code, Constants.MIME_TYPE)
|
||||
}
|
||||
|
||||
def evalOld(code: String): Value = {
|
||||
evalGeneric(code, Constants.Debug.MIME_TYPE)
|
||||
}
|
||||
|
||||
def consumeOut: List[String] = {
|
||||
@ -29,7 +43,7 @@ trait InterpreterRunner {
|
||||
}
|
||||
|
||||
def parse(code: String): Value =
|
||||
InterpreterException.rethrowPolyglot(eval(code))
|
||||
InterpreterException.rethrowPolyglot(evalOld(code))
|
||||
|
||||
def getReplInstrument: ReplDebuggerInstrument = {
|
||||
ctx.getEngine.getInstruments
|
||||
|
@ -19,7 +19,7 @@ class ReplTest extends InterpreterTest {
|
||||
scopeResult = executor.listBindings.asScala.toMap
|
||||
executor.exit()
|
||||
}
|
||||
eval(code)
|
||||
evalOld(code)
|
||||
scopeResult shouldEqual Map("x" -> 10, "y" -> 20, "z" -> 30)
|
||||
}
|
||||
|
||||
@ -37,7 +37,7 @@ class ReplTest extends InterpreterTest {
|
||||
evalResult = executor.evaluate("x + y")
|
||||
executor.exit()
|
||||
}
|
||||
eval(code)
|
||||
evalOld(code)
|
||||
evalResult shouldEqual 3
|
||||
}
|
||||
|
||||
@ -55,7 +55,7 @@ class ReplTest extends InterpreterTest {
|
||||
executor.evaluate("a + b")
|
||||
executor.exit()
|
||||
}
|
||||
eval(code) shouldEqual 55
|
||||
evalOld(code) shouldEqual 55
|
||||
}
|
||||
|
||||
"Repl" should "be able to define its local variables" in {
|
||||
@ -72,7 +72,7 @@ class ReplTest extends InterpreterTest {
|
||||
executor.evaluate("z")
|
||||
executor.exit()
|
||||
}
|
||||
eval(code) shouldEqual 110
|
||||
evalOld(code) shouldEqual 110
|
||||
}
|
||||
|
||||
"Repl" should "access and modify monadic state" in {
|
||||
@ -89,6 +89,6 @@ class ReplTest extends InterpreterTest {
|
||||
executor.evaluate("@put[@State, x+1]")
|
||||
executor.exit()
|
||||
}
|
||||
eval(code) shouldEqual 11
|
||||
evalOld(code) shouldEqual 11
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ class ConstructorsTest extends InterpreterTest {
|
||||
| >
|
||||
|}
|
||||
""".stripMargin
|
||||
eval(patternMatchingCode) shouldEqual 1
|
||||
evalOld(patternMatchingCode) shouldEqual 1
|
||||
}
|
||||
|
||||
"Recursion with pattern matching" should "terminate" in {
|
||||
@ -31,7 +31,7 @@ class ConstructorsTest extends InterpreterTest {
|
||||
| res
|
||||
|}
|
||||
""".stripMargin
|
||||
eval(testCode) shouldEqual 55
|
||||
evalOld(testCode) shouldEqual 55
|
||||
}
|
||||
|
||||
"Pattern match expression" should "behave correctly in non-tail positions" in {
|
||||
@ -46,7 +46,7 @@ class ConstructorsTest extends InterpreterTest {
|
||||
| result + 1
|
||||
|}
|
||||
""".stripMargin
|
||||
eval(testCode).execute() shouldEqual 4
|
||||
evalOld(testCode).execute() shouldEqual 4
|
||||
}
|
||||
|
||||
"Pattern match expressions" should "accept a catch-all fallback clause" in {
|
||||
@ -60,7 +60,7 @@ class ConstructorsTest extends InterpreterTest {
|
||||
| >
|
||||
|}
|
||||
""".stripMargin
|
||||
eval(testCode).execute() shouldEqual 1
|
||||
evalOld(testCode).execute() shouldEqual 1
|
||||
}
|
||||
|
||||
"Pattern match expressions" should "throw an exception when match fails" in {
|
||||
@ -73,7 +73,7 @@ class ConstructorsTest extends InterpreterTest {
|
||||
| >
|
||||
|}
|
||||
""".stripMargin
|
||||
the[InterpreterException] thrownBy eval(testCode)
|
||||
the[InterpreterException] thrownBy evalOld(testCode)
|
||||
.call() should have message "Inexhaustive pattern match."
|
||||
}
|
||||
|
||||
@ -93,6 +93,6 @@ class ConstructorsTest extends InterpreterTest {
|
||||
|
|
||||
|@sumList [@Unit, @genList [@Unit, 10]]
|
||||
""".stripMargin
|
||||
eval(testCode) shouldEqual 55
|
||||
evalOld(testCode) shouldEqual 55
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ class CurryingTest extends InterpreterTest {
|
||||
|}
|
||||
|""".stripMargin
|
||||
|
||||
eval(code) shouldEqual 11
|
||||
evalOld(code) shouldEqual 11
|
||||
}
|
||||
|
||||
"Functions" should "allow default arguments to be suspended" in {
|
||||
@ -32,7 +32,7 @@ class CurryingTest extends InterpreterTest {
|
||||
|}
|
||||
|""".stripMargin
|
||||
|
||||
eval(code) shouldEqual 26
|
||||
evalOld(code) shouldEqual 26
|
||||
}
|
||||
|
||||
"Functions" should "allow defaults to be suspended in application chains" in {
|
||||
@ -45,6 +45,6 @@ class CurryingTest extends InterpreterTest {
|
||||
|}
|
||||
|""".stripMargin
|
||||
|
||||
eval(code) shouldEqual 32
|
||||
evalOld(code) shouldEqual 32
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ class ErrorsTest extends InterpreterTest {
|
||||
|}
|
||||
|""".stripMargin
|
||||
|
||||
val exception = the[InterpreterException] thrownBy eval(code)
|
||||
val exception = the[InterpreterException] thrownBy evalOld(code)
|
||||
exception.isGuestException shouldEqual true
|
||||
exception.getGuestObject.toString shouldEqual "Bar<>"
|
||||
consumeOut shouldEqual List("Foo<>")
|
||||
@ -34,7 +34,7 @@ class ErrorsTest extends InterpreterTest {
|
||||
|}
|
||||
|""".stripMargin
|
||||
|
||||
noException shouldBe thrownBy(eval(code))
|
||||
noException shouldBe thrownBy(evalOld(code))
|
||||
consumeOut shouldEqual List("Error:MyError<>")
|
||||
}
|
||||
|
||||
@ -52,8 +52,8 @@ class ErrorsTest extends InterpreterTest {
|
||||
| @println [@IO, matched]
|
||||
|}
|
||||
|""".stripMargin
|
||||
eval(code)
|
||||
noException shouldBe thrownBy(eval(code))
|
||||
evalOld(code)
|
||||
noException shouldBe thrownBy(evalOld(code))
|
||||
consumeOut shouldEqual List("Error:MyError<>")
|
||||
}
|
||||
|
||||
@ -65,7 +65,7 @@ class ErrorsTest extends InterpreterTest {
|
||||
| @catch [intError, { |x| x + 3 }]
|
||||
|}
|
||||
|""".stripMargin
|
||||
eval(code) shouldEqual 4
|
||||
evalOld(code) shouldEqual 4
|
||||
}
|
||||
|
||||
"Catch function" should "accept a constructor handler" in {
|
||||
@ -78,7 +78,7 @@ class ErrorsTest extends InterpreterTest {
|
||||
| @println [@IO, @catch [unitErr, MyCons]]
|
||||
|}
|
||||
|""".stripMargin
|
||||
eval(code)
|
||||
evalOld(code)
|
||||
consumeOut shouldEqual List("MyCons<Unit<>>")
|
||||
}
|
||||
|
||||
@ -98,12 +98,12 @@ class ErrorsTest extends InterpreterTest {
|
||||
|}
|
||||
|
|
||||
|""".stripMargin
|
||||
eval(code)
|
||||
evalOld(code)
|
||||
consumeOut shouldEqual List("MyRecovered<20>")
|
||||
}
|
||||
|
||||
"Catch function" should "act as identity for non-error values" in {
|
||||
val code = "@catch [10, {|x| x + 1}]"
|
||||
eval(code) shouldEqual 10
|
||||
evalOld(code) shouldEqual 10
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ class EvalTest extends InterpreterTest {
|
||||
| @eval [@Debug, "@println[@IO, \"foo\"]"]
|
||||
|}
|
||||
|""".stripMargin
|
||||
eval(code)
|
||||
evalOld(code)
|
||||
consumeOut shouldEqual List("foo")
|
||||
}
|
||||
|
||||
@ -22,7 +22,7 @@ class EvalTest extends InterpreterTest {
|
||||
| @eval [@Debug, "@println[@IO, x]"]
|
||||
|}
|
||||
|""".stripMargin
|
||||
eval(code)
|
||||
evalOld(code)
|
||||
consumeOut shouldEqual List("Hello World!")
|
||||
}
|
||||
|
||||
@ -36,7 +36,7 @@ class EvalTest extends InterpreterTest {
|
||||
| @eval [@Debug, "@println[@IO, @MyType[x]]"]
|
||||
|}
|
||||
|""".stripMargin
|
||||
eval(code)
|
||||
evalOld(code)
|
||||
consumeOut shouldEqual List("MyType<10>")
|
||||
}
|
||||
|
||||
@ -50,7 +50,7 @@ class EvalTest extends InterpreterTest {
|
||||
| res + 1
|
||||
|}
|
||||
|""".stripMargin
|
||||
eval(code) shouldEqual 4
|
||||
evalOld(code) shouldEqual 4
|
||||
}
|
||||
|
||||
"Debug.eval" should "work in a recursive setting" in {
|
||||
@ -64,7 +64,7 @@ class EvalTest extends InterpreterTest {
|
||||
| res
|
||||
|}
|
||||
|""".stripMargin
|
||||
val fun = eval(code)
|
||||
val fun = evalOld(code)
|
||||
fun.call(100) shouldEqual 5050
|
||||
}
|
||||
|
||||
@ -79,7 +79,7 @@ class EvalTest extends InterpreterTest {
|
||||
| res
|
||||
|}
|
||||
|""".stripMargin
|
||||
val fun = eval(code)
|
||||
val fun = evalOld(code)
|
||||
fun.call(100) shouldEqual 5050
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ class FunctionArgumentsTest extends InterpreterTest {
|
||||
|{ |x| x * x }
|
||||
|""".stripMargin
|
||||
|
||||
val function = eval(code)
|
||||
val function = evalOld(code)
|
||||
function.call(1) shouldEqual 1
|
||||
function.call(4) shouldEqual 16
|
||||
}
|
||||
@ -25,7 +25,7 @@ class FunctionArgumentsTest extends InterpreterTest {
|
||||
|}
|
||||
""".stripMargin
|
||||
|
||||
eval(code).call(3) shouldEqual 5
|
||||
evalOld(code).call(3) shouldEqual 5
|
||||
}
|
||||
|
||||
"Recursion" should "work" in {
|
||||
@ -37,7 +37,7 @@ class FunctionArgumentsTest extends InterpreterTest {
|
||||
|}
|
||||
""".stripMargin
|
||||
|
||||
eval(code) shouldEqual 55
|
||||
evalOld(code) shouldEqual 55
|
||||
}
|
||||
|
||||
"Function calls" should "accept more arguments than needed and pass them to the result upon execution" in {
|
||||
@ -50,7 +50,7 @@ class FunctionArgumentsTest extends InterpreterTest {
|
||||
|}
|
||||
|""".stripMargin
|
||||
|
||||
eval(code) shouldEqual 3
|
||||
evalOld(code) shouldEqual 3
|
||||
}
|
||||
|
||||
"Function calls" should "allow oversaturation and execute until completion" in {
|
||||
@ -63,7 +63,7 @@ class FunctionArgumentsTest extends InterpreterTest {
|
||||
|}
|
||||
|""".stripMargin
|
||||
|
||||
eval(code) shouldEqual 20
|
||||
evalOld(code) shouldEqual 20
|
||||
}
|
||||
|
||||
"Function calls" should "be able to return atoms that are evaluated with oversaturated args" in {
|
||||
@ -80,7 +80,7 @@ class FunctionArgumentsTest extends InterpreterTest {
|
||||
|}
|
||||
|""".stripMargin
|
||||
|
||||
eval(code) shouldEqual 5
|
||||
evalOld(code) shouldEqual 5
|
||||
}
|
||||
|
||||
"Methods" should "support the use of oversaturated args" in {
|
||||
@ -96,7 +96,7 @@ class FunctionArgumentsTest extends InterpreterTest {
|
||||
|}
|
||||
|""".stripMargin
|
||||
|
||||
eval(code) shouldEqual 1
|
||||
evalOld(code) shouldEqual 1
|
||||
}
|
||||
|
||||
"Recursion closing over lexical scope" should "work properly" in {
|
||||
@ -109,6 +109,6 @@ class FunctionArgumentsTest extends InterpreterTest {
|
||||
|}
|
||||
|""".stripMargin
|
||||
|
||||
eval(code) shouldEqual 0
|
||||
evalOld(code) shouldEqual 0
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ class GlobalScopeTest extends InterpreterTest {
|
||||
|@a [@Unit]
|
||||
""".stripMargin
|
||||
|
||||
eval(code) shouldEqual 10
|
||||
evalOld(code) shouldEqual 10
|
||||
}
|
||||
|
||||
"Functions" should "use values from the global scope in their bodies" in {
|
||||
@ -24,7 +24,7 @@ class GlobalScopeTest extends InterpreterTest {
|
||||
|@addTen [@Unit, 5]
|
||||
""".stripMargin
|
||||
|
||||
eval(code) shouldEqual 15
|
||||
evalOld(code) shouldEqual 15
|
||||
}
|
||||
|
||||
"Functions" should "be able to call other functions in scope" in {
|
||||
@ -39,7 +39,7 @@ class GlobalScopeTest extends InterpreterTest {
|
||||
|} [2]
|
||||
""".stripMargin
|
||||
|
||||
eval(code) shouldEqual 6
|
||||
evalOld(code) shouldEqual 6
|
||||
}
|
||||
|
||||
"Functions" should "be able to be passed as values when in scope" in {
|
||||
@ -55,7 +55,7 @@ class GlobalScopeTest extends InterpreterTest {
|
||||
|@binaryFn [@Unit, 1, 2, { |a, b| @adder [@Unit, a, b] }]
|
||||
""".stripMargin
|
||||
|
||||
eval(code) shouldEqual 3
|
||||
evalOld(code) shouldEqual 3
|
||||
}
|
||||
|
||||
"Functions" should "be able to mutually recurse in the global scope" in {
|
||||
@ -73,7 +73,7 @@ class GlobalScopeTest extends InterpreterTest {
|
||||
|@fn1 [@Unit, 5]
|
||||
""".stripMargin
|
||||
|
||||
eval(code) shouldEqual 3
|
||||
evalOld(code) shouldEqual 3
|
||||
}
|
||||
|
||||
"Functions" should "be suspended within blocks" in {
|
||||
@ -85,7 +85,7 @@ class GlobalScopeTest extends InterpreterTest {
|
||||
|b
|
||||
""".stripMargin
|
||||
|
||||
noException should be thrownBy eval(code)
|
||||
noException should be thrownBy evalOld(code)
|
||||
}
|
||||
|
||||
"Exceptions" should "be thrown when called" in {
|
||||
@ -97,7 +97,7 @@ class GlobalScopeTest extends InterpreterTest {
|
||||
|@b [@Unit]
|
||||
""".stripMargin
|
||||
|
||||
an[InterpreterException] should be thrownBy eval(code)
|
||||
an[InterpreterException] should be thrownBy evalOld(code)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ class InteropTest extends InterpreterTest {
|
||||
|}
|
||||
|""".stripMargin
|
||||
|
||||
val recurFun = eval(code)
|
||||
val recurFun = evalOld(code)
|
||||
recurFun.call(15) shouldEqual 0
|
||||
}
|
||||
|
||||
@ -25,7 +25,7 @@ class InteropTest extends InterpreterTest {
|
||||
|}
|
||||
|""".stripMargin
|
||||
|
||||
val curriedFun = eval(code)
|
||||
val curriedFun = evalOld(code)
|
||||
curriedFun.call(2, 3) shouldEqual 6
|
||||
}
|
||||
|
||||
@ -35,7 +35,7 @@ class InteropTest extends InterpreterTest {
|
||||
|{ |x, y, z| (x + y) + z }
|
||||
|""".stripMargin
|
||||
|
||||
val fun = eval(code)
|
||||
val fun = evalOld(code)
|
||||
fun.call(1).call(2).call(3) shouldEqual 6
|
||||
}
|
||||
|
||||
@ -47,7 +47,7 @@ class InteropTest extends InterpreterTest {
|
||||
|{ |x| method }
|
||||
|""".stripMargin
|
||||
|
||||
val fun = eval(code)
|
||||
val fun = evalOld(code)
|
||||
fun.call(1, 2) shouldEqual 2
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ class LazyArgumentsTest extends InterpreterTest {
|
||||
|}
|
||||
|""".stripMargin
|
||||
noException should be thrownBy parse(code)
|
||||
eval(code)
|
||||
evalOld(code)
|
||||
consumeOut shouldEqual List("2")
|
||||
}
|
||||
|
||||
@ -28,7 +28,7 @@ class LazyArgumentsTest extends InterpreterTest {
|
||||
| res
|
||||
|}
|
||||
|""".stripMargin
|
||||
eval(code) shouldEqual 50005000
|
||||
evalOld(code) shouldEqual 50005000
|
||||
}
|
||||
|
||||
subject should "work in non-tail positions" in {
|
||||
@ -41,7 +41,7 @@ class LazyArgumentsTest extends InterpreterTest {
|
||||
|}
|
||||
|""".stripMargin
|
||||
|
||||
val result = eval(code)
|
||||
val result = evalOld(code)
|
||||
result shouldEqual 12
|
||||
}
|
||||
|
||||
@ -60,7 +60,7 @@ class LazyArgumentsTest extends InterpreterTest {
|
||||
| @method [@Foo, @println [@IO, 3]]
|
||||
|}
|
||||
|""".stripMargin
|
||||
eval(code)
|
||||
evalOld(code)
|
||||
consumeOut shouldEqual List("2")
|
||||
}
|
||||
|
||||
@ -74,7 +74,7 @@ class LazyArgumentsTest extends InterpreterTest {
|
||||
| @foo [1, @println [@IO, 3], @println [@IO, 4]]
|
||||
|}
|
||||
|""".stripMargin
|
||||
eval(code)
|
||||
evalOld(code)
|
||||
consumeOut shouldEqual List("1","4")
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ class LexicalScopeTest extends InterpreterTest {
|
||||
|}
|
||||
""".stripMargin
|
||||
|
||||
eval(code) shouldEqual 15
|
||||
evalOld(code) shouldEqual 15
|
||||
}
|
||||
|
||||
"Variable shadowing" should "work" in {
|
||||
@ -29,7 +29,7 @@ class LexicalScopeTest extends InterpreterTest {
|
||||
| }
|
||||
|}
|
||||
""".stripMargin
|
||||
eval(code) shouldEqual 6
|
||||
evalOld(code) shouldEqual 6
|
||||
}
|
||||
|
||||
"Variable redefinition in same scope" should "throw error" in {
|
||||
@ -44,7 +44,7 @@ class LexicalScopeTest extends InterpreterTest {
|
||||
| }
|
||||
|}
|
||||
""".stripMargin
|
||||
the[InterpreterException] thrownBy eval(code) should have message "Variable y was already defined in this scope."
|
||||
the[InterpreterException] thrownBy evalOld(code) should have message "Variable y was already defined in this scope."
|
||||
}
|
||||
|
||||
"Reference to an undefined variable" should "throw error" in {
|
||||
@ -58,7 +58,7 @@ class LexicalScopeTest extends InterpreterTest {
|
||||
| y
|
||||
|}
|
||||
""".stripMargin
|
||||
the[InterpreterException] thrownBy eval(code) should have message "Variable y is not defined."
|
||||
the[InterpreterException] thrownBy evalOld(code) should have message "Variable y is not defined."
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ class MethodsTest extends InterpreterTest {
|
||||
|Foo.bar = { |number| number + 1 }
|
||||
|@bar [@Foo, 10]
|
||||
|""".stripMargin
|
||||
eval(code) shouldEqual 11
|
||||
evalOld(code) shouldEqual 11
|
||||
}
|
||||
|
||||
"Methods" should "be dispatched to the proper constructor" in {
|
||||
@ -24,7 +24,7 @@ class MethodsTest extends InterpreterTest {
|
||||
|@sum [@Cons [1, @Cons [2, @Nil]], 0]
|
||||
|""".stripMargin
|
||||
|
||||
eval(code) shouldEqual 3
|
||||
evalOld(code) shouldEqual 3
|
||||
}
|
||||
|
||||
"Method call target" should "be passable by-name" in {
|
||||
@ -34,7 +34,7 @@ class MethodsTest extends InterpreterTest {
|
||||
|@testMethod [x = 1, y = 2, this = @Unit, z = 3]
|
||||
|""".stripMargin
|
||||
|
||||
eval(code) shouldEqual 6
|
||||
evalOld(code) shouldEqual 6
|
||||
}
|
||||
|
||||
"Calling a non-existent method" should "throw an exception" in {
|
||||
@ -42,7 +42,7 @@ class MethodsTest extends InterpreterTest {
|
||||
"""
|
||||
|@foo [7]
|
||||
|""".stripMargin
|
||||
the[InterpreterException] thrownBy eval(code) should have message "Object Number does not define method foo."
|
||||
the[InterpreterException] thrownBy evalOld(code) should have message "Object Number does not define method foo."
|
||||
}
|
||||
|
||||
"Methods defined on Any type" should "be callable for any type" in {
|
||||
@ -69,7 +69,7 @@ class MethodsTest extends InterpreterTest {
|
||||
| 0
|
||||
|}
|
||||
|""".stripMargin
|
||||
eval(code)
|
||||
evalOld(code)
|
||||
consumeOut shouldEqual List("1", "2", "3", "0", "0", "0")
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ class NamedArgumentsTest extends InterpreterTest {
|
||||
|@addTen [@Unit, b = 10]
|
||||
""".stripMargin
|
||||
|
||||
eval(code) shouldEqual 20
|
||||
evalOld(code) shouldEqual 20
|
||||
}
|
||||
|
||||
"Functions" should "be able to have named arguments given out of order" in {
|
||||
@ -23,7 +23,7 @@ class NamedArgumentsTest extends InterpreterTest {
|
||||
|@subtract [@Unit, b = 10, a = 5]
|
||||
""".stripMargin
|
||||
|
||||
eval(code) shouldEqual -5
|
||||
evalOld(code) shouldEqual -5
|
||||
}
|
||||
|
||||
"Functions" should "be able to have scope values as named arguments" in {
|
||||
@ -37,7 +37,7 @@ class NamedArgumentsTest extends InterpreterTest {
|
||||
|}
|
||||
""".stripMargin
|
||||
|
||||
eval(code) shouldEqual 20
|
||||
evalOld(code) shouldEqual 20
|
||||
}
|
||||
|
||||
"Functions" should "be able to be defined with default argument values" in {
|
||||
@ -48,7 +48,7 @@ class NamedArgumentsTest extends InterpreterTest {
|
||||
|@addNum [@Unit, 5]
|
||||
""".stripMargin
|
||||
|
||||
eval(code) shouldEqual 15
|
||||
evalOld(code) shouldEqual 15
|
||||
}
|
||||
|
||||
"Default arguments" should "be able to default to complex expressions" in {
|
||||
@ -61,7 +61,7 @@ class NamedArgumentsTest extends InterpreterTest {
|
||||
|@doThing [@Unit, 10]
|
||||
|""".stripMargin
|
||||
|
||||
eval(code) shouldEqual 13
|
||||
evalOld(code) shouldEqual 13
|
||||
}
|
||||
|
||||
"Default arguments" should "be able to close over their outer scope" in {
|
||||
@ -77,7 +77,7 @@ class NamedArgumentsTest extends InterpreterTest {
|
||||
|}
|
||||
|""".stripMargin
|
||||
|
||||
eval(code) shouldEqual 1
|
||||
evalOld(code) shouldEqual 1
|
||||
}
|
||||
|
||||
"Functions" should "use their default values when none is supplied" in {
|
||||
@ -88,7 +88,7 @@ class NamedArgumentsTest extends InterpreterTest {
|
||||
|@addTogether [@Unit]
|
||||
""".stripMargin
|
||||
|
||||
eval(code) shouldEqual 11
|
||||
evalOld(code) shouldEqual 11
|
||||
}
|
||||
|
||||
"Functions" should "override defaults by name" in {
|
||||
@ -99,7 +99,7 @@ class NamedArgumentsTest extends InterpreterTest {
|
||||
|@addNum [@Unit, 1, num = 1]
|
||||
""".stripMargin
|
||||
|
||||
eval(code) shouldEqual 2
|
||||
evalOld(code) shouldEqual 2
|
||||
}
|
||||
|
||||
"Functions" should "override defaults by position" in {
|
||||
@ -110,7 +110,7 @@ class NamedArgumentsTest extends InterpreterTest {
|
||||
|@addNum [@Unit, 1, 2]
|
||||
|""".stripMargin
|
||||
|
||||
eval(code) shouldEqual 3
|
||||
evalOld(code) shouldEqual 3
|
||||
}
|
||||
|
||||
"Defaulted arguments" should "work in a recursive context" in {
|
||||
@ -127,7 +127,7 @@ class NamedArgumentsTest extends InterpreterTest {
|
||||
|@summer [@Unit, 100]
|
||||
""".stripMargin
|
||||
|
||||
eval(code) shouldEqual 5050
|
||||
evalOld(code) shouldEqual 5050
|
||||
}
|
||||
|
||||
"Named Arguments" should "only be scoped to their definitions" in {
|
||||
@ -146,7 +146,7 @@ class NamedArgumentsTest extends InterpreterTest {
|
||||
|}
|
||||
|""".stripMargin
|
||||
|
||||
eval(code) shouldEqual 0
|
||||
evalOld(code) shouldEqual 0
|
||||
}
|
||||
|
||||
"Named arguments" should "be applied in a sequence compatible with Eta-expansions" in {
|
||||
@ -166,7 +166,7 @@ class NamedArgumentsTest extends InterpreterTest {
|
||||
|@doubleOrAdd [@Unit, 5]
|
||||
|""".stripMargin
|
||||
|
||||
eval(code) shouldEqual 10
|
||||
evalOld(code) shouldEqual 10
|
||||
}
|
||||
|
||||
"Default arguments" should "not be able to depend on later arguments" in {
|
||||
@ -178,7 +178,7 @@ class NamedArgumentsTest extends InterpreterTest {
|
||||
|@badArgFn [@Unit, 3]
|
||||
|""".stripMargin
|
||||
|
||||
an[InterpreterException] should be thrownBy eval(code)
|
||||
an[InterpreterException] should be thrownBy evalOld(code)
|
||||
}
|
||||
|
||||
"Constructors" should "be able to use named arguments" in {
|
||||
@ -200,7 +200,7 @@ class NamedArgumentsTest extends InterpreterTest {
|
||||
|}
|
||||
""".stripMargin
|
||||
|
||||
eval(code) shouldEqual 55
|
||||
evalOld(code) shouldEqual 55
|
||||
}
|
||||
|
||||
"Constructors" should "be able to take default arguments that are overridden" in {
|
||||
@ -221,7 +221,7 @@ class NamedArgumentsTest extends InterpreterTest {
|
||||
|}
|
||||
""".stripMargin
|
||||
|
||||
eval(code) shouldEqual 15
|
||||
evalOld(code) shouldEqual 15
|
||||
}
|
||||
|
||||
"Default arguments to constructors" should "be resolved dynamically" in {
|
||||
@ -233,7 +233,7 @@ class NamedArgumentsTest extends InterpreterTest {
|
||||
|5
|
||||
|""".stripMargin
|
||||
|
||||
eval(code) shouldEqual 5
|
||||
evalOld(code) shouldEqual 5
|
||||
}
|
||||
|
||||
"Constructors" should "be able to take and use default arguments" in {
|
||||
@ -250,7 +250,7 @@ class NamedArgumentsTest extends InterpreterTest {
|
||||
|@sumList [@Unit, @Cons2 [10]]
|
||||
""".stripMargin
|
||||
|
||||
eval(code) shouldEqual 10
|
||||
evalOld(code) shouldEqual 10
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3,10 +3,23 @@ package org.enso.interpreter.test.semantic
|
||||
import org.enso.interpreter.test.InterpreterTest
|
||||
|
||||
class SimpleArithmeticTest extends InterpreterTest {
|
||||
"1" should "equal 1" in {
|
||||
eval("1") shouldEqual 1
|
||||
}
|
||||
|
||||
"1 + 1" should "equal 2" in {
|
||||
eval("1 + 1") shouldEqual 2
|
||||
}
|
||||
|
||||
"2 + (2 * 2)" should "equal 6" in {
|
||||
eval("2 + (2 * 2)") shouldEqual 6
|
||||
}
|
||||
|
||||
"2 + 2 * 3" should "equal 8" in {
|
||||
eval("2 + 2 * 3") shouldEqual 8
|
||||
}
|
||||
|
||||
"2 * 2 / 2" should "equal 2" in {
|
||||
eval("2 * 2 / 2") shouldEqual 2
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ class StateTest extends InterpreterTest {
|
||||
|}
|
||||
|""".stripMargin
|
||||
|
||||
eval(code) shouldEqual 11
|
||||
evalOld(code) shouldEqual 11
|
||||
}
|
||||
|
||||
"State" should "be implicitly threaded through function executions" in {
|
||||
@ -36,7 +36,7 @@ class StateTest extends InterpreterTest {
|
||||
|}
|
||||
|""".stripMargin
|
||||
|
||||
eval(code) shouldEqual 5
|
||||
evalOld(code) shouldEqual 5
|
||||
}
|
||||
|
||||
"State" should "be localized with State.run" in {
|
||||
@ -54,7 +54,7 @@ class StateTest extends InterpreterTest {
|
||||
| res + state
|
||||
|}
|
||||
|""".stripMargin
|
||||
eval(code) shouldEqual 30
|
||||
evalOld(code) shouldEqual 30
|
||||
}
|
||||
|
||||
"State" should "work well with recursive code" in {
|
||||
@ -70,7 +70,7 @@ class StateTest extends InterpreterTest {
|
||||
| @run [@State, 0, @stateSum [10]]
|
||||
|}
|
||||
|""".stripMargin
|
||||
eval(code) shouldEqual 55
|
||||
evalOld(code) shouldEqual 55
|
||||
}
|
||||
|
||||
"State" should "be initialized to a Unit by default" in {
|
||||
@ -78,7 +78,7 @@ class StateTest extends InterpreterTest {
|
||||
"""
|
||||
|@println[@IO, @get[@State]]
|
||||
|""".stripMargin
|
||||
eval(code)
|
||||
evalOld(code)
|
||||
consumeOut shouldEqual List("Unit<>")
|
||||
}
|
||||
|
||||
@ -98,7 +98,7 @@ class StateTest extends InterpreterTest {
|
||||
| 0
|
||||
|}
|
||||
|""".stripMargin
|
||||
eval(code)
|
||||
evalOld(code)
|
||||
consumeOut shouldEqual List("11", "16")
|
||||
}
|
||||
|
||||
@ -112,6 +112,6 @@ class StateTest extends InterpreterTest {
|
||||
| @get[@State]
|
||||
|}
|
||||
|""".stripMargin
|
||||
eval(code) shouldEqual (-5)
|
||||
evalOld(code) shouldEqual (-5)
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ class StringTest extends InterpreterTest {
|
||||
|@println [@IO, "hello world!"]
|
||||
|""".stripMargin
|
||||
|
||||
noException shouldBe thrownBy(eval(code))
|
||||
noException shouldBe thrownBy(evalOld(code))
|
||||
consumeOut shouldEqual List("hello world!")
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user