ssc/frontend/main.cs

172 lines
4.6 KiB
C#
Raw Normal View History

2015-12-10 13:14:32 +09:00
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
2015-12-13 06:51:31 +09:00
using System.Text;
2015-12-10 13:14:32 +09:00
namespace arookas
{
2015-12-28 17:13:30 +09:00
static class SSC {
static void Main(string[] args) {
2015-12-10 13:14:32 +09:00
Message("ssc v0.1 arookas\n");
var cmd = new aCommandLine(args);
2015-12-28 17:13:30 +09:00
if (cmd.Count == 0) {
2015-12-10 13:14:32 +09:00
Message("Usage: ssc -input <input.sun> [-output <output.sb>]\n");
Pause();
Exit(1);
}
var compiler = new sunCompiler();
int exitCode = 0;
string inputFile, outputFile;
ReadCmdLine(cmd, out inputFile, out outputFile);
2015-12-28 17:13:30 +09:00
using (var output = OpenOutput(outputFile)) {
2015-12-10 13:14:32 +09:00
var results = compiler.Compile(inputFile, output);
2015-12-28 17:13:30 +09:00
if (results.Success) {
2015-12-10 13:14:32 +09:00
Message("Finished compiling in {0:F2}ms.\n", results.CompileTime.TotalMilliseconds);
Message(" Data count: {0}\n", results.Data.Length);
Message("Symbol count: {0}\n", results.Symbols.Length);
Message(" - builtins: {0}\n", results.Symbols.Count(i => i.Type == sunSymbolType.Builtin));
Message(" - functions: {0}\n", results.Symbols.Count(i => i.Type == sunSymbolType.Function));
Message(" - variables: {0}\n", results.Symbols.Count(i => i.Type == sunSymbolType.Variable));
2015-12-10 13:14:32 +09:00
}
2015-12-28 17:13:30 +09:00
else {
if (results.Error is sunSourceException) {
var error = results.Error as sunSourceException;
Error(" in file \"{0}\"\n at line {1}, col {2}\n\n{3}{4}", error.Location.ScriptName, error.Location.Line, error.Location.Column, GetErrorPreview(error.Location), error.Message);
2015-12-10 13:14:32 +09:00
exitCode = 1;
}
2015-12-28 17:13:30 +09:00
else {
2015-12-10 13:14:32 +09:00
var error = results.Error;
Error("{0}", error.Message);
exitCode = 1;
}
}
}
Pause();
Exit(exitCode);
}
2015-12-28 17:13:30 +09:00
static Stream OpenOutput(string path) {
try {
2015-12-10 13:14:32 +09:00
return File.Create(path);
}
2015-12-28 17:13:30 +09:00
catch {
2015-12-10 13:14:32 +09:00
Error("Failed to create output file '{0}'.", path);
Pause();
Exit(1);
}
return null;
}
2015-12-28 17:13:30 +09:00
// command-line
static void ReadCmdLine(aCommandLine cmd, out string inputFile, out string outputFile) {
2015-12-10 13:14:32 +09:00
inputFile = null;
outputFile = null;
2015-12-28 17:13:30 +09:00
foreach (var prm in cmd) {
switch (prm.Name) {
2015-12-10 13:14:32 +09:00
case "-input": GetInput(prm, ref inputFile); break;
case "-output": GetOutput(prm, ref outputFile); break;
}
}
2015-12-28 17:13:30 +09:00
if (inputFile == null) {
2015-12-10 13:14:32 +09:00
Error("Missing -input option.\n");
Pause();
Exit(1);
}
2015-12-28 17:13:30 +09:00
if (outputFile == null) {
2015-12-10 13:14:32 +09:00
outputFile = Path.ChangeExtension(inputFile, ".sb");
}
}
static void GetInput(aCommandLineParameter prm, ref string inputFile) {
2015-12-28 17:13:30 +09:00
if (inputFile != null) {
2015-12-10 13:14:32 +09:00
Error("Only one -input option is allowed.\n");
Pause();
Exit(1);
}
2015-12-28 17:13:30 +09:00
if (prm.Count != 1) {
2015-12-10 13:14:32 +09:00
Error("Incorrect number of arguments in -input option.\n");
Pause();
Exit(1);
}
inputFile = prm[0];
}
static void GetOutput(aCommandLineParameter prm, ref string outputFile) {
2015-12-28 17:13:30 +09:00
if (outputFile != null) {
2015-12-10 13:14:32 +09:00
Error("Only one -output option is allowed.\n");
Pause();
Exit(1);
}
2015-12-28 17:13:30 +09:00
if (prm.Count != 1) {
2015-12-10 13:14:32 +09:00
Error("Incorrect number of arguments in -output option.\n");
Pause();
Exit(1);
}
outputFile = prm[0];
}
2015-12-28 17:13:30 +09:00
// error preview
static string GetErrorPreview(sunSourceLocation location) {
2015-12-13 06:51:31 +09:00
Stream file;
2015-12-28 17:13:30 +09:00
try {
file = File.OpenRead(location.ScriptName);
2015-12-13 06:51:31 +09:00
}
2015-12-28 17:13:30 +09:00
catch {
2015-12-13 06:51:31 +09:00
// simply don't do a preview if opening a file fails
return "";
}
2015-12-28 17:13:30 +09:00
using (var reader = new StreamReader(file)) {
2015-12-13 06:51:31 +09:00
// skip to line
2015-12-28 17:13:30 +09:00
for (var line = 1; line < location.Line; ++line) {
2015-12-13 06:51:31 +09:00
reader.ReadLine();
}
// generate column string
var sb = new StringBuilder();
var preview = reader.ReadLine();
sb.AppendLine(preview);
2015-12-28 17:13:30 +09:00
for (var column = 1; column < location.Column; ++column) {
var c = preview[column - 1];
2015-12-28 17:13:30 +09:00
if (IsFullWidth(c)) {
sb.Append(" "); // full-width hack
}
2015-12-28 17:13:30 +09:00
else if (c == '\t') {
sb.Append('\t');
}
2015-12-28 17:13:30 +09:00
else {
sb.Append(" ");
2015-12-13 06:51:31 +09:00
}
}
sb.Append("^");
sb.Append("\n");
return sb.ToString();
}
}
2016-02-13 12:53:51 +09:00
static bool IsFullWidth(char c) {
return (c >= 0x2E80 && c <= 0x9FFF) || (c >= 0xFF00 && c <= 0xFFEF);
}
2015-12-13 06:51:31 +09:00
2015-12-28 17:13:30 +09:00
// output
2016-02-13 12:53:51 +09:00
static void Message(string format, params object[] args) {
Console.Write(format, args);
}
2015-12-28 17:13:30 +09:00
static void Warning(string format, params object[] args) {
2015-12-10 13:14:32 +09:00
Console.ForegroundColor = ConsoleColor.Yellow;
Console.Write("WARNING:\n");
Message(format, args);
Console.ResetColor();
}
2015-12-28 17:13:30 +09:00
static void Error(string format, params object[] args) {
2015-12-10 13:14:32 +09:00
Console.ForegroundColor = ConsoleColor.Red;
Console.Write("ERROR:\n");
Message(format, args);
Console.ResetColor();
}
2015-12-28 17:13:30 +09:00
2016-02-13 12:53:51 +09:00
[Conditional("DEBUG")] static void Pause() {
Console.ReadKey();
}
static void Exit(int code) {
Environment.Exit(code);
}
2015-12-10 13:14:32 +09:00
}
}