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
{
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 ) ;
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 ) ;
}
else
{
2015-12-13 14:57:21 +09:00
if ( results . Error is sunSourceException )
2015-12-10 13:14:32 +09:00
{
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 ;
}
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 ;
}
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 ] ;
}
2015-12-13 06:51:31 +09:00
static string GetErrorPreview ( sunSourceLocation location )
{
Stream file ;
try
{
file = File . OpenRead ( location . File ) ;
}
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 )
{
2015-12-13 14:55:05 +09:00
var c = preview [ column - 1 ] ;
if ( IsFullWidth ( c ) )
2015-12-13 06:51:31 +09:00
{
2015-12-13 14:55:05 +09:00
sb . Append ( " " ) ; // full-width hack
}
else if ( c = = '\t' )
{
sb . Append ( '\t' ) ;
}
else
{
sb . Append ( " " ) ;
2015-12-13 06:51:31 +09:00
}
}
sb . Append ( "^" ) ;
sb . Append ( "\n" ) ;
return sb . ToString ( ) ;
}
}
2015-12-13 14:55:05 +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-10 13:14:32 +09:00
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 ) ; }
}
}