Binary expressions working with types
This commit is contained in:
@@ -85,6 +85,27 @@ public class Generator
|
|||||||
ret ; get out
|
ret ; get out
|
||||||
""");
|
""");
|
||||||
|
|
||||||
|
_builder.AppendLine("""
|
||||||
|
|
||||||
|
strcmp:
|
||||||
|
xor rdx, rdx
|
||||||
|
strcmp_loop:
|
||||||
|
mov al, [rsi + rdx]
|
||||||
|
mov bl, [rdi + rdx]
|
||||||
|
inc rdx
|
||||||
|
cmp al, bl
|
||||||
|
jne strcmp_not_equal
|
||||||
|
cmp al, 0
|
||||||
|
je strcmp_equal
|
||||||
|
jmp strcmp_loop
|
||||||
|
strcmp_not_equal:
|
||||||
|
mov rax, 0
|
||||||
|
ret
|
||||||
|
strcmp_equal:
|
||||||
|
mov rax, 1
|
||||||
|
ret
|
||||||
|
""");
|
||||||
|
|
||||||
|
|
||||||
_builder.AppendLine();
|
_builder.AppendLine();
|
||||||
_builder.AppendLine("section .data");
|
_builder.AppendLine("section .data");
|
||||||
@@ -101,12 +122,14 @@ public class Generator
|
|||||||
var func = _symbolTable.ResolveFunc(node.Name, node.Parameters.Select(p => p.Type).ToList());
|
var func = _symbolTable.ResolveFunc(node.Name, node.Parameters.Select(p => p.Type).ToList());
|
||||||
_builder.AppendLine($"; {node.ToString()}");
|
_builder.AppendLine($"; {node.ToString()}");
|
||||||
_builder.AppendLine($"{func.StartLabel}:");
|
_builder.AppendLine($"{func.StartLabel}:");
|
||||||
|
_builder.AppendLine(" ; Set up stack frame");
|
||||||
_builder.AppendLine(" push rbp");
|
_builder.AppendLine(" push rbp");
|
||||||
_builder.AppendLine(" mov rbp, rsp");
|
_builder.AppendLine(" mov rbp, rsp");
|
||||||
_builder.AppendLine($" sub rsp, {func.StackAllocation}");
|
_builder.AppendLine($" sub rsp, {func.StackAllocation}");
|
||||||
|
|
||||||
string[] registers = ["rdi", "rsi", "rdx", "rcx", "r8", "r9"];
|
string[] registers = ["rdi", "rsi", "rdx", "rcx", "r8", "r9"];
|
||||||
|
|
||||||
|
_builder.AppendLine(" ; Body");
|
||||||
for (var i = 0; i < func.Parameters.Count; i++)
|
for (var i = 0; i < func.Parameters.Count; i++)
|
||||||
{
|
{
|
||||||
var parameter = func.ResolveLocalVariable(func.Parameters.ElementAt(i).Name);
|
var parameter = func.ResolveLocalVariable(func.Parameters.ElementAt(i).Name);
|
||||||
@@ -125,6 +148,7 @@ public class Generator
|
|||||||
GenerateBlock(node.Body, func);
|
GenerateBlock(node.Body, func);
|
||||||
|
|
||||||
_builder.AppendLine($"{func.EndLabel}:");
|
_builder.AppendLine($"{func.EndLabel}:");
|
||||||
|
_builder.AppendLine("; Clean up stack frame");
|
||||||
_builder.AppendLine(" mov rsp, rbp");
|
_builder.AppendLine(" mov rsp, rbp");
|
||||||
_builder.AppendLine(" pop rbp");
|
_builder.AppendLine(" pop rbp");
|
||||||
_builder.AppendLine(" ret");
|
_builder.AppendLine(" ret");
|
||||||
@@ -217,81 +241,159 @@ public class Generator
|
|||||||
{
|
{
|
||||||
GenerateExpression(binaryExpression.Left, func);
|
GenerateExpression(binaryExpression.Left, func);
|
||||||
_builder.AppendLine(" push rax");
|
_builder.AppendLine(" push rax");
|
||||||
|
|
||||||
GenerateExpression(binaryExpression.Right, func);
|
GenerateExpression(binaryExpression.Right, func);
|
||||||
_builder.AppendLine(" pop rbx");
|
_builder.AppendLine(" mov rbx, rax");
|
||||||
|
_builder.AppendLine(" pop rax");
|
||||||
|
|
||||||
switch (binaryExpression.Operator)
|
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:
|
case BinaryExpressionOperator.Equal:
|
||||||
{
|
GenerateComparison(binaryExpression.Left.Type);
|
||||||
_builder.AppendLine(" cmp rax, rbx");
|
|
||||||
_builder.AppendLine(" sete al");
|
_builder.AppendLine(" sete al");
|
||||||
_builder.AppendLine(" movzx rax, al");
|
_builder.AppendLine(" movzx rax, al");
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case BinaryExpressionOperator.NotEqual:
|
case BinaryExpressionOperator.NotEqual:
|
||||||
{
|
GenerateComparison(binaryExpression.Left.Type);
|
||||||
_builder.AppendLine(" cmp rax, rbx");
|
|
||||||
_builder.AppendLine(" setne al");
|
_builder.AppendLine(" setne al");
|
||||||
_builder.AppendLine(" movzx rax, al");
|
_builder.AppendLine(" movzx rax, al");
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case BinaryExpressionOperator.GreaterThan:
|
case BinaryExpressionOperator.GreaterThan:
|
||||||
{
|
GenerateComparison(binaryExpression.Left.Type);
|
||||||
_builder.AppendLine(" cmp rax, rbx");
|
|
||||||
_builder.AppendLine(" setg al");
|
_builder.AppendLine(" setg al");
|
||||||
_builder.AppendLine(" movzx rax, al");
|
_builder.AppendLine(" movzx rax, al");
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case BinaryExpressionOperator.GreaterThanOrEqual:
|
case BinaryExpressionOperator.GreaterThanOrEqual:
|
||||||
{
|
GenerateComparison(binaryExpression.Left.Type);
|
||||||
_builder.AppendLine(" cmp rax, rbx");
|
|
||||||
_builder.AppendLine(" setge al");
|
_builder.AppendLine(" setge al");
|
||||||
_builder.AppendLine(" movzx rax, al");
|
_builder.AppendLine(" movzx rax, al");
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case BinaryExpressionOperator.LessThan:
|
case BinaryExpressionOperator.LessThan:
|
||||||
{
|
GenerateComparison(binaryExpression.Left.Type);
|
||||||
_builder.AppendLine(" cmp rax, rbx");
|
|
||||||
_builder.AppendLine(" setl al");
|
_builder.AppendLine(" setl al");
|
||||||
_builder.AppendLine(" movzx rax, al");
|
_builder.AppendLine(" movzx rax, al");
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case BinaryExpressionOperator.LessThanOrEqual:
|
case BinaryExpressionOperator.LessThanOrEqual:
|
||||||
{
|
GenerateComparison(binaryExpression.Left.Type);
|
||||||
_builder.AppendLine(" cmp rax, rbx");
|
|
||||||
_builder.AppendLine(" setle al");
|
_builder.AppendLine(" setle al");
|
||||||
_builder.AppendLine(" movzx rax, al");
|
_builder.AppendLine(" movzx rax, al");
|
||||||
break;
|
break;
|
||||||
}
|
case BinaryExpressionOperator.Plus:
|
||||||
|
GenerateBinaryAddition(binaryExpression.Left.Type);
|
||||||
|
break;
|
||||||
|
case BinaryExpressionOperator.Minus:
|
||||||
|
GenerateBinarySubtraction(binaryExpression.Left.Type);
|
||||||
|
break;
|
||||||
|
case BinaryExpressionOperator.Multiply:
|
||||||
|
GenerateBinaryMultiplication(binaryExpression.Left.Type);
|
||||||
|
break;
|
||||||
|
case BinaryExpressionOperator.Divide:
|
||||||
|
GenerateBinaryDivision(binaryExpression.Left.Type);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
{
|
throw new ArgumentOutOfRangeException();
|
||||||
throw new ArgumentOutOfRangeException(nameof(binaryExpression.Operator), binaryExpression.Operator, null);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void GenerateComparison(Type type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case DelegateType:
|
||||||
|
throw new NotSupportedException($"Comparison on type {type.GetType().Name} is not supported");
|
||||||
|
break;
|
||||||
|
case PrimitiveType:
|
||||||
|
_builder.AppendLine(" cmp rax, rax");
|
||||||
|
break;
|
||||||
|
case StringType:
|
||||||
|
_builder.AppendLine(" mov rdi, rax");
|
||||||
|
_builder.AppendLine(" mov rsi, rbx");
|
||||||
|
_builder.AppendLine(" call strcmp");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(type));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GenerateBinaryAddition(Type type)
|
||||||
|
{
|
||||||
|
if (type is not PrimitiveType primitiveType)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Addition can only be done on primitive types");
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (primitiveType.Kind)
|
||||||
|
{
|
||||||
|
case PrimitiveTypeKind.Int64:
|
||||||
|
_builder.AppendLine(" add rax, rbx");
|
||||||
|
break;
|
||||||
|
case PrimitiveTypeKind.Int32:
|
||||||
|
_builder.AppendLine(" add eax, ebx");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new InvalidOperationException($"Invalid type {primitiveType.Kind}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GenerateBinarySubtraction(Type type)
|
||||||
|
{
|
||||||
|
if (type is not PrimitiveType primitiveType)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Subtraction can only be done on primitive types");
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (primitiveType.Kind)
|
||||||
|
{
|
||||||
|
case PrimitiveTypeKind.Int64:
|
||||||
|
_builder.AppendLine(" sub rax, rbx");
|
||||||
|
break;
|
||||||
|
case PrimitiveTypeKind.Int32:
|
||||||
|
_builder.AppendLine(" sub eax, ebx");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new InvalidOperationException($"Invalid type {primitiveType.Kind}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GenerateBinaryMultiplication(Type type)
|
||||||
|
{
|
||||||
|
if (type is not PrimitiveType primitiveType)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Multiplication can only be done on primitive types");
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (primitiveType.Kind)
|
||||||
|
{
|
||||||
|
case PrimitiveTypeKind.Int64:
|
||||||
|
_builder.AppendLine(" imul rbx");
|
||||||
|
break;
|
||||||
|
case PrimitiveTypeKind.Int32:
|
||||||
|
_builder.AppendLine(" imul ebx");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new InvalidOperationException($"Invalid type {primitiveType.Kind}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GenerateBinaryDivision(Type type)
|
||||||
|
{
|
||||||
|
if (type is not PrimitiveType primitiveType)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Division can only be done on primitive types");
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (primitiveType.Kind)
|
||||||
|
{
|
||||||
|
case PrimitiveTypeKind.Int64:
|
||||||
|
_builder.AppendLine(" cqo");
|
||||||
|
_builder.AppendLine(" idiv rbx");
|
||||||
|
break;
|
||||||
|
case PrimitiveTypeKind.Int32:
|
||||||
|
_builder.AppendLine(" cdq");
|
||||||
|
_builder.AppendLine(" idiv ebx");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new InvalidOperationException($"Invalid type {primitiveType.Kind}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GenerateIdentifier(IdentifierNode identifier, Func func)
|
private void GenerateIdentifier(IdentifierNode identifier, Func func)
|
||||||
@@ -320,51 +422,38 @@ public class Generator
|
|||||||
switch (literal.Type)
|
switch (literal.Type)
|
||||||
{
|
{
|
||||||
case DelegateType:
|
case DelegateType:
|
||||||
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case StringType:
|
case StringType:
|
||||||
|
{
|
||||||
var ident = $"string{++_stringIndex}";
|
var ident = $"string{++_stringIndex}";
|
||||||
_strings.Add(ident, literal.Literal);
|
_strings.Add(ident, literal.Literal);
|
||||||
_builder.AppendLine($" mov rax, {ident}");
|
_builder.AppendLine($" mov rax, {ident}");
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case PrimitiveType primitive:
|
case PrimitiveType primitive:
|
||||||
|
{
|
||||||
switch (primitive.Kind)
|
switch (primitive.Kind)
|
||||||
{
|
{
|
||||||
case PrimitiveTypeKind.Bool:
|
case PrimitiveTypeKind.Bool:
|
||||||
{
|
_builder.AppendLine($" mov rax, {(bool.Parse(literal.Literal) ? "1" : "0")}");
|
||||||
var value = literal.Literal == "true" ? 1 : 0;
|
|
||||||
_builder.AppendLine($" mov al, {value}");
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case PrimitiveTypeKind.Char:
|
case PrimitiveTypeKind.Char:
|
||||||
throw new NotImplementedException();
|
_builder.AppendLine($" mov rax, '{literal.Literal}'");
|
||||||
break;
|
|
||||||
case PrimitiveTypeKind.Int8:
|
|
||||||
case PrimitiveTypeKind.UInt8:
|
|
||||||
_builder.AppendLine($" mov al, {literal.Literal}");
|
|
||||||
break;
|
|
||||||
case PrimitiveTypeKind.Int16:
|
|
||||||
case PrimitiveTypeKind.UInt16:
|
|
||||||
_builder.AppendLine($" mov ax, {literal.Literal}");
|
|
||||||
break;
|
|
||||||
case PrimitiveTypeKind.Int32:
|
|
||||||
case PrimitiveTypeKind.UInt32:
|
|
||||||
_builder.AppendLine($" mov eax, {literal.Literal}");
|
|
||||||
break;
|
break;
|
||||||
case PrimitiveTypeKind.Int64:
|
case PrimitiveTypeKind.Int64:
|
||||||
case PrimitiveTypeKind.UInt64:
|
|
||||||
_builder.AppendLine($" mov rax, {literal.Literal}");
|
_builder.AppendLine($" mov rax, {literal.Literal}");
|
||||||
break;
|
break;
|
||||||
case PrimitiveTypeKind.Float:
|
case PrimitiveTypeKind.Int32:
|
||||||
throw new NotImplementedException();
|
_builder.AppendLine($" mov rax, {literal.Literal}");
|
||||||
break;
|
|
||||||
case PrimitiveTypeKind.Double:
|
|
||||||
throw new NotImplementedException();
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new ArgumentOutOfRangeException();
|
throw new Exception("Cannot convert literal to string");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
throw new ArgumentOutOfRangeException();
|
throw new ArgumentOutOfRangeException();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,4 @@
|
|||||||
let SYS_WRITE = 1;
|
|
||||||
let STD_IN = 0;
|
|
||||||
let STD_OUT = 1;
|
|
||||||
let STD_ERR = 2;
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
let x = 5 * 5 + 5;
|
let x = "test" == "test";
|
||||||
}
|
syscall(60, x);
|
||||||
|
|
||||||
func write(msg: String) {
|
|
||||||
syscall(SYS_WRITE, STD_OUT, msg, strlen(msg));
|
|
||||||
}
|
}
|
||||||
@@ -97,6 +97,7 @@ public class Lexer
|
|||||||
return new LiteralToken(new PrimitiveType(PrimitiveTypeKind.Int64), buffer);
|
return new LiteralToken(new PrimitiveType(PrimitiveTypeKind.Int64), buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Revisit this
|
||||||
foreach (var chain in Chians)
|
foreach (var chain in Chians)
|
||||||
{
|
{
|
||||||
if (current.Value != chain.Key[0]) continue;
|
if (current.Value != chain.Key[0]) continue;
|
||||||
@@ -108,6 +109,11 @@ public class Lexer
|
|||||||
|
|
||||||
if (i == chain.Key.Length - 1)
|
if (i == chain.Key.Length - 1)
|
||||||
{
|
{
|
||||||
|
for (var j = 0; j <= i; j++)
|
||||||
|
{
|
||||||
|
Next();
|
||||||
|
}
|
||||||
|
|
||||||
return new SymbolToken(chain.Value);
|
return new SymbolToken(chain.Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
9
Nub.Lang/Nub.Lang/Output/debug.sh
Executable file
9
Nub.Lang/Nub.Lang/Output/debug.sh
Executable file
@@ -0,0 +1,9 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
nasm -g -felf64 out.asm -o out.o
|
||||||
|
ld out.o -o out
|
||||||
|
|
||||||
|
gdb -tui out
|
||||||
|
|
||||||
|
rm out.o
|
||||||
|
rm out
|
||||||
5
Nub.Lang/Nub.Lang/Output/run.sh
Normal file → Executable file
5
Nub.Lang/Nub.Lang/Output/run.sh
Normal file → Executable file
@@ -2,8 +2,9 @@
|
|||||||
|
|
||||||
nasm -g -felf64 out.asm -o out.o
|
nasm -g -felf64 out.asm -o out.o
|
||||||
ld out.o -o out
|
ld out.o -o out
|
||||||
|
|
||||||
./out
|
./out
|
||||||
|
echo "Process exited with status code $?"
|
||||||
|
|
||||||
rm out.o
|
rm out.o
|
||||||
|
rm out
|
||||||
echo "Process exited with status code $?"
|
|
||||||
@@ -17,16 +17,7 @@ public record PrimitiveType : Type
|
|||||||
{
|
{
|
||||||
"bool" => PrimitiveTypeKind.Bool,
|
"bool" => PrimitiveTypeKind.Bool,
|
||||||
"char" => PrimitiveTypeKind.Char,
|
"char" => PrimitiveTypeKind.Char,
|
||||||
"int8" => PrimitiveTypeKind.Int8,
|
|
||||||
"uint8" => PrimitiveTypeKind.UInt8,
|
|
||||||
"int16" => PrimitiveTypeKind.Int16,
|
|
||||||
"uint16" => PrimitiveTypeKind.UInt16,
|
|
||||||
"int32" => PrimitiveTypeKind.Int32,
|
|
||||||
"uint32" => PrimitiveTypeKind.UInt32,
|
|
||||||
"int64" => PrimitiveTypeKind.Int64,
|
"int64" => PrimitiveTypeKind.Int64,
|
||||||
"uint64" => PrimitiveTypeKind.UInt64,
|
|
||||||
"float" => PrimitiveTypeKind.Float,
|
|
||||||
"double" => PrimitiveTypeKind.Double,
|
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(value), value, null)
|
_ => throw new ArgumentOutOfRangeException(nameof(value), value, null)
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -42,16 +33,8 @@ public enum PrimitiveTypeKind
|
|||||||
{
|
{
|
||||||
Bool,
|
Bool,
|
||||||
Char,
|
Char,
|
||||||
Int8,
|
|
||||||
UInt8,
|
|
||||||
Int16,
|
|
||||||
UInt16,
|
|
||||||
Int32,
|
|
||||||
UInt32,
|
|
||||||
Int64,
|
Int64,
|
||||||
UInt64,
|
Int32,
|
||||||
Float,
|
|
||||||
Double,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public record StringType : Type
|
public record StringType : Type
|
||||||
|
|||||||
@@ -159,8 +159,7 @@ public class ExpressionTyper
|
|||||||
case BinaryExpressionOperator.Multiply:
|
case BinaryExpressionOperator.Multiply:
|
||||||
case BinaryExpressionOperator.Divide:
|
case BinaryExpressionOperator.Divide:
|
||||||
{
|
{
|
||||||
// TODO: Add change if int8, int16, int32, float or double
|
binaryExpression.Type = binaryExpression.Left.Type;
|
||||||
binaryExpression.Type = new PrimitiveType(PrimitiveTypeKind.Int64);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|||||||
Reference in New Issue
Block a user