mirror of
https://github.com/enso-org/enso.git
synced 2024-12-23 10:42:05 +03:00
Method naming fixes (#1024)
This commit is contained in:
parent
ded61865a4
commit
6137c6559b
@ -96,6 +96,8 @@ Text.it ~behavior =
|
|||||||
|
|
||||||
## Runs a suite of tests, consisting of multiple `describe` blocks.
|
## Runs a suite of tests, consisting of multiple `describe` blocks.
|
||||||
|
|
||||||
|
Returns a `Suite` object containing the test report.
|
||||||
|
|
||||||
> Example
|
> Example
|
||||||
Suite.run <|
|
Suite.run <|
|
||||||
describe "Number" <|
|
describe "Number" <|
|
||||||
@ -107,5 +109,20 @@ Suite.run ~specs =
|
|||||||
r = State.run Suite (Suite Nil) <|
|
r = State.run Suite (Suite Nil) <|
|
||||||
specs
|
specs
|
||||||
State.get Suite
|
State.get Suite
|
||||||
code = if r.is_fail then 1 else 0
|
r
|
||||||
System.exit code
|
|
||||||
|
## Runs a suite of tests, consisting of multiple `describe` blocks.
|
||||||
|
|
||||||
|
Exits the process with code `1` if the suite failed and `0` otherwise.
|
||||||
|
|
||||||
|
> Example
|
||||||
|
Suite.run <|
|
||||||
|
describe "Number" <|
|
||||||
|
it "should define addition" <|
|
||||||
|
2+3 . should_equal 5
|
||||||
|
it "should define multiplication" <|
|
||||||
|
2*3 . should_equal 6
|
||||||
|
Suite.runMain ~specs =
|
||||||
|
r = this.run specs
|
||||||
|
code = if r.is_fail then 1 else 0
|
||||||
|
System.exit code
|
||||||
|
@ -10,8 +10,9 @@ import org.enso.languageserver.boot.LanguageServerConfig
|
|||||||
import org.enso.pkg.PackageManager
|
import org.enso.pkg.PackageManager
|
||||||
import org.enso.polyglot.{LanguageInfo, Module, PolyglotContext}
|
import org.enso.polyglot.{LanguageInfo, Module, PolyglotContext}
|
||||||
import org.enso.version.VersionDescription
|
import org.enso.version.VersionDescription
|
||||||
import org.graalvm.polyglot.Value
|
import org.graalvm.polyglot.{PolyglotException, Value}
|
||||||
|
|
||||||
|
import scala.jdk.CollectionConverters._
|
||||||
import scala.util.Try
|
import scala.util.Try
|
||||||
|
|
||||||
/** The main CLI entry point class. */
|
/** The main CLI entry point class. */
|
||||||
@ -143,7 +144,10 @@ object Main {
|
|||||||
new HelpFormatter().printHelp(LanguageInfo.ID, options)
|
new HelpFormatter().printHelp(LanguageInfo.ID, options)
|
||||||
|
|
||||||
/** Terminates the process with a failure exit code. */
|
/** Terminates the process with a failure exit code. */
|
||||||
private def exitFail(): Unit = System.exit(1)
|
private def exitFail(): Nothing = {
|
||||||
|
System.exit(1)
|
||||||
|
throw new IllegalStateException("impossible to reach here")
|
||||||
|
}
|
||||||
|
|
||||||
/** Terminates the process with a success exit code. */
|
/** Terminates the process with a success exit code. */
|
||||||
private def exitSuccess(): Unit = System.exit(0)
|
private def exitSuccess(): Unit = System.exit(0)
|
||||||
@ -189,7 +193,7 @@ object Main {
|
|||||||
}
|
}
|
||||||
val mainFile = main.get
|
val mainFile = main.get
|
||||||
val mainModuleName = pkg.get.moduleNameForFile(mainFile).toString
|
val mainModuleName = pkg.get.moduleNameForFile(mainFile).toString
|
||||||
runPackage(context, mainModuleName)
|
runPackage(context, mainModuleName, file)
|
||||||
} else {
|
} else {
|
||||||
runSingleFile(context, file)
|
runSingleFile(context, file)
|
||||||
}
|
}
|
||||||
@ -198,22 +202,81 @@ object Main {
|
|||||||
|
|
||||||
private def runPackage(
|
private def runPackage(
|
||||||
context: PolyglotContext,
|
context: PolyglotContext,
|
||||||
mainModuleName: String
|
mainModuleName: String,
|
||||||
|
projectPath: File
|
||||||
): Unit = {
|
): Unit = {
|
||||||
val topScope = context.getTopScope
|
val topScope = context.getTopScope
|
||||||
val mainModule = topScope.getModule(mainModuleName)
|
val mainModule = topScope.getModule(mainModuleName)
|
||||||
runMain(mainModule)
|
runMain(mainModule, Some(projectPath))
|
||||||
}
|
}
|
||||||
|
|
||||||
private def runSingleFile(context: PolyglotContext, file: File): Unit = {
|
private def runSingleFile(context: PolyglotContext, file: File): Unit = {
|
||||||
val mainModule = context.evalModule(file)
|
val mainModule = context.evalModule(file)
|
||||||
runMain(mainModule)
|
runMain(mainModule, Some(file))
|
||||||
}
|
}
|
||||||
|
|
||||||
private def runMain(mainModule: Module): Value = {
|
private def printPolyglotException(
|
||||||
|
exception: PolyglotException,
|
||||||
|
relativeTo: Option[File]
|
||||||
|
): Unit = {
|
||||||
|
val fullStack = exception.getPolyglotStackTrace.asScala.toList
|
||||||
|
val dropInitJava = fullStack.reverse
|
||||||
|
.dropWhile(_.getLanguage.getId != LanguageInfo.ID)
|
||||||
|
.reverse
|
||||||
|
println(s"Execution finished with an error: ${exception.getMessage}")
|
||||||
|
dropInitJava.foreach { frame =>
|
||||||
|
val langId =
|
||||||
|
if (frame.isHostFrame) "java" else frame.getLanguage.getId
|
||||||
|
val fmtFrame = if (frame.getLanguage.getId == LanguageInfo.ID) {
|
||||||
|
val fName = frame.getRootName
|
||||||
|
val src = Option(frame.getSourceLocation)
|
||||||
|
.map { sourceLoc =>
|
||||||
|
val ident = Option(sourceLoc.getSource.getPath)
|
||||||
|
.map { path =>
|
||||||
|
relativeTo match {
|
||||||
|
case None => path
|
||||||
|
case Some(root) =>
|
||||||
|
val absRoot = root.getAbsoluteFile
|
||||||
|
if (path.startsWith(absRoot.getAbsolutePath)) {
|
||||||
|
val rootDir =
|
||||||
|
if (absRoot.isDirectory) absRoot
|
||||||
|
else absRoot.getParentFile
|
||||||
|
rootDir.toPath.relativize(new File(path).toPath).toString
|
||||||
|
} else {
|
||||||
|
path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.getOrElse(sourceLoc.getSource.getName)
|
||||||
|
val loc = if (sourceLoc.getStartLine == sourceLoc.getEndLine) {
|
||||||
|
val line = sourceLoc.getStartLine
|
||||||
|
val start = sourceLoc.getStartColumn
|
||||||
|
val end = sourceLoc.getEndColumn
|
||||||
|
s"$line:$start-$end"
|
||||||
|
} else {
|
||||||
|
s"${sourceLoc.getStartLine}-${sourceLoc.getEndLine}"
|
||||||
|
}
|
||||||
|
s"$ident:$loc"
|
||||||
|
}
|
||||||
|
.getOrElse("Internal")
|
||||||
|
s"$fName($src)"
|
||||||
|
} else {
|
||||||
|
frame.toString
|
||||||
|
}
|
||||||
|
println(s" at <$langId> $fmtFrame")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private def runMain(mainModule: Module, rootPkgPath: Option[File]): Value = {
|
||||||
val mainCons = mainModule.getAssociatedConstructor
|
val mainCons = mainModule.getAssociatedConstructor
|
||||||
val mainFun = mainModule.getMethod(mainCons, "main")
|
val mainFun = mainModule.getMethod(mainCons, "main")
|
||||||
mainFun.execute(mainCons.newInstance())
|
try {
|
||||||
|
mainFun.execute(mainCons.newInstance())
|
||||||
|
} catch {
|
||||||
|
case e: PolyglotException =>
|
||||||
|
printPolyglotException(e, rootPkgPath)
|
||||||
|
exitFail()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -226,7 +289,7 @@ object Main {
|
|||||||
new ContextFactory().create("", System.in, System.out, Repl(TerminalIO()))
|
new ContextFactory().create("", System.in, System.out, Repl(TerminalIO()))
|
||||||
val mainModule =
|
val mainModule =
|
||||||
context.evalModule(dummySourceToTriggerRepl, replModuleName)
|
context.evalModule(dummySourceToTriggerRepl, replModuleName)
|
||||||
runMain(mainModule)
|
runMain(mainModule, None)
|
||||||
exitSuccess()
|
exitSuccess()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -299,7 +362,6 @@ object Main {
|
|||||||
val line: CommandLine = Try(parser.parse(options, args)).getOrElse {
|
val line: CommandLine = Try(parser.parse(options, args)).getOrElse {
|
||||||
printHelp(options)
|
printHelp(options)
|
||||||
exitFail()
|
exitFail()
|
||||||
return
|
|
||||||
}
|
}
|
||||||
if (line.hasOption(HELP_OPTION)) {
|
if (line.hasOption(HELP_OPTION)) {
|
||||||
printHelp(options)
|
printHelp(options)
|
||||||
|
@ -8,10 +8,14 @@ import com.oracle.truffle.api.frame.FrameInstanceVisitor;
|
|||||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||||
import com.oracle.truffle.api.instrumentation.*;
|
import com.oracle.truffle.api.instrumentation.*;
|
||||||
import com.oracle.truffle.api.nodes.Node;
|
import com.oracle.truffle.api.nodes.Node;
|
||||||
|
import com.oracle.truffle.api.nodes.RootNode;
|
||||||
|
import org.enso.interpreter.node.EnsoRootNode;
|
||||||
import org.enso.interpreter.node.ExpressionNode;
|
import org.enso.interpreter.node.ExpressionNode;
|
||||||
|
import org.enso.interpreter.node.MethodRootNode;
|
||||||
import org.enso.interpreter.node.callable.FunctionCallInstrumentationNode;
|
import org.enso.interpreter.node.callable.FunctionCallInstrumentationNode;
|
||||||
import org.enso.interpreter.runtime.tag.IdentifiedTag;
|
import org.enso.interpreter.runtime.tag.IdentifiedTag;
|
||||||
import org.enso.interpreter.runtime.type.Types;
|
import org.enso.interpreter.runtime.type.Types;
|
||||||
|
import org.enso.pkg.QualifiedName;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -114,7 +118,8 @@ public class IdExecutionInstrument extends TruffleInstrument {
|
|||||||
/** Information about the function call. */
|
/** Information about the function call. */
|
||||||
public static class FunctionCallInfo {
|
public static class FunctionCallInfo {
|
||||||
|
|
||||||
private final String callTargetName;
|
private final QualifiedName moduleName;
|
||||||
|
private final QualifiedName typeName;
|
||||||
private final String functionName;
|
private final String functionName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -123,16 +128,34 @@ public class IdExecutionInstrument extends TruffleInstrument {
|
|||||||
* @param call the function call.
|
* @param call the function call.
|
||||||
*/
|
*/
|
||||||
public FunctionCallInfo(FunctionCallInstrumentationNode.FunctionCall call) {
|
public FunctionCallInfo(FunctionCallInstrumentationNode.FunctionCall call) {
|
||||||
this.callTargetName = call.getFunction().getCallTarget().getRootNode().getQualifiedName();
|
RootNode rootNode = call.getFunction().getCallTarget().getRootNode();
|
||||||
this.functionName = call.getFunction().getName();
|
if (rootNode instanceof MethodRootNode) {
|
||||||
|
MethodRootNode methodNode = (MethodRootNode) rootNode;
|
||||||
|
moduleName = methodNode.getModuleScope().getModule().getName();
|
||||||
|
typeName = methodNode.getAtomConstructor().getQualifiedName();
|
||||||
|
functionName = methodNode.getMethodName();
|
||||||
|
} else if (rootNode instanceof EnsoRootNode) {
|
||||||
|
moduleName = ((EnsoRootNode) rootNode).getModuleScope().getModule().getName();
|
||||||
|
typeName = null;
|
||||||
|
functionName = rootNode.getName();
|
||||||
|
} else {
|
||||||
|
moduleName = null;
|
||||||
|
typeName = null;
|
||||||
|
functionName = rootNode.getQualifiedName();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return call target name. */
|
/** @return the name of the module this function was defined in, or null if not available. */
|
||||||
public String getCallTargetName() {
|
public QualifiedName getModuleName() {
|
||||||
return callTargetName;
|
return moduleName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return function name. */
|
/** @return the name of the type this method was defined for, or null if not a method. */
|
||||||
|
public QualifiedName getTypeName() {
|
||||||
|
return typeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return the name of this function. */
|
||||||
public String getFunctionName() {
|
public String getFunctionName() {
|
||||||
return functionName;
|
return functionName;
|
||||||
}
|
}
|
||||||
|
@ -22,19 +22,16 @@ import org.enso.interpreter.runtime.state.Stateful;
|
|||||||
public class ClosureRootNode extends EnsoRootNode {
|
public class ClosureRootNode extends EnsoRootNode {
|
||||||
|
|
||||||
@Child private ExpressionNode body;
|
@Child private ExpressionNode body;
|
||||||
private final String qualifiedName;
|
|
||||||
|
|
||||||
private ClosureRootNode(
|
ClosureRootNode(
|
||||||
Language language,
|
Language language,
|
||||||
LocalScope localScope,
|
LocalScope localScope,
|
||||||
ModuleScope moduleScope,
|
ModuleScope moduleScope,
|
||||||
ExpressionNode body,
|
ExpressionNode body,
|
||||||
SourceSection section,
|
SourceSection section,
|
||||||
String name,
|
String name) {
|
||||||
String qualifiedName) {
|
|
||||||
super(language, localScope, moduleScope, name, section);
|
super(language, localScope, moduleScope, name, section);
|
||||||
this.body = body;
|
this.body = body;
|
||||||
this.qualifiedName = qualifiedName;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -54,10 +51,9 @@ public class ClosureRootNode extends EnsoRootNode {
|
|||||||
ModuleScope moduleScope,
|
ModuleScope moduleScope,
|
||||||
ExpressionNode body,
|
ExpressionNode body,
|
||||||
SourceSection section,
|
SourceSection section,
|
||||||
String name,
|
String name) {
|
||||||
String qualifiedName) {
|
|
||||||
return new ClosureRootNode(
|
return new ClosureRootNode(
|
||||||
language, localScope, moduleScope, body, section, name, qualifiedName);
|
language, localScope, moduleScope, body, section, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -74,14 +70,4 @@ public class ClosureRootNode extends EnsoRootNode {
|
|||||||
state = FrameUtil.getObjectSafe(frame, this.getStateFrameSlot());
|
state = FrameUtil.getObjectSafe(frame, this.getStateFrameSlot());
|
||||||
return new Stateful(state, result);
|
return new Stateful(state, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a qualified name that uniquely identifies the node.
|
|
||||||
*
|
|
||||||
* @return a qualified name of this node.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String getQualifiedName() {
|
|
||||||
return qualifiedName;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,94 @@
|
|||||||
|
package org.enso.interpreter.node;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.dsl.ReportPolymorphism;
|
||||||
|
import com.oracle.truffle.api.frame.FrameUtil;
|
||||||
|
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||||
|
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||||
|
import com.oracle.truffle.api.source.SourceSection;
|
||||||
|
import org.enso.interpreter.Language;
|
||||||
|
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
|
||||||
|
import org.enso.interpreter.runtime.callable.function.Function;
|
||||||
|
import org.enso.interpreter.runtime.scope.LocalScope;
|
||||||
|
import org.enso.interpreter.runtime.scope.ModuleScope;
|
||||||
|
import org.enso.interpreter.runtime.state.Stateful;
|
||||||
|
|
||||||
|
@ReportPolymorphism
|
||||||
|
@NodeInfo(shortName = "Method", description = "A root node for Enso methods.")
|
||||||
|
public class MethodRootNode extends ClosureRootNode {
|
||||||
|
|
||||||
|
private final AtomConstructor atomConstructor;
|
||||||
|
private final String methodName;
|
||||||
|
|
||||||
|
private MethodRootNode(
|
||||||
|
Language language,
|
||||||
|
LocalScope localScope,
|
||||||
|
ModuleScope moduleScope,
|
||||||
|
ExpressionNode body,
|
||||||
|
SourceSection section,
|
||||||
|
AtomConstructor atomConstructor,
|
||||||
|
String methodName) {
|
||||||
|
super(
|
||||||
|
language,
|
||||||
|
localScope,
|
||||||
|
moduleScope,
|
||||||
|
body,
|
||||||
|
section,
|
||||||
|
shortName(atomConstructor.getName(), methodName));
|
||||||
|
this.atomConstructor = atomConstructor;
|
||||||
|
this.methodName = methodName;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String shortName(String atomName, String methodName) {
|
||||||
|
return atomName + "." + methodName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an instance of this node.
|
||||||
|
*
|
||||||
|
* @param language the language identifier
|
||||||
|
* @param localScope a description of the local scope
|
||||||
|
* @param moduleScope a description of the module scope
|
||||||
|
* @param body the program body to be executed
|
||||||
|
* @param section a mapping from {@code body} to the program source
|
||||||
|
* @param atomConstructor the constructor this method is defined for
|
||||||
|
* @param methodName the name of this method
|
||||||
|
* @return a node representing the specified closure
|
||||||
|
*/
|
||||||
|
public static MethodRootNode build(
|
||||||
|
Language language,
|
||||||
|
LocalScope localScope,
|
||||||
|
ModuleScope moduleScope,
|
||||||
|
ExpressionNode body,
|
||||||
|
SourceSection section,
|
||||||
|
AtomConstructor atomConstructor,
|
||||||
|
String methodName) {
|
||||||
|
return new MethodRootNode(
|
||||||
|
language, localScope, moduleScope, body, section, atomConstructor, methodName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the fully qualified name of this method.
|
||||||
|
*
|
||||||
|
* <p>The name has a form of [method's module]::[qualified type name]::[method name].
|
||||||
|
*
|
||||||
|
* @return the qualified name of this method.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String getQualifiedName() {
|
||||||
|
return getModuleScope().getModule().getName().toString()
|
||||||
|
+ "::"
|
||||||
|
+ atomConstructor.getQualifiedName().toString()
|
||||||
|
+ "::"
|
||||||
|
+ methodName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return the constructor this method was defined for */
|
||||||
|
public AtomConstructor getAtomConstructor() {
|
||||||
|
return atomConstructor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return the method name */
|
||||||
|
public String getMethodName() {
|
||||||
|
return methodName;
|
||||||
|
}
|
||||||
|
}
|
@ -6,9 +6,12 @@ import com.oracle.truffle.api.nodes.NodeInfo;
|
|||||||
import com.oracle.truffle.api.nodes.RootNode;
|
import com.oracle.truffle.api.nodes.RootNode;
|
||||||
import com.oracle.truffle.api.source.Source;
|
import com.oracle.truffle.api.source.Source;
|
||||||
import org.enso.interpreter.Language;
|
import org.enso.interpreter.Language;
|
||||||
|
import org.enso.interpreter.runtime.Context;
|
||||||
import org.enso.interpreter.runtime.Module;
|
import org.enso.interpreter.runtime.Module;
|
||||||
import org.enso.pkg.QualifiedName;
|
import org.enso.pkg.QualifiedName;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This node handles static transformation of the input AST before execution and represents the root
|
* This node handles static transformation of the input AST before execution and represents the root
|
||||||
* of an Enso program.
|
* of an Enso program.
|
||||||
@ -48,15 +51,26 @@ public class ProgramRootNode extends RootNode {
|
|||||||
public Object execute(VirtualFrame frame) {
|
public Object execute(VirtualFrame frame) {
|
||||||
if (module == null) {
|
if (module == null) {
|
||||||
CompilerDirectives.transferToInterpreterAndInvalidate();
|
CompilerDirectives.transferToInterpreterAndInvalidate();
|
||||||
|
QualifiedName name = QualifiedName.simpleName(canonicalizeName(sourceCode.getName()));
|
||||||
|
Context ctx = lookupContextReference(Language.class).get();
|
||||||
module =
|
module =
|
||||||
new Module(
|
sourceCode.getPath() != null
|
||||||
QualifiedName.simpleName(sourceCode.getName()),
|
? new Module(name, ctx.getTruffleFile(new File(sourceCode.getPath())))
|
||||||
sourceCode.getCharacters().toString());
|
: new Module(name, sourceCode.getCharacters().toString());
|
||||||
}
|
}
|
||||||
// Note [Static Passes]
|
// Note [Static Passes]
|
||||||
return module;
|
return module;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String canonicalizeName(String name) {
|
||||||
|
String[] segs = name.split("\\.");
|
||||||
|
if (segs.length == 0) {
|
||||||
|
return "Unnamed";
|
||||||
|
} else {
|
||||||
|
return segs[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Note [Static Passes]
|
/* Note [Static Passes]
|
||||||
* ~~~~~~~~~~~~~~~~~~~~
|
* ~~~~~~~~~~~~~~~~~~~~
|
||||||
* Almost all of the static analysis functionality required by the interpreter requires access to
|
* Almost all of the static analysis functionality required by the interpreter requires access to
|
||||||
|
@ -58,9 +58,7 @@ public abstract class EvalNode extends BaseNode {
|
|||||||
|
|
||||||
RootCallTarget parseExpression(LocalScope scope, ModuleScope moduleScope, String expression) {
|
RootCallTarget parseExpression(LocalScope scope, ModuleScope moduleScope, String expression) {
|
||||||
LocalScope localScope = scope.createChild();
|
LocalScope localScope = scope.createChild();
|
||||||
InlineContext inlineContext =
|
InlineContext inlineContext = InlineContext.fromJava(localScope, moduleScope, isTail());
|
||||||
InlineContext.fromJava(
|
|
||||||
localScope, moduleScope, isTail());
|
|
||||||
ExpressionNode expr =
|
ExpressionNode expr =
|
||||||
lookupContextReference(Language.class)
|
lookupContextReference(Language.class)
|
||||||
.get()
|
.get()
|
||||||
@ -81,8 +79,7 @@ public abstract class EvalNode extends BaseNode {
|
|||||||
moduleScope,
|
moduleScope,
|
||||||
expr,
|
expr,
|
||||||
null,
|
null,
|
||||||
"<dynamic_eval>",
|
"<eval>");
|
||||||
null);
|
|
||||||
return Truffle.getRuntime().createCallTarget(framedNode);
|
return Truffle.getRuntime().createCallTarget(framedNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,10 +39,10 @@ public class Module implements TruffleObject {
|
|||||||
private boolean isParsed = false;
|
private boolean isParsed = false;
|
||||||
private boolean isIndexed = false;
|
private boolean isIndexed = false;
|
||||||
private IR ir;
|
private IR ir;
|
||||||
private final QualifiedName name;
|
private QualifiedName name;
|
||||||
|
|
||||||
private Module(TruffleFile sourceFile, Rope literalSource,
|
private Module(
|
||||||
boolean isParsed, IR ir, QualifiedName name) {
|
TruffleFile sourceFile, Rope literalSource, boolean isParsed, IR ir, QualifiedName name) {
|
||||||
this.sourceFile = sourceFile;
|
this.sourceFile = sourceFile;
|
||||||
this.literalSource = literalSource;
|
this.literalSource = literalSource;
|
||||||
this.isParsed = isParsed;
|
this.isParsed = isParsed;
|
||||||
@ -205,17 +205,10 @@ public class Module implements TruffleObject {
|
|||||||
/**
|
/**
|
||||||
* Renames a project part of the QualifiedName of this module.
|
* Renames a project part of the QualifiedName of this module.
|
||||||
*
|
*
|
||||||
* @param oldName the old project name
|
|
||||||
* @param newName the new project name
|
* @param newName the new project name
|
||||||
* @return a module with the updated QualifiedName
|
|
||||||
*/
|
*/
|
||||||
public Module renameProject(String oldName, String newName) {
|
public void renameProject(String newName) {
|
||||||
if (name.path().head().equals(oldName)) {
|
this.name = name.renameProject(newName);
|
||||||
QualifiedName renamed = name.renameProject(oldName, newName);
|
|
||||||
return new Module(sourceFile, literalSource, false, ir, renamed);
|
|
||||||
} else {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return the indexed flag. */
|
/** @return the indexed flag. */
|
||||||
|
@ -18,6 +18,7 @@ import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
|||||||
import org.enso.interpreter.runtime.callable.function.Function;
|
import org.enso.interpreter.runtime.callable.function.Function;
|
||||||
import org.enso.interpreter.runtime.callable.function.FunctionSchema;
|
import org.enso.interpreter.runtime.callable.function.FunctionSchema;
|
||||||
import org.enso.interpreter.runtime.scope.ModuleScope;
|
import org.enso.interpreter.runtime.scope.ModuleScope;
|
||||||
|
import org.enso.pkg.QualifiedName;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -181,4 +182,9 @@ public class AtomConstructor implements TruffleObject {
|
|||||||
}
|
}
|
||||||
return newInstance(arguments);
|
return newInstance(arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @return the fully qualified name of this constructor. */
|
||||||
|
public QualifiedName getQualifiedName() {
|
||||||
|
return definitionScope.getModule().getName().createChild(getName());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ public class ModuleScope {
|
|||||||
*/
|
*/
|
||||||
public ModuleScope(Module module) {
|
public ModuleScope(Module module) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
this.associatedType = new AtomConstructor(module.getName().module(), this).initializeFields();
|
this.associatedType = new AtomConstructor(module.getName().item(), this).initializeFields();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -24,21 +24,18 @@ import java.util.Map;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/** Represents the top scope of Enso execution, containing all the importable modules. */
|
||||||
* Represents the top scope of Enso execution, containing all the importable modules.
|
|
||||||
*/
|
|
||||||
@ExportLibrary(InteropLibrary.class)
|
@ExportLibrary(InteropLibrary.class)
|
||||||
public class TopLevelScope implements TruffleObject {
|
public class TopLevelScope implements TruffleObject {
|
||||||
private final Builtins builtins;
|
private final Builtins builtins;
|
||||||
private final Map<String, Module> modules;
|
private final Map<String, Module> modules;
|
||||||
private final Scope scope = Scope.newBuilder("top_scope", this).build();
|
private final Scope scope = Scope.newBuilder("top_scope", this).build();
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance of top scope.
|
* Creates a new instance of top scope.
|
||||||
*
|
*
|
||||||
* @param builtins the automatically-imported builtin module.
|
* @param builtins the automatically-imported builtin module.
|
||||||
* @param modules the initial modules this scope contains.
|
* @param modules the initial modules this scope contains.
|
||||||
*/
|
*/
|
||||||
public TopLevelScope(Builtins builtins, Map<String, Module> modules) {
|
public TopLevelScope(Builtins builtins, Map<String, Module> modules) {
|
||||||
this.builtins = builtins;
|
this.builtins = builtins;
|
||||||
@ -70,7 +67,7 @@ public class TopLevelScope implements TruffleObject {
|
|||||||
/**
|
/**
|
||||||
* Creates and registers a new module with given name and source file.
|
* Creates and registers a new module with given name and source file.
|
||||||
*
|
*
|
||||||
* @param name the module name.
|
* @param name the module name.
|
||||||
* @param sourceFile the module source file.
|
* @param sourceFile the module source file.
|
||||||
* @return the newly created module.
|
* @return the newly created module.
|
||||||
*/
|
*/
|
||||||
@ -89,19 +86,17 @@ public class TopLevelScope implements TruffleObject {
|
|||||||
public void renameProjectInModules(String oldName, String newName) {
|
public void renameProjectInModules(String oldName, String newName) {
|
||||||
String separator = QualifiedName$.MODULE$.separator();
|
String separator = QualifiedName$.MODULE$.separator();
|
||||||
List<String> keys =
|
List<String> keys =
|
||||||
modules
|
modules.keySet().stream()
|
||||||
.keySet()
|
|
||||||
.stream()
|
|
||||||
.filter(name -> name.startsWith(oldName + separator))
|
.filter(name -> name.startsWith(oldName + separator))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
keys
|
keys.stream()
|
||||||
.stream()
|
|
||||||
.map(modules::remove)
|
.map(modules::remove)
|
||||||
.map(module -> module.renameProject(oldName, newName))
|
.forEach(
|
||||||
.forEach(module -> {
|
module -> {
|
||||||
modules.put(module.getName().toString(), module);
|
module.renameProject(newName);
|
||||||
});
|
modules.put(module.getName().toString(), module);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -140,9 +135,7 @@ public class TopLevelScope implements TruffleObject {
|
|||||||
MethodNames.TopScope.UNREGISTER_MODULE);
|
MethodNames.TopScope.UNREGISTER_MODULE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Handles member invocation through the polyglot API. */
|
||||||
* Handles member invocation through the polyglot API.
|
|
||||||
*/
|
|
||||||
@ExportMessage
|
@ExportMessage
|
||||||
abstract static class InvokeMember {
|
abstract static class InvokeMember {
|
||||||
private static Module getModule(
|
private static Module getModule(
|
||||||
|
@ -39,6 +39,7 @@ import org.enso.interpreter.node.expression.literal.{
|
|||||||
import org.enso.interpreter.node.scope.{AssignmentNode, ReadLocalVariableNode}
|
import org.enso.interpreter.node.scope.{AssignmentNode, ReadLocalVariableNode}
|
||||||
import org.enso.interpreter.node.{
|
import org.enso.interpreter.node.{
|
||||||
ClosureRootNode,
|
ClosureRootNode,
|
||||||
|
MethodRootNode,
|
||||||
ExpressionNode => RuntimeExpression
|
ExpressionNode => RuntimeExpression
|
||||||
}
|
}
|
||||||
import org.enso.interpreter.runtime.Context
|
import org.enso.interpreter.runtime.Context
|
||||||
@ -217,34 +218,39 @@ class IrToTruffle(
|
|||||||
dataflowInfo
|
dataflowInfo
|
||||||
)
|
)
|
||||||
|
|
||||||
val funNode = methodDef.body match {
|
val cons = moduleScope
|
||||||
|
.getConstructor(typeName)
|
||||||
|
.orElseThrow(() =>
|
||||||
|
new VariableDoesNotExistException(methodDef.typeName.name)
|
||||||
|
)
|
||||||
|
|
||||||
|
val function = methodDef.body match {
|
||||||
case fn: IR.Function =>
|
case fn: IR.Function =>
|
||||||
expressionProcessor.processFunctionBody(
|
val (body, arguments) =
|
||||||
fn.arguments,
|
expressionProcessor.buildFunctionBody(fn.arguments, fn.body)
|
||||||
fn.body,
|
val rootNode = MethodRootNode.build(
|
||||||
methodDef.location,
|
language,
|
||||||
Some(methodDef.methodName.name)
|
expressionProcessor.scope,
|
||||||
|
moduleScope,
|
||||||
|
body,
|
||||||
|
makeSection(methodDef.location),
|
||||||
|
cons,
|
||||||
|
methodDef.methodName.name
|
||||||
|
)
|
||||||
|
val callTarget = Truffle.getRuntime.createCallTarget(rootNode)
|
||||||
|
new RuntimeFunction(
|
||||||
|
callTarget,
|
||||||
|
null,
|
||||||
|
new FunctionSchema(
|
||||||
|
FunctionSchema.CallStrategy.CALL_LOOP,
|
||||||
|
arguments: _*
|
||||||
|
)
|
||||||
)
|
)
|
||||||
case _ =>
|
case _ =>
|
||||||
throw new CompilerError(
|
throw new CompilerError(
|
||||||
"Method bodies must be functions at the point of codegen."
|
"Method bodies must be functions at the point of codegen."
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val function = new RuntimeFunction(
|
|
||||||
funNode.getCallTarget,
|
|
||||||
null,
|
|
||||||
new FunctionSchema(
|
|
||||||
FunctionSchema.CallStrategy.CALL_LOOP,
|
|
||||||
funNode.getArgs: _*
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
val cons = moduleScope
|
|
||||||
.getConstructor(typeName)
|
|
||||||
.orElseThrow(() =>
|
|
||||||
new VariableDoesNotExistException(methodDef.typeName.name)
|
|
||||||
)
|
|
||||||
moduleScope.registerMethod(cons, methodDef.methodName.name, function)
|
moduleScope.registerMethod(cons, methodDef.methodName.name, function)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -300,7 +306,7 @@ class IrToTruffle(
|
|||||||
val scopeName: String
|
val scopeName: String
|
||||||
) {
|
) {
|
||||||
|
|
||||||
private var currentVarName = "anonymous"
|
private var currentVarName = "<anonymous>"
|
||||||
|
|
||||||
// === Construction =======================================================
|
// === Construction =======================================================
|
||||||
|
|
||||||
@ -412,15 +418,14 @@ class IrToTruffle(
|
|||||||
childScope,
|
childScope,
|
||||||
moduleScope,
|
moduleScope,
|
||||||
blockNode,
|
blockNode,
|
||||||
null,
|
makeSection(block.location),
|
||||||
s"default::$scopeName",
|
currentVarName
|
||||||
null
|
|
||||||
)
|
)
|
||||||
|
|
||||||
val callTarget = Truffle.getRuntime.createCallTarget(defaultRootNode)
|
val callTarget = Truffle.getRuntime.createCallTarget(defaultRootNode)
|
||||||
setLocation(CreateThunkNode.build(callTarget), block.location)
|
setLocation(CreateThunkNode.build(callTarget), block.location)
|
||||||
} else {
|
} else {
|
||||||
val statementExprs = block.expressions.map(this.run(_)).toArray
|
val statementExprs = block.expressions.map(this.run).toArray
|
||||||
val retExpr = this.run(block.returnValue)
|
val retExpr = this.run(block.returnValue)
|
||||||
|
|
||||||
val blockNode = BlockNode.build(statementExprs, retExpr)
|
val blockNode = BlockNode.build(statementExprs, retExpr)
|
||||||
@ -520,8 +525,7 @@ class IrToTruffle(
|
|||||||
val branchCodeNode = childProcessor.processFunctionBody(
|
val branchCodeNode = childProcessor.processFunctionBody(
|
||||||
arg,
|
arg,
|
||||||
branch.expression,
|
branch.expression,
|
||||||
branch.location,
|
branch.location
|
||||||
None
|
|
||||||
)
|
)
|
||||||
|
|
||||||
val branchNode = CatchAllBranchNode.build(branchCodeNode)
|
val branchNode = CatchAllBranchNode.build(branchCodeNode)
|
||||||
@ -542,8 +546,7 @@ class IrToTruffle(
|
|||||||
val branchCodeNode = childProcessor.processFunctionBody(
|
val branchCodeNode = childProcessor.processFunctionBody(
|
||||||
fieldsAsArgs,
|
fieldsAsArgs,
|
||||||
branch.expression,
|
branch.expression,
|
||||||
branch.location,
|
branch.location
|
||||||
None
|
|
||||||
)
|
)
|
||||||
|
|
||||||
moduleScope.getConstructor(constructor.name).toScala match {
|
moduleScope.getConstructor(constructor.name).toScala match {
|
||||||
@ -659,8 +662,7 @@ class IrToTruffle(
|
|||||||
val fn = child.processFunctionBody(
|
val fn = child.processFunctionBody(
|
||||||
function.arguments,
|
function.arguments,
|
||||||
function.body,
|
function.body,
|
||||||
function.location,
|
function.location
|
||||||
None
|
|
||||||
)
|
)
|
||||||
|
|
||||||
fn
|
fn
|
||||||
@ -755,20 +757,19 @@ class IrToTruffle(
|
|||||||
setLocation(ErrorNode.build(payload), error.location)
|
setLocation(ErrorNode.build(payload), error.location)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Generates code for an Enso function body.
|
/**
|
||||||
|
* Processes function arguments, generates arguments reads and creates
|
||||||
|
* a node to represent the whole method body.
|
||||||
*
|
*
|
||||||
* @param arguments the arguments to the function
|
* @param arguments the argument definitions
|
||||||
* @param body the body of the function
|
* @param body the body definition
|
||||||
* @param location the location at which the function exists in the source
|
* @return a node for the final shape of function body and pre-processed
|
||||||
* @param name the name of the function
|
* argument definitions.
|
||||||
* @return a truffle node representing the described function
|
|
||||||
*/
|
*/
|
||||||
def processFunctionBody(
|
def buildFunctionBody(
|
||||||
arguments: List[IR.DefinitionArgument],
|
arguments: List[IR.DefinitionArgument],
|
||||||
body: IR.Expression,
|
body: IR.Expression
|
||||||
location: Option[IdentifiedLocation],
|
): (BlockNode, Array[ArgumentDefinition]) = {
|
||||||
name: Option[String]
|
|
||||||
): CreateFunctionNode = {
|
|
||||||
val argFactory = new DefinitionArgumentProcessor(scopeName, scope)
|
val argFactory = new DefinitionArgumentProcessor(scopeName, scope)
|
||||||
|
|
||||||
val argDefinitions = new Array[ArgumentDefinition](arguments.size)
|
val argDefinitions = new Array[ArgumentDefinition](arguments.size)
|
||||||
@ -809,24 +810,35 @@ class IrToTruffle(
|
|||||||
val bodyExpr = this.run(body)
|
val bodyExpr = this.run(body)
|
||||||
|
|
||||||
val fnBodyNode = BlockNode.build(argExpressions.toArray, bodyExpr)
|
val fnBodyNode = BlockNode.build(argExpressions.toArray, bodyExpr)
|
||||||
|
fnBodyNode.setTail(bodyIsTail)
|
||||||
|
(fnBodyNode, argDefinitions)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Generates code for an Enso function body.
|
||||||
|
*
|
||||||
|
* @param arguments the arguments to the function
|
||||||
|
* @param body the body of the function
|
||||||
|
* @param location the location at which the function exists in the source
|
||||||
|
* @return a truffle node representing the described function
|
||||||
|
*/
|
||||||
|
def processFunctionBody(
|
||||||
|
arguments: List[IR.DefinitionArgument],
|
||||||
|
body: IR.Expression,
|
||||||
|
location: Option[IdentifiedLocation]
|
||||||
|
): CreateFunctionNode = {
|
||||||
|
val (fnBodyNode, argDefinitions) = buildFunctionBody(arguments, body)
|
||||||
val fnRootNode = ClosureRootNode.build(
|
val fnRootNode = ClosureRootNode.build(
|
||||||
language,
|
language,
|
||||||
scope,
|
scope,
|
||||||
moduleScope,
|
moduleScope,
|
||||||
fnBodyNode,
|
fnBodyNode,
|
||||||
makeSection(location),
|
makeSection(location),
|
||||||
scopeName,
|
scopeName
|
||||||
name
|
|
||||||
.map(moduleScope.getModule.getName.createChild)
|
|
||||||
.map(_.toString)
|
|
||||||
.orNull
|
|
||||||
)
|
)
|
||||||
val callTarget = Truffle.getRuntime.createCallTarget(fnRootNode)
|
val callTarget = Truffle.getRuntime.createCallTarget(fnRootNode)
|
||||||
|
|
||||||
val expr = CreateFunctionNode.build(callTarget, argDefinitions)
|
val expr = CreateFunctionNode.build(callTarget, argDefinitions)
|
||||||
|
|
||||||
fnBodyNode.setTail(bodyIsTail)
|
|
||||||
|
|
||||||
setLocation(expr, location)
|
setLocation(expr, location)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -987,7 +999,7 @@ class IrToTruffle(
|
|||||||
argumentExpression.setTail(argExpressionIsTail)
|
argumentExpression.setTail(argExpressionIsTail)
|
||||||
|
|
||||||
val displayName =
|
val displayName =
|
||||||
s"call_argument<${name.getOrElse(String.valueOf(position))}>"
|
s"argument<${name.getOrElse(String.valueOf(position))}>"
|
||||||
|
|
||||||
val section = value.location
|
val section = value.location
|
||||||
.map(loc => source.createSection(loc.start, loc.end))
|
.map(loc => source.createSection(loc.start, loc.end))
|
||||||
@ -1000,8 +1012,7 @@ class IrToTruffle(
|
|||||||
moduleScope,
|
moduleScope,
|
||||||
argumentExpression,
|
argumentExpression,
|
||||||
section,
|
section,
|
||||||
displayName,
|
displayName
|
||||||
null
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1077,8 +1088,7 @@ class IrToTruffle(
|
|||||||
moduleScope,
|
moduleScope,
|
||||||
defaultExpression,
|
defaultExpression,
|
||||||
null,
|
null,
|
||||||
s"default::$scopeName::${arg.name}",
|
s"<default::$scopeName::${arg.name}>"
|
||||||
null
|
|
||||||
)
|
)
|
||||||
|
|
||||||
CreateThunkNode.build(
|
CreateThunkNode.build(
|
||||||
|
@ -22,7 +22,6 @@ import org.enso.interpreter.instrument.{
|
|||||||
Visualisation
|
Visualisation
|
||||||
}
|
}
|
||||||
import org.enso.interpreter.node.callable.FunctionCallInstrumentationNode.FunctionCall
|
import org.enso.interpreter.node.callable.FunctionCallInstrumentationNode.FunctionCall
|
||||||
import org.enso.pkg.QualifiedName
|
|
||||||
import org.enso.polyglot.runtime.Runtime.Api
|
import org.enso.polyglot.runtime.Runtime.Api
|
||||||
import org.enso.polyglot.runtime.Runtime.Api.ContextId
|
import org.enso.polyglot.runtime.Runtime.Api.ContextId
|
||||||
|
|
||||||
@ -255,10 +254,9 @@ trait ProgramExecutionSupport {
|
|||||||
)(implicit ctx: RuntimeContext): Option[Api.MethodPointer] =
|
)(implicit ctx: RuntimeContext): Option[Api.MethodPointer] =
|
||||||
for {
|
for {
|
||||||
call <- Option(value.getCallInfo)
|
call <- Option(value.getCallInfo)
|
||||||
qualifiedName <- QualifiedName.fromString(call.getCallTargetName)
|
moduleName <- Option(call.getModuleName)
|
||||||
moduleName <- qualifiedName.getParent
|
functionName = call.getFunctionName
|
||||||
functionName <- QualifiedName.fromString(call.getFunctionName)
|
typeName <- Option(call.getTypeName).map(_.item)
|
||||||
typeName <- functionName.getParent
|
|
||||||
module <- OptionConverters.toScala(
|
module <- OptionConverters.toScala(
|
||||||
ctx.executionService.getContext.getTopScope
|
ctx.executionService.getContext.getTopScope
|
||||||
.getModule(moduleName.toString)
|
.getModule(moduleName.toString)
|
||||||
@ -266,8 +264,8 @@ trait ProgramExecutionSupport {
|
|||||||
modulePath <- Option(module.getPath)
|
modulePath <- Option(module.getPath)
|
||||||
} yield Api.MethodPointer(
|
} yield Api.MethodPointer(
|
||||||
new File(modulePath),
|
new File(modulePath),
|
||||||
typeName.toString,
|
typeName,
|
||||||
functionName.module
|
functionName
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
package org.enso.pkg
|
package org.enso.pkg
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a qualified name of a source module.
|
* Represents a qualified name of a source item.
|
||||||
*
|
*
|
||||||
* @param path the names of the package and directories the module is
|
* @param path the names of the package and directories the item is
|
||||||
* contained in
|
* contained in
|
||||||
* @param module the name of the module
|
* @param item the name of the item
|
||||||
*/
|
*/
|
||||||
case class QualifiedName(path: List[String], module: String) {
|
case class QualifiedName(path: List[String], item: String) {
|
||||||
override def toString: String =
|
override def toString: String =
|
||||||
(path :+ module).mkString(QualifiedName.separator)
|
(path :+ item).mkString(QualifiedName.separator)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the parent of this qualified name.
|
* Get the parent of this qualified name.
|
||||||
@ -26,21 +26,16 @@ case class QualifiedName(path: List[String], module: String) {
|
|||||||
* @return a new qualified name based on this name.
|
* @return a new qualified name based on this name.
|
||||||
*/
|
*/
|
||||||
def createChild(name: String): QualifiedName =
|
def createChild(name: String): QualifiedName =
|
||||||
QualifiedName(path :+ module, name)
|
QualifiedName(path :+ item, name)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renames a project part of this [[QualifiedName]].
|
* Renames a project part of this [[QualifiedName]].
|
||||||
*
|
*
|
||||||
* @param oldName the old project name
|
|
||||||
* @param newName the new project name
|
* @param newName the new project name
|
||||||
* @return a [[QualifiedName]] with the updated project name
|
* @return a [[QualifiedName]] with the updated project name
|
||||||
*/
|
*/
|
||||||
def renameProject(oldName: String, newName: String): QualifiedName = {
|
def renameProject(newName: String): QualifiedName = {
|
||||||
if (path.head == oldName) {
|
this.copy(path = newName :: path.tail)
|
||||||
this.copy(path = newName :: path.tail)
|
|
||||||
} else {
|
|
||||||
this
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,6 @@ import Base.Test
|
|||||||
import Test.List_Spec
|
import Test.List_Spec
|
||||||
import Test.Number_Spec
|
import Test.Number_Spec
|
||||||
|
|
||||||
main = Suite.run <|
|
main = Suite.runMain <|
|
||||||
List_Spec.spec
|
List_Spec.spec
|
||||||
Number_Spec.spec
|
Number_Spec.spec
|
||||||
|
Loading…
Reference in New Issue
Block a user