2015-12-10 13:14:32 +09:00
using System ;
using System.Diagnostics ;
using System.IO ;
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 CommandLine ( 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 ) ;
2015-12-11 07:16:56 +09:00
Message ( " Data count: {0}\n" , results . DataCount ) ;
2015-12-10 13:14:32 +09:00
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 ) ;
}
2015-12-28 17:13:30 +09:00
else {
if ( results . Error is sunSourceException ) {
2015-12-13 14:57:21 +09:00
var error = results . Error as sunSourceException ;
2015-12-13 06:51:31 +09:00
Error ( " in file \"{0}\"\n at line {1}, col {2}\n\n{3}{4}" , error . Location . File , 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 ( CommandLine 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" ) ;
}
}
2015-12-28 17:13:30 +09:00
static void GetInput ( CommandLineParameter prm , ref string inputFile ) {
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 ] ;
}
2015-12-28 17:13:30 +09:00
static void GetOutput ( CommandLineParameter prm , ref string outputFile ) {
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 {
2015-12-13 06:51:31 +09:00
file = File . OpenRead ( location . File ) ;
}
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 ) {
2015-12-13 14:55:05 +09:00
var c = preview [ column - 1 ] ;
2015-12-28 17:13:30 +09:00
if ( IsFullWidth ( c ) ) {
2015-12-13 14:55:05 +09:00
sb . Append ( " " ) ; // full-width hack
}
2015-12-28 17:13:30 +09:00
else if ( c = = '\t' ) {
2015-12-13 14:55:05 +09:00
sb . Append ( '\t' ) ;
}
2015-12-28 17:13:30 +09:00
else {
2015-12-13 14:55:05 +09:00
sb . Append ( " " ) ;
2015-12-13 06:51:31 +09:00
}
}
sb . Append ( "^" ) ;
sb . Append ( "\n" ) ;
return sb . ToString ( ) ;
}
}
2015-12-28 17:13:30 +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
2015-12-10 13:14:32 +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
[Conditional("DEBUG")] static void Pause ( ) { Console . ReadKey ( ) ; }
2015-12-10 13:14:32 +09:00
static void Exit ( int code ) { Environment . Exit ( code ) ; }
}
}