Skip to content

Commit

Permalink
(compiler) Make compiled mode be the default and drop interpreted mode (
Browse files Browse the repository at this point in the history
#465)

This is the biggest change for a while. Because
#406 is moving along
nicely, we are now ready to:

* Flip the switch, i.e. _make compiled mode the default_ for Perlang.
* Remove the PerlangInterpreter class in its entirety. This may be
  reimplemented in one form or another, once we have the LLVM-emitting
  backend in place, but not as a tree-walking interpreter.

This probably means we'll drop Windows (and perhaps macOS) support for a
while. Please don't despair; this is not intended to be permanent. While
we depend on a specific Clang version for compiling Perlang code, it
simply gets easier to not have to support too many platforms. Once we
have started emitting C++ code from Perlang, in an idempotent way (being
able to disable all timestamping etc in the file header), we could see
how hard it would be to get this Perlang-to-C++-transpiled code
compiling on macOS and Windows too.
  • Loading branch information
perlun authored Apr 26, 2024
1 parent 783c5df commit 315b642
Show file tree
Hide file tree
Showing 14 changed files with 83 additions and 2,877 deletions.
14 changes: 5 additions & 9 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,12 @@ jobs:
strategy:
matrix:
runner:
- windows-2022
# Windows and maOS disabled as of https://github.com/perlang-org/perlang/pull/465. We are planning to
# reintroduce Windows and macOS support in the future, but for now, we are focusing on Linux for simplicity.
# Once we have a compiler which is C# and C++ (transpiled from Perlang), we should be able to build the
# compiler for these platforms, but getting rid of the "Linux-onliness" of the compiler really depends on
# moving to an LLVM-based backend, so we don't need to shell-execute clang++-14 to compile the C++ code.
- ubuntu-22.04
- macos-11
execution_mode:
- interpreted
include:
# Run in interpreted mode on all runners, but additionally also in compiled mode on Ubuntu
- runner: ubuntu-22.04
execution_mode: compiled

steps:
- uses: actions/checkout@v1
Expand All @@ -39,5 +36,4 @@ jobs:
- name: Run test suite
run: dotnet test --configuration Release --verbosity minimal
env:
PERLANG_EXPERIMENTAL_COMPILATION: ${{ matrix.execution_mode == 'compiled' && 'true' || 'false' }}
PERLANG_ROOT: ${{ github.workspace }}
3 changes: 3 additions & 0 deletions .github/workflows/website.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ jobs:
- name: Build Perlang (in release mode)
run: dotnet publish src/Perlang.ConsoleApp/Perlang.ConsoleApp.csproj -c Release -r linux-x64 --self-contained true /p:PublishReadyToRun=true /p:SolutionDir=$(pwd)/

- name: Rebuild stdlib
run: make stdlib && cp -rv lib src/Perlang.ConsoleApp/bin/Release/net7.0/linux-x64/publish

- name: Ensure examples execute without errors
run: make docs-test-examples SHELL="sh -x -e"

Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ src/Perlang.Common/CommonConstants.Generated.cs: scripts/update_common_constants
clean:
dotnet clean
rm -f src/Perlang.Common/CommonConstants.Generated.cs
rm -rf src/Perlang.ConsoleApp/bin/Release

docs-clean:
rm -rf _site
Expand Down
14 changes: 14 additions & 0 deletions Perlang.sln
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,18 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "release-notes", "release-no
release-notes\v0.5.0.md = release-notes\v0.5.0.md
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".github", ".github", "{74DEE88F-82F6-49CB-A019-E527D293E0B4}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{0220A61B-85BE-4076-9FDA-0467E6971F40}"
ProjectSection(SolutionItems) = preProject
.github\workflows\perlang-install.yml = .github\workflows\perlang-install.yml
.github\workflows\publish-release-packages.yml = .github\workflows\publish-release-packages.yml
.github\workflows\publish-snapshot-packages.yml = .github\workflows\publish-snapshot-packages.yml
.github\workflows\publish-website.yml = .github\workflows\publish-website.yml
.github\workflows\test.yml = .github\workflows\test.yml
.github\workflows\website.yml = .github\workflows\website.yml
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -99,5 +111,7 @@ Global
{E9D632CB-E520-4868-9E64-A4A70ACD713C} = {F13F8E4E-5231-4321-9722-1BFCC08E5BB5}
{7E7CF7BF-F792-49C9-BB16-67FE856D8D51} = {B924E83B-6AFE-4ABF-B79D-444F92582892}
{3223DBA6-64AE-41B5-8864-6FDD232FCE7F} = {47B4A37F-6999-4510-9815-418E03D7B39E}
{74DEE88F-82F6-49CB-A019-E527D293E0B4} = {47B4A37F-6999-4510-9815-418E03D7B39E}
{0220A61B-85BE-4076-9FDA-0467E6971F40} = {74DEE88F-82F6-49CB-A019-E527D293E0B4}
EndGlobalSection
EndGlobal
6 changes: 5 additions & 1 deletion docs/examples/the-language/calling-base64-encode.per
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
// calling-base64-encode.per

// TODO: The code below no longer works as of the changes being done in
// https://github.com/perlang-org/perlang/issues/406; calling methods in
// the standard library is currently broken.

// Will output SGVsbG8sIFdvcmxk
print Base64.encode("Hello, World");
//print Base64.encode("Hello, World");
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// defining-and-calling-a-function-with-parameters.per
fun greet(name: string, age: int): void {
print "Hello " + name + ". Your age is " + age;
// TODO: depends on functionality not yet supported in compiled mode.
// https://github.com/perlang-org/perlang/issues/406
//print "Hello " + name + ". Your age is " + age;
}

// Expected output: Hello John Doe. Your age is 42
Expand Down
4 changes: 4 additions & 0 deletions release-notes/v0.5.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
hope to bring it back in the future.
- The `-e` option has been removed. Similarly as above, this was a feature that was only available in interpreted mode
which is now going away.
- Interpreted mode has been removed, and compiled mode is now the default. Some features are still not available in
compiled mode; these will print an error or throw an exception if you attempt to use them.

### Added
#### Experimental compilation
Expand All @@ -18,6 +20,7 @@
- Remove `using namespace` in generated C++ code [[#458][458]]
- Add partial inline C++ support [[#462][462]]
- Detect method being redefined [[#464][464]]
- Make compiled mode be the default and drop interpreted mode [[#465][465]]

### Changed
#### Data types
Expand Down Expand Up @@ -49,3 +52,4 @@
[462]: https://github.com/perlang-org/perlang/pull/462
[463]: https://github.com/perlang-org/perlang/pull/463
[464]: https://github.com/perlang-org/perlang/pull/464
[465]: https://github.com/perlang-org/perlang/pull/465
12 changes: 9 additions & 3 deletions src/Perlang.Common/PerlangMode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,17 @@ namespace Perlang;

public static class PerlangMode
{
public static bool ExperimentalCompilation
public static bool ExperimentalCompilation => !ExperimentalInterpretation;

private static bool ExperimentalInterpretation
{
get
{
string environmentVariable = Environment.GetEnvironmentVariable("PERLANG_EXPERIMENTAL_COMPILATION");
// This used to be an environment variable PERLANG_EXPERIMENTAL_COMPILATION. Now that compilation is enabled
// by default, we have flipped the flag to instead be PERLANG_EXPERIMENTAL_INTERPRETATION. The interpreter
// part (which will in fact emit native code via an LLVM backend) is not yet implemented, but we're keeping
// the infrastructure in place to make room for it until if/when it gets implemented.
string environmentVariable = Environment.GetEnvironmentVariable("PERLANG_EXPERIMENTAL_INTERPRETATION");

// The environment variable takes precedence, if set
if (Boolean.TryParse(environmentVariable, out bool flag))
Expand All @@ -19,7 +25,7 @@ public static bool ExperimentalCompilation

string homeDirectory = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);

return File.Exists(Path.Combine(homeDirectory, ".perlang_experimental_compilation"));
return File.Exists(Path.Combine(homeDirectory, ".perlang_experimental_interpretation"));
}
}
}
41 changes: 4 additions & 37 deletions src/Perlang.ConsoleApp/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
using System.Text;
using System.Threading.Tasks;
using Perlang.Compiler;
using Perlang.Internal;
using Perlang.Interpreter;
using Perlang.Interpreter.Compiler;
using Perlang.Interpreter.NameResolution;
Expand Down Expand Up @@ -56,7 +55,6 @@ internal enum ExitCodes
INVALID_ARGUMENT = 67
}

private readonly PerlangInterpreter interpreter;
private readonly PerlangCompiler compiler;

/// <summary>
Expand All @@ -81,11 +79,6 @@ internal enum ExitCodes

private readonly HashSet<WarningType> disabledWarningsAsErrors;

/// <summary>
/// A flag which determines if (highly experimental) compilation to machine code is enabled or not.
/// </summary>
private readonly bool experimentalCompilation;

private bool hadError;
private bool hadRuntimeError;

Expand Down Expand Up @@ -267,20 +260,11 @@ internal Program(
this.standardOutputHandler = standardOutputHandler;
this.standardErrorHandler = standardOutputHandler;
this.disabledWarningsAsErrors = (disabledWarningsAsErrors ?? Enumerable.Empty<WarningType>()).ToHashSet();
this.experimentalCompilation = experimentalCompilation;

// Convenience fields while we are migrating away from CLR strings to Perlang strings.
this.standardOutputHandlerFromClrString = s => this.standardOutputHandler(Lang.String.from(s));
this.standardErrorHandlerFromClrString = s => this.standardErrorHandler(Lang.String.from(s));

interpreter = new PerlangInterpreter(
runtimeErrorHandler ?? RuntimeError,
this.standardOutputHandler,
null,
arguments ?? new List<string>(),
replMode: replMode
);

compiler = new PerlangCompiler(
runtimeErrorHandler ?? RuntimeError,
this.standardOutputHandler
Expand All @@ -298,14 +282,7 @@ private int RunFile(string path)
var bytes = File.ReadAllBytes(path);
string source = Encoding.UTF8.GetString(bytes);

if (experimentalCompilation)
{
CompileAndRun(source, path, CompilerWarning);
}
else
{
Run(source, CompilerWarning);
}
CompileAndRun(source, path, CompilerWarning);

// Indicate an error in the exit code.
if (hadError)
Expand Down Expand Up @@ -350,18 +327,6 @@ private int CompileAndAssembleFile(string path)
return (int)ExitCodes.SUCCESS;
}

internal int Run(string source, CompilerWarningHandler compilerWarningHandler)
{
object? result = interpreter.Eval(source, ScanError, ParseError, NameResolutionError, ValidationError, ValidationError, compilerWarningHandler);

if (result != null && result != VoidObject.Void)
{
standardOutputHandler(Utils.Stringify(result));
}

return (int)ExitCodes.SUCCESS;
}

private void CompileAndRun(string source, string path, CompilerWarningHandler compilerWarningHandler)
{
compiler.CompileAndRun(source, path, CompilerFlags.None, ScanError, ParseError, NameResolutionError, ValidationError, ValidationError, compilerWarningHandler);
Expand All @@ -374,7 +339,9 @@ private void CompileAndAssemble(string source, string path, CompilerWarningHandl

private void ParseAndPrint(string source)
{
string? result = interpreter.Parse(source, ScanError, ParseError);
// TODO: Implement this in PerlangCompiler. Should definitely be doable, and could be taken in a nice little
// TODO: isolated PR of its own.
string? result = compiler.Parse(source, ScanError, ParseError);

if (result == null)
{
Expand Down
9 changes: 7 additions & 2 deletions src/Perlang.Interpreter/Compiler/PerlangCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ private static bool CompilationCacheDisabled
}
}

internal IBindingHandler BindingHandler { get; }

private readonly Action<RuntimeError> runtimeErrorHandler;
private readonly Action<Lang.String> standardOutputHandler;
private readonly PerlangEnvironment globals = new();
Expand All @@ -97,8 +99,6 @@ private static bool CompilationCacheDisabled
private readonly ImmutableDictionary<string, Type> nativeClasses;
private readonly IDictionary<string, Method> methods;

private IBindingHandler BindingHandler { get; }

private StringBuilder currentMethod;

private int indentationLevel = 1;
Expand Down Expand Up @@ -1562,4 +1562,9 @@ private record Method(string Name, IImmutableList<Parameter> Parameters, string
)
);
}

public string? Parse(string source, Action<ScanError> scanError, Action<ParseError> parseError)
{
throw new NotImplementedException();
}
}
Loading

0 comments on commit 315b642

Please sign in to comment.