Add basic binary expression support
Current implementation is placeholder. Assembly is generated by mr. chat and is currently unchecked. Also only 64 bit ints are supported
This commit is contained in:
@@ -190,6 +190,9 @@ public class Generator
|
||||
{
|
||||
switch (expression)
|
||||
{
|
||||
case BinaryExpressionNode binaryExpression:
|
||||
GenerateBinaryExpression(binaryExpression, func);
|
||||
break;
|
||||
case FuncCallExpressionNode funcCallExpression:
|
||||
GenerateFuncCall(funcCallExpression.FuncCall, func);
|
||||
break;
|
||||
@@ -210,6 +213,87 @@ public class Generator
|
||||
}
|
||||
}
|
||||
|
||||
private void GenerateBinaryExpression(BinaryExpressionNode binaryExpression, Func func)
|
||||
{
|
||||
GenerateExpression(binaryExpression.Left, func);
|
||||
_builder.AppendLine(" push rax");
|
||||
|
||||
GenerateExpression(binaryExpression.Right, func);
|
||||
_builder.AppendLine(" pop rbx");
|
||||
|
||||
switch (binaryExpression.Operator)
|
||||
{
|
||||
|
||||
case BinaryExpressionOperator.Plus:
|
||||
{
|
||||
_builder.AppendLine(" add rax, rbx");
|
||||
break;
|
||||
}
|
||||
case BinaryExpressionOperator.Minus:
|
||||
{
|
||||
_builder.AppendLine(" sub rax, rbx");
|
||||
break;
|
||||
}
|
||||
case BinaryExpressionOperator.Multiply:
|
||||
{
|
||||
_builder.AppendLine(" imul rax, rbx");
|
||||
break;
|
||||
}
|
||||
case BinaryExpressionOperator.Divide:
|
||||
{
|
||||
_builder.AppendLine(" xor rdx, rdx");
|
||||
_builder.AppendLine(" div rbx");
|
||||
break;
|
||||
}
|
||||
case BinaryExpressionOperator.Equal:
|
||||
{
|
||||
_builder.AppendLine(" cmp rax, rbx");
|
||||
_builder.AppendLine(" sete al");
|
||||
_builder.AppendLine(" movzx rax, al");
|
||||
break;
|
||||
}
|
||||
case BinaryExpressionOperator.NotEqual:
|
||||
{
|
||||
_builder.AppendLine(" cmp rax, rbx");
|
||||
_builder.AppendLine(" setne al");
|
||||
_builder.AppendLine(" movzx rax, al");
|
||||
break;
|
||||
}
|
||||
case BinaryExpressionOperator.GreaterThan:
|
||||
{
|
||||
_builder.AppendLine(" cmp rax, rbx");
|
||||
_builder.AppendLine(" setg al");
|
||||
_builder.AppendLine(" movzx rax, al");
|
||||
break;
|
||||
}
|
||||
case BinaryExpressionOperator.GreaterThanOrEqual:
|
||||
{
|
||||
_builder.AppendLine(" cmp rax, rbx");
|
||||
_builder.AppendLine(" setge al");
|
||||
_builder.AppendLine(" movzx rax, al");
|
||||
break;
|
||||
}
|
||||
case BinaryExpressionOperator.LessThan:
|
||||
{
|
||||
_builder.AppendLine(" cmp rax, rbx");
|
||||
_builder.AppendLine(" setl al");
|
||||
_builder.AppendLine(" movzx rax, al");
|
||||
break;
|
||||
}
|
||||
case BinaryExpressionOperator.LessThanOrEqual:
|
||||
{
|
||||
_builder.AppendLine(" cmp rax, rbx");
|
||||
_builder.AppendLine(" setle al");
|
||||
_builder.AppendLine(" movzx rax, al");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(binaryExpression.Operator), binaryExpression.Operator, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void GenerateIdentifier(IdentifierNode identifier, Func func)
|
||||
{
|
||||
var variable = func.ResolveVariable(identifier.Identifier);
|
||||
|
||||
@@ -4,10 +4,7 @@ let STD_OUT = 1;
|
||||
let STD_ERR = 2;
|
||||
|
||||
func main() {
|
||||
let x = "test\n";
|
||||
write(x);
|
||||
x = "uwu\n";
|
||||
write(x);
|
||||
let x = 5 * 5 + 5;
|
||||
}
|
||||
|
||||
func write(msg: String) {
|
||||
|
||||
@@ -22,8 +22,8 @@ public enum Symbol
|
||||
Comma,
|
||||
Period,
|
||||
Assign,
|
||||
Equal,
|
||||
Bang,
|
||||
Equal,
|
||||
NotEqual,
|
||||
LessThan,
|
||||
LessThanOrEqual,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Nub.Lang.Lexing;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Nub.Lang.Lexing;
|
||||
using Nub.Lib;
|
||||
|
||||
namespace Nub.Lang.Parsing;
|
||||
@@ -156,7 +157,84 @@ public class Parser
|
||||
}
|
||||
}
|
||||
|
||||
private ExpressionNode ParseExpression()
|
||||
private ExpressionNode ParseExpression(int precedence = 0)
|
||||
{
|
||||
var left = ParsePrimaryExpression();
|
||||
|
||||
while (true)
|
||||
{
|
||||
var token = Peek();
|
||||
if (!token.HasValue || token.Value is not SymbolToken symbolToken || !TryGetBinaryOperator(symbolToken.Symbol, out var op) || GetBinaryOperatorPrecedence(op.Value) < precedence)
|
||||
break;
|
||||
|
||||
Next();
|
||||
var right = ParseExpression(GetBinaryOperatorPrecedence(op.Value) + 1);
|
||||
|
||||
left = new BinaryExpressionNode(left, op.Value, right);
|
||||
}
|
||||
|
||||
return left;
|
||||
}
|
||||
|
||||
private static int GetBinaryOperatorPrecedence(BinaryExpressionOperator binaryExpressionOperator)
|
||||
{
|
||||
return binaryExpressionOperator switch
|
||||
{
|
||||
BinaryExpressionOperator.Multiply => 3,
|
||||
BinaryExpressionOperator.Divide => 3,
|
||||
BinaryExpressionOperator.Plus => 2,
|
||||
BinaryExpressionOperator.Minus => 2,
|
||||
BinaryExpressionOperator.GreaterThan => 1,
|
||||
BinaryExpressionOperator.GreaterThanOrEqual => 1,
|
||||
BinaryExpressionOperator.LessThan => 1,
|
||||
BinaryExpressionOperator.LessThanOrEqual => 1,
|
||||
BinaryExpressionOperator.Equal => 0,
|
||||
BinaryExpressionOperator.NotEqual => 0,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(binaryExpressionOperator), binaryExpressionOperator, null)
|
||||
};
|
||||
}
|
||||
|
||||
private static bool TryGetBinaryOperator(Symbol symbol, [NotNullWhen(true)] out BinaryExpressionOperator? binaryExpressionOperator)
|
||||
{
|
||||
switch (symbol)
|
||||
{
|
||||
case Symbol.Equal:
|
||||
binaryExpressionOperator = BinaryExpressionOperator.Equal;
|
||||
return true;
|
||||
case Symbol.NotEqual:
|
||||
binaryExpressionOperator = BinaryExpressionOperator.NotEqual;
|
||||
return true;
|
||||
case Symbol.LessThan:
|
||||
binaryExpressionOperator = BinaryExpressionOperator.LessThan;
|
||||
return true;
|
||||
case Symbol.LessThanOrEqual:
|
||||
binaryExpressionOperator = BinaryExpressionOperator.LessThanOrEqual;
|
||||
return true;
|
||||
case Symbol.GreaterThan:
|
||||
binaryExpressionOperator = BinaryExpressionOperator.GreaterThan;
|
||||
return true;
|
||||
case Symbol.GreaterThanOrEqual:
|
||||
binaryExpressionOperator = BinaryExpressionOperator.GreaterThanOrEqual;
|
||||
return true;
|
||||
case Symbol.Plus:
|
||||
binaryExpressionOperator = BinaryExpressionOperator.Plus;
|
||||
return true;
|
||||
case Symbol.Minus:
|
||||
binaryExpressionOperator = BinaryExpressionOperator.Minus;
|
||||
return true;
|
||||
case Symbol.Star:
|
||||
binaryExpressionOperator = BinaryExpressionOperator.Multiply;
|
||||
return true;
|
||||
case Symbol.ForwardSlash:
|
||||
binaryExpressionOperator = BinaryExpressionOperator.Divide;
|
||||
return true;
|
||||
default:
|
||||
binaryExpressionOperator = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private ExpressionNode ParsePrimaryExpression()
|
||||
{
|
||||
var token = ExpectToken();
|
||||
return token switch
|
||||
|
||||
@@ -115,6 +115,9 @@ public class ExpressionTyper
|
||||
{
|
||||
switch (expression)
|
||||
{
|
||||
case BinaryExpressionNode binaryExpression:
|
||||
PopulateBinaryExpression(binaryExpression);
|
||||
break;
|
||||
case FuncCallExpressionNode funcCall:
|
||||
PopulateFuncCallExpression(funcCall);
|
||||
break;
|
||||
@@ -135,6 +138,38 @@ public class ExpressionTyper
|
||||
}
|
||||
}
|
||||
|
||||
private void PopulateBinaryExpression(BinaryExpressionNode binaryExpression)
|
||||
{
|
||||
PopulateExpression(binaryExpression.Left);
|
||||
PopulateExpression(binaryExpression.Right);
|
||||
switch (binaryExpression.Operator)
|
||||
{
|
||||
case BinaryExpressionOperator.Equal:
|
||||
case BinaryExpressionOperator.NotEqual:
|
||||
case BinaryExpressionOperator.GreaterThan:
|
||||
case BinaryExpressionOperator.GreaterThanOrEqual:
|
||||
case BinaryExpressionOperator.LessThan:
|
||||
case BinaryExpressionOperator.LessThanOrEqual:
|
||||
{
|
||||
binaryExpression.Type = new PrimitiveType(PrimitiveTypeKind.Bool);
|
||||
break;
|
||||
}
|
||||
case BinaryExpressionOperator.Plus:
|
||||
case BinaryExpressionOperator.Minus:
|
||||
case BinaryExpressionOperator.Multiply:
|
||||
case BinaryExpressionOperator.Divide:
|
||||
{
|
||||
// TODO: Add change if int8, int16, int32, float or double
|
||||
binaryExpression.Type = new PrimitiveType(PrimitiveTypeKind.Int64);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(binaryExpression.Operator));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void PopulateFuncCallExpression(FuncCallExpressionNode funcCall)
|
||||
{
|
||||
foreach (var parameter in funcCall.FuncCall.Parameters)
|
||||
|
||||
Reference in New Issue
Block a user