675f2ab4a7
Now the local identifier is associated with each node so symbols in function bodies (which are compiled long after the associated sunScriptFile instances are closed) can be mangled correctly.
162 lines
4.4 KiB
C#
162 lines
4.4 KiB
C#
using System;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Text;
|
|
|
|
namespace arookas
|
|
{
|
|
static class SSC {
|
|
static void Main(string[] args) {
|
|
Message("ssc v0.1 arookas\n");
|
|
var cmd = new CommandLine(args);
|
|
if (cmd.Count == 0) {
|
|
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);
|
|
using (var output = OpenOutput(outputFile)) {
|
|
var results = compiler.Compile(inputFile, output);
|
|
if (results.Success) {
|
|
Message("Finished compiling in {0:F2}ms.\n", results.CompileTime.TotalMilliseconds);
|
|
Message(" Data count: {0}\n", results.DataCount);
|
|
Message("Symbol count: {0}\n", results.SymbolCount);
|
|
Message(" - builtins: {0}\n", results.BuiltinCount);
|
|
Message(" - functions: {0}\n", results.FunctionCount);
|
|
Message(" - variables: {0}\n", results.VariableCount);
|
|
}
|
|
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);
|
|
exitCode = 1;
|
|
}
|
|
else {
|
|
var error = results.Error;
|
|
Error("{0}", error.Message);
|
|
exitCode = 1;
|
|
}
|
|
}
|
|
}
|
|
Pause();
|
|
Exit(exitCode);
|
|
}
|
|
|
|
static Stream OpenOutput(string path) {
|
|
try {
|
|
return File.Create(path);
|
|
}
|
|
catch {
|
|
Error("Failed to create output file '{0}'.", path);
|
|
Pause();
|
|
Exit(1);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
// command-line
|
|
static void ReadCmdLine(CommandLine cmd, out string inputFile, out string outputFile) {
|
|
inputFile = null;
|
|
outputFile = null;
|
|
foreach (var prm in cmd) {
|
|
switch (prm.Name) {
|
|
case "-input": GetInput(prm, ref inputFile); break;
|
|
case "-output": GetOutput(prm, ref outputFile); break;
|
|
}
|
|
}
|
|
if (inputFile == null) {
|
|
Error("Missing -input option.\n");
|
|
Pause();
|
|
Exit(1);
|
|
}
|
|
if (outputFile == null) {
|
|
outputFile = Path.ChangeExtension(inputFile, ".sb");
|
|
}
|
|
}
|
|
static void GetInput(CommandLineParameter prm, ref string inputFile) {
|
|
if (inputFile != null) {
|
|
Error("Only one -input option is allowed.\n");
|
|
Pause();
|
|
Exit(1);
|
|
}
|
|
if (prm.Count != 1) {
|
|
Error("Incorrect number of arguments in -input option.\n");
|
|
Pause();
|
|
Exit(1);
|
|
}
|
|
inputFile = prm[0];
|
|
}
|
|
static void GetOutput(CommandLineParameter prm, ref string outputFile) {
|
|
if (outputFile != null) {
|
|
Error("Only one -output option is allowed.\n");
|
|
Pause();
|
|
Exit(1);
|
|
}
|
|
if (prm.Count != 1) {
|
|
Error("Incorrect number of arguments in -output option.\n");
|
|
Pause();
|
|
Exit(1);
|
|
}
|
|
outputFile = prm[0];
|
|
}
|
|
|
|
// error preview
|
|
static string GetErrorPreview(sunSourceLocation location) {
|
|
Stream file;
|
|
try {
|
|
file = File.OpenRead(location.ScriptName);
|
|
}
|
|
catch {
|
|
// simply don't do a preview if opening a file fails
|
|
return "";
|
|
}
|
|
using (var reader = new StreamReader(file)) {
|
|
// skip to line
|
|
for (var line = 1; line < location.Line; ++line) {
|
|
reader.ReadLine();
|
|
}
|
|
// generate column string
|
|
var sb = new StringBuilder();
|
|
var preview = reader.ReadLine();
|
|
sb.AppendLine(preview);
|
|
for (var column = 1; column < location.Column; ++column) {
|
|
var c = preview[column - 1];
|
|
if (IsFullWidth(c)) {
|
|
sb.Append(" "); // full-width hack
|
|
}
|
|
else if (c == '\t') {
|
|
sb.Append('\t');
|
|
}
|
|
else {
|
|
sb.Append(" ");
|
|
}
|
|
}
|
|
sb.Append("^");
|
|
sb.Append("\n");
|
|
return sb.ToString();
|
|
}
|
|
}
|
|
static bool IsFullWidth(char c) { return (c >= 0x2E80 && c <= 0x9FFF) || (c >= 0xFF00 && c <= 0xFFEF); }
|
|
|
|
// output
|
|
static void Message(string format, params object[] args) { Console.Write(format, args); }
|
|
static void Warning(string format, params object[] args) {
|
|
Console.ForegroundColor = ConsoleColor.Yellow;
|
|
Console.Write("WARNING:\n");
|
|
Message(format, args);
|
|
Console.ResetColor();
|
|
}
|
|
static void Error(string format, params object[] args) {
|
|
Console.ForegroundColor = ConsoleColor.Red;
|
|
Console.Write("ERROR:\n");
|
|
Message(format, args);
|
|
Console.ResetColor();
|
|
}
|
|
|
|
[Conditional("DEBUG")] static void Pause() { Console.ReadKey(); }
|
|
static void Exit(int code) { Environment.Exit(code); }
|
|
}
|
|
}
|