126 lines
4.4 KiB
C#
126 lines
4.4 KiB
C#
using System;
|
|
using System.Text;
|
|
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 ((bool)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();
|
|
}
|
|
}
|
|
|
|
} |