This instance will be upgraded to Heptapod 0.17.0 on 2020-11-26 at 14:00 UTC+1 (a few minutes of down time)

Commit 39bdf431 authored by Jesse McGrew's avatar Jesse McGrew

Issue error ZIL0400 (+ info ZIL0403) for "OPT" or "AUX" variables in GO.

Issue error ZIL0400 on its own for required arguments in GO.
Adapt diagnostic text for ZIL0400 and ZIL0403 to these situations.
[ZILF-210]
parent 371aefe7edcc
......@@ -83,7 +83,7 @@ namespace Zilf.Emit.Zap
paramName = GameBuilder.SanitizeSymbol(paramName);
if (entryPoint)
throw new InvalidOperationException("Entry point may not have parameters");
throw new InvalidOperationException("Entry point may not have required parameters");
if (LocalExists(paramName))
throw new ArgumentException("Local variable already exists: " + paramName, nameof(paramName));
......@@ -92,14 +92,14 @@ namespace Zilf.Emit.Zap
return local;
}
/// <exception cref="InvalidOperationException">This is an entry point routine.</exception>
/// <exception cref="InvalidOperationException">This is an entry point routine and the target is not V6.</exception>
/// <exception cref="ArgumentException">A local variable named <paramref name="paramName"/> is already defined.</exception>
public ILocalBuilder DefineOptionalParameter(string paramName)
{
paramName = GameBuilder.SanitizeSymbol(paramName);
if (entryPoint)
throw new InvalidOperationException("Entry point may not have parameters");
if (entryPoint && game.zversion != 6)
throw new InvalidOperationException("Entry point may not have optional parameters");
if (LocalExists(paramName))
throw new ArgumentException("Local variable already exists: " + paramName, nameof(paramName));
......@@ -108,13 +108,13 @@ namespace Zilf.Emit.Zap
return local;
}
/// <exception cref="InvalidOperationException">This is an entry point routine.</exception>
/// <exception cref="InvalidOperationException">This is an entry point routine and the target is not V6.</exception>
/// <exception cref="ArgumentException">A local variable named <paramref name="localName"/> is already defined.</exception>
public ILocalBuilder DefineLocal(string localName)
{
localName = GameBuilder.SanitizeSymbol(localName);
if (entryPoint)
if (entryPoint && game.zversion != 6)
throw new InvalidOperationException("Entry point may not have local variables");
if (LocalExists(localName))
throw new ArgumentException("Local variable already exists: " + localName, nameof(localName));
......
......@@ -158,35 +158,37 @@ namespace Zilf.Compiler
ILocalBuilder MakeLocalBuilder(ArgItem arg, string uniqueArgName)
{
ILocalBuilder lb;
switch (arg.Type)
try
{
case ArgItem.ArgType.Required:
try
{
lb = rb.DefineRequiredParameter(uniqueArgName);
}
catch (InvalidOperationException)
return arg.Type switch
{
ArgItem.ArgType.Required => rb.DefineRequiredParameter(uniqueArgName),
ArgItem.ArgType.Optional => rb.DefineOptionalParameter(uniqueArgName),
ArgItem.ArgType.Auxiliary => rb.DefineLocal(uniqueArgName),
_ => throw UnhandledCaseException.FromEnum(arg.Type),
};
}
catch (InvalidOperationException)
{
var ex = new CompilerError(
CompilerMessages._0_Are_Not_Allowed_In_The_Entry_Point_Routine,
arg.Type switch
{
throw new CompilerError(
CompilerMessages.Expression_Needs_Temporary_Variables_Not_Allowed_Here);
}
break;
ArgItem.ArgType.Required => "required arguments",
ArgItem.ArgType.Optional => "optional arguments",
ArgItem.ArgType.Auxiliary => "local variables",
_ => throw UnhandledCaseException.FromEnum(arg.Type),
});
case ArgItem.ArgType.Optional:
lb = rb.DefineOptionalParameter(uniqueArgName);
break;
case ArgItem.ArgType.Auxiliary:
lb = rb.DefineLocal(uniqueArgName);
break;
if (arg.Type != ArgItem.ArgType.Required)
{
ex = ex.Combine(new CompilerError(
CompilerMessages.This_Would_Be_Legal_In_Other_Zmachine_Versions_Eg_V0,
6));
}
default:
throw UnhandledCaseException.FromEnum(arg.Type);
throw ex;
}
return lb;
}
void SetOrEmitDefaultValue(ILocalBuilder lb, ArgItem arg)
......@@ -343,7 +345,12 @@ namespace Zilf.Compiler
}
catch (InvalidOperationException)
{
throw new CompilerError(CompilerMessages.Expression_Needs_Temporary_Variables_Not_Allowed_Here);
throw new CompilerError(
CompilerMessages._0_Are_Not_Allowed_In_The_Entry_Point_Routine,
"expressions requiring temporary variables")
.Combine(new CompilerError(
CompilerMessages.This_Would_Be_Legal_In_Other_Zmachine_Versions_Eg_V0,
6));
}
TempLocalNames.Add(tempName);
......
......@@ -147,14 +147,14 @@ namespace Zilf.Diagnostics
// Platform Limits - 0400
[Error("expression needs temporary variables, not allowed here")]
public const int Expression_Needs_Temporary_Variables_Not_Allowed_Here = 400;
[Error("{0} are not allowed in the entry point routine")]
public const int _0_Are_Not_Allowed_In_The_Entry_Point_Routine = 400;
[Error("header extensions not supported for this target")]
public const int Header_Extensions_Not_Supported_For_This_Target = 401;
[Error("too many call arguments: only {0} allowed in V{1}")]
public const int Too_Many_Call_Arguments_Only_0_Allowed_In_V1 = 402;
[Info("this arg count would be legal in other Z-machine versions, e.g. V{0}")]
public const int This_Arg_Count_Would_Be_Legal_In_Other_Zmachine_Versions_Eg_V0 = 403;
[Info("this would be legal in other Z-machine versions, e.g. V{0}")]
public const int This_Would_Be_Legal_In_Other_Zmachine_Versions_Eg_V0 = 403;
[Error("too many {0}: {1} defined, only {2} allowed")]
public const int Too_Many_0_1_Defined_Only_2_Allowed = 404;
[Error("{0} is not supported in this Z-machine version")]
......
......@@ -89,7 +89,7 @@ namespace Zilf.Language
if (acceptableVersion != null)
{
var info = new CompilerError(
CompilerMessages.This_Arg_Count_Would_Be_Legal_In_Other_Zmachine_Versions_Eg_V0,
CompilerMessages.This_Would_Be_Legal_In_Other_Zmachine_Versions_Eg_V0,
acceptableVersion);
error = error.Combine(info);
}
......
......@@ -208,6 +208,19 @@ namespace Zilf.Tests.Integration
this.body = body;
}
public void Compiles()
{
var testCode = $"{GlobalCode()}\r\n" +
$"<ROUTINE GO ({argSpec})\r\n" +
$"\t{body}\r\n" +
"\t<QUIT>>";
var result = ZlrHelper.Run(testCode, null, compileOnly: true, wantDebugInfo: wantDebugInfo);
Assert.AreEqual(ZlrTestStatus.Finished, result.Status);
CheckWarnings(result);
}
public void DoesNotCompile()
{
var testCode = $"{GlobalCode()}\r\n" +
......
......@@ -557,6 +557,29 @@ namespace Zilf.Tests.Integration
{
AssertEntryPoint("X Y Z", @"<TELL ""hi"" CR>")
.DoesNotCompile();
AssertEntryPoint("\"OPT\" X Y Z", @"<TELL ""hi"" CR>")
.DoesNotCompile();
AssertEntryPoint("\"AUX\" X Y Z", @"<TELL ""hi"" CR>")
.DoesNotCompile();
}
[TestMethod]
public void GO_Routine_With_Locals_In_V6_Should_Compile()
{
AssertEntryPoint("\"AUX\" A", "<SET A 5>")
.InV6()
.Compiles();
AssertEntryPoint("\"OPT\" A", "<SET A 5>")
.InV6()
.Compiles();
// entry point still can't have required variables
AssertEntryPoint("A", "<SET A 5>")
.InV6()
.DoesNotCompile();
}
[TestMethod]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment