Upsilon/UpsilonCompiler/Compiler.cs

127 lines
4.5 KiB
C#

using System;
using System.Text;
using Upsilon.BaseTypes;
using Upsilon.BaseTypes.Number;
using Upsilon.Binder;
using Type = Upsilon.BaseTypes.Type;
namespace UpsilonCompiler
{
public class Transpiler
{
public string TranspilerToCSharp(BoundScript script)
{
var s = script.Statement;
return Transpile(s);
}
private string Transpile(BoundNode e)
{
switch (e.Kind)
{
case BoundKind.BoundScript:
throw new ArgumentOutOfRangeException();
case BoundKind.BoundLiteralExpression:
return TranspileLiteralExpression((BoundLiteralExpression) e);
case BoundKind.BoundBinaryExpression:
return TranspileBinaryExpression((BoundBinaryExpression) e);
case BoundKind.BoundUnaryExpression:
case BoundKind.VariableExpression:
case BoundKind.BoundAssignmentStatement:
throw new ArgumentOutOfRangeException();
case BoundKind.BoundExpressionStatement:
return Transpile(((BoundExpressionStatement)e).Expression);
case BoundKind.BoundBlockStatement:
return TranspileBlockStatement((BoundBlockStatement) e);
case BoundKind.BoundIfStatement:
return TranspileIfStatement((BoundIfStatement) e);
case BoundKind.BoundElseStatement:
default:
throw new ArgumentOutOfRangeException(e.Kind.ToString());
}
}
private string TranspileBlockStatement(BoundBlockStatement s)
{
var sb = new StringBuilder();
foreach (var sStatement in s.Statements)
{
var compile = Transpile(sStatement);
sb.Append(compile);
sb.Append(";\n");
}
return sb.ToString();
}
private static string TranspileLiteralExpression(BoundLiteralExpression e)
{
switch (e.Type)
{
case Type.Nil:
return "null";
case Type.Boolean:
return ((LuaBoolean)e.Value) ? "true" : "false";
case Type.Number:
return ((Number) e.Value).ToString();
case Type.String:
case Type.Function:
case Type.UserData:
case Type.Thread:
case Type.Table:
default:
throw new ArgumentOutOfRangeException();
}
}
private string TranspileBinaryExpression(BoundBinaryExpression e)
{
var sb = new StringBuilder();
sb.Append("(");
var compiledLeft = Transpile(e.LeftExpression);
var compiledRight = Transpile(e.RightExpression);
sb.Append(compiledLeft);
switch (e.Operator.Kind)
{
case BoundBinaryOperator.OperatorKind.Addition:
sb.Append("+");
break;
case BoundBinaryOperator.OperatorKind.Subtraction:
sb.Append("-");
break;
case BoundBinaryOperator.OperatorKind.Multiplication:
sb.Append("*");
break;
case BoundBinaryOperator.OperatorKind.Division:
sb.Append("/");
break;
case BoundBinaryOperator.OperatorKind.Equality:
sb.Append("==");
break;
case BoundBinaryOperator.OperatorKind.Inequality:
sb.Append("!=");
break;
default:
throw new ArgumentOutOfRangeException();
}
sb.Append(compiledRight);
sb.Append(")");
return sb.ToString();
}
private string TranspileIfStatement(BoundIfStatement s, bool isElseIf = false)
{
var sb = new StringBuilder();
var openToken = isElseIf ? "else if(" : "if(";
sb.Append(openToken);
var compiledCondition = Transpile(s.Condition);
sb.Append(compiledCondition);
sb.Append("){\n");
var compiledBlock = Transpile(s.Block);
sb.Append(compiledBlock);
sb.Append("}");
return sb.ToString();
}
}
}