This commit is contained in:
nub31
2025-10-22 11:22:06 +02:00
parent 8709eeb09d
commit e2da6cccff
9 changed files with 91 additions and 233 deletions

View File

@@ -1,3 +1,4 @@
using System.Text;
using NubLang.Ast;
using NubLang.Syntax;
@@ -39,6 +40,21 @@ public class Generator
_writer.WriteLine("#include <stddef.h>");
_writer.WriteLine();
_writer.WriteLine("""
typedef struct
{
size_t length;
uint8_t *data;
} string;
typedef struct
{
size_t length;
void *data;
} slice;
""");
foreach (var structType in _compilationUnit.ImportedStructTypes)
{
_writer.WriteLine("typedef struct");
@@ -68,22 +84,6 @@ public class Generator
_writer.WriteLine();
}
// note(nub31): declare extern functions
foreach (var funcNode in _compilationUnit.Functions)
{
if (funcNode.Body != null) continue;
EmitLine(funcNode.Tokens.FirstOrDefault());
var parameters = funcNode.Prototype.Parameters.Count != 0
? string.Join(", ", funcNode.Prototype.Parameters.Select(x => CType.Create(x.Type, x.Name)))
: "void";
var name = FuncName(funcNode.Module, funcNode.Name, funcNode.Prototype.ExternSymbol);
_writer.WriteLine($"{CType.Create(funcNode.Prototype.ReturnType, name)}({parameters});");
}
_writer.WriteLine();
// note(nub31): Normal functions
foreach (var funcNode in _compilationUnit.Functions)
{
@@ -94,11 +94,6 @@ public class Generator
? string.Join(", ", funcNode.Prototype.Parameters.Select(x => CType.Create(x.Type, x.Name)))
: "void";
if (funcNode.Prototype.ExternSymbol == null)
{
_writer.Write("static ");
}
var name = FuncName(funcNode.Module, funcNode.Name, funcNode.Prototype.ExternSymbol);
_writer.WriteLine($"{CType.Create(funcNode.Prototype.ReturnType, name)}({parameters})");
EmitBlock(funcNode.Body);
@@ -165,11 +160,13 @@ public class Generator
private void EmitBreak(BreakNode _)
{
// todo(nub31): Emit deferred statements
_writer.WriteLine("break;");
}
private void EmitContinue(ContinueNode _)
{
// todo(nub31): Emit deferred statements
_writer.WriteLine("continue;");
}
@@ -265,38 +262,31 @@ public class Generator
ArrayIndexAccessNode arrayIndexAccessNode => EmitArrayIndexAccess(arrayIndexAccessNode),
ArrayInitializerNode arrayInitializerNode => EmitArrayInitializer(arrayInitializerNode),
BinaryExpressionNode binaryExpressionNode => EmitBinaryExpression(binaryExpressionNode),
BoolLiteralNode boolLiteralNode => EmitBoolLiteral(boolLiteralNode),
ConstArrayIndexAccessNode constArrayIndexAccessNode => EmitConstArrayIndexAccess(constArrayIndexAccessNode),
ConstArrayInitializerNode constArrayInitializerNode => EmitConstArrayInitializer(constArrayInitializerNode),
// ConvertConstArrayToArrayNode convertConstArrayToArrayNode => EmitConvertConstArrayToArray(convertConstArrayToArrayNode),
BoolLiteralNode boolLiteralNode => boolLiteralNode.Value ? "true" : "false",
ConvertCStringToStringNode convertCStringToStringNode => EmitConvertCStringToString(convertCStringToStringNode),
ConvertFloatNode convertFloatNode => EmitConvertFloat(convertFloatNode),
ConvertIntNode convertIntNode => EmitConvertInt(convertIntNode),
CStringLiteralNode cStringLiteralNode => EmitCStringLiteral(cStringLiteralNode),
ConvertStringToCStringNode convertStringToCStringNode => EmitConvertStringToCString(convertStringToCStringNode),
CStringLiteralNode cStringLiteralNode => $"\"{cStringLiteralNode.Value}\"",
DereferenceNode dereferenceNode => EmitDereference(dereferenceNode),
Float32LiteralNode float32LiteralNode => EmitFloat32Literal(float32LiteralNode),
Float64LiteralNode float64LiteralNode => EmitFloat64Literal(float64LiteralNode),
FloatToIntBuiltinNode floatToIntBuiltinNode => EmitFloatToIntBuiltin(floatToIntBuiltinNode),
FuncCallNode funcCallNode => EmitFuncCall(funcCallNode),
FuncIdentifierNode funcIdentifierNode => EmitFuncIdentifier(funcIdentifierNode),
FuncIdentifierNode funcIdentifierNode => FuncName(funcIdentifierNode.Module, funcIdentifierNode.Name, funcIdentifierNode.ExternSymbol),
IntLiteralNode intLiteralNode => EmitIntLiteral(intLiteralNode),
AddressOfNode addressOfNode => EmitAddressOf(addressOfNode),
LValueIdentifierNode lValueIdentifierNode => EmitLValueIdentifier(lValueIdentifierNode),
RValueIdentifierNode rValueIdentifierNode => EmitRValueIdentifier(rValueIdentifierNode),
SizeBuiltinNode sizeBuiltinNode => EmitSizeBuiltin(sizeBuiltinNode),
SizeBuiltinNode sizeBuiltinNode => $"sizeof({CType.Create(sizeBuiltinNode.TargetType)})",
SliceIndexAccessNode sliceIndexAccessNode => EmitSliceArrayIndexAccess(sliceIndexAccessNode),
StringLiteralNode stringLiteralNode => EmitStringLiteral(stringLiteralNode),
StructFieldAccessNode structFieldAccessNode => EmitStructFieldAccess(structFieldAccessNode),
StructInitializerNode structInitializerNode => EmitStructInitializer(structInitializerNode),
UIntLiteralNode uIntLiteralNode => EmitUIntLiteral(uIntLiteralNode),
UnaryExpressionNode unaryExpressionNode => EmitUnaryExpression(unaryExpressionNode),
VariableIdentifierNode variableIdentifierNode => variableIdentifierNode.Name,
_ => throw new ArgumentOutOfRangeException(nameof(expressionNode))
};
if (expressionNode is ConstArrayInitializerNode)
{
return expr;
}
return $"({expr})";
}
@@ -309,10 +299,9 @@ public class Generator
private string EmitArrayInitializer(ArrayInitializerNode arrayInitializerNode)
{
var type = (NubArrayType)arrayInitializerNode.Type;
var capacity = EmitExpression(arrayInitializerNode.Capacity);
var tmp = NewTmp();
_writer.WriteLine($"{CType.Create(type.ElementType)} {tmp}[{capacity}];");
_writer.WriteLine($"{CType.Create(arrayInitializerNode.ElementType)} {tmp}[{capacity}];");
return tmp;
}
@@ -347,30 +336,12 @@ public class Generator
return $"{left} {op} {right}";
}
private string EmitBoolLiteral(BoolLiteralNode boolLiteralNode)
private string EmitConvertCStringToString(ConvertCStringToStringNode convertCStringToStringNode)
{
return boolLiteralNode.Value ? "true" : "false";
var value = EmitExpression(convertCStringToStringNode.Value);
return $"(string){{.length = strlen({value}), .data = {value}}}";
}
private string EmitConstArrayIndexAccess(ConstArrayIndexAccessNode constArrayIndexAccessNode)
{
var array = EmitExpression(constArrayIndexAccessNode.Target);
var index = EmitExpression(constArrayIndexAccessNode.Index);
// todo(nub31): We can emit bounds checking here
return $"{array}[{index}]";
}
private string EmitConstArrayInitializer(ConstArrayInitializerNode constArrayInitializerNode)
{
return "{0}";
}
// private string EmitConvertConstArrayToArray(ConvertConstArrayToArrayNode convertConstArrayToArrayNode)
// {
// var value = EmitExpression(convertConstArrayToArrayNode.Value);
// return $"({CType.Create(convertConstArrayToArrayNode.Type)}){value}";
// }
private string EmitConvertFloat(ConvertFloatNode convertFloatNode)
{
var value = EmitExpression(convertFloatNode.Value);
@@ -387,24 +358,21 @@ public class Generator
private string EmitConvertInt(ConvertIntNode convertIntNode)
{
var value = EmitExpression(convertIntNode.Value);
var targetType = (convertIntNode.TargetType.Signed, convertIntNode.TargetType.Width) switch
var targetType = convertIntNode.TargetType.Width switch
{
(false, 8) => "u8",
(false, 16) => "u16",
(false, 32) => "u32",
(false, 64) => "u64",
(true, 8) => "i8",
(true, 16) => "i16",
(true, 32) => "i32",
(true, 64) => "i64",
8 => convertIntNode.TargetType.Signed ? "int8_t" : "uint8_t",
16 => convertIntNode.TargetType.Signed ? "int16_t" : "uint16_t",
32 => convertIntNode.TargetType.Signed ? "int32_t" : "uint32_t",
64 => convertIntNode.TargetType.Signed ? "int64_t" : "uint64_t",
_ => throw new ArgumentOutOfRangeException()
};
return $"({targetType}){value}";
}
private string EmitCStringLiteral(CStringLiteralNode cStringLiteralNode)
private string EmitConvertStringToCString(ConvertStringToCStringNode convertStringToCStringNode)
{
return $"\"{cStringLiteralNode.Value}\"";
var value = EmitExpression(convertStringToCStringNode.Value);
return $"(char*){value}.data";
}
private string EmitDereference(DereferenceNode dereferenceNode)
@@ -438,16 +406,12 @@ public class Generator
private string EmitFloatToIntBuiltin(FloatToIntBuiltinNode floatToIntBuiltinNode)
{
var value = EmitExpression(floatToIntBuiltinNode.Value);
var targetType = (floatToIntBuiltinNode.TargetType.Signed, floatToIntBuiltinNode.TargetType.Width) switch
var targetType = floatToIntBuiltinNode.TargetType.Width switch
{
(false, 8) => "u8",
(false, 16) => "u16",
(false, 32) => "u32",
(false, 64) => "u64",
(true, 8) => "i8",
(true, 16) => "i16",
(true, 32) => "i32",
(true, 64) => "i64",
8 => floatToIntBuiltinNode.TargetType.Signed ? "int8_t" : "uint8_t",
16 => floatToIntBuiltinNode.TargetType.Signed ? "int16_t" : "uint16_t",
32 => floatToIntBuiltinNode.TargetType.Signed ? "int32_t" : "uint32_t",
64 => floatToIntBuiltinNode.TargetType.Signed ? "int64_t" : "uint64_t",
_ => throw new ArgumentOutOfRangeException()
};
return $"({targetType}){value}";
@@ -460,11 +424,6 @@ public class Generator
return $"{name}({string.Join(", ", parameterNames)})";
}
private string EmitFuncIdentifier(FuncIdentifierNode funcIdentifierNode)
{
return FuncName(funcIdentifierNode.Module, funcIdentifierNode.Name, funcIdentifierNode.ExternSymbol);
}
private string EmitIntLiteral(IntLiteralNode intLiteralNode)
{
var type = (NubIntType)intLiteralNode.Type;
@@ -482,32 +441,18 @@ public class Generator
return $"&{value}";
}
private string EmitLValueIdentifier(LValueIdentifierNode lValueIdentifierNode)
{
return lValueIdentifierNode.Name;
}
private string EmitRValueIdentifier(RValueIdentifierNode rValueIdentifierNode)
{
return rValueIdentifierNode.Name;
}
private string EmitSizeBuiltin(SizeBuiltinNode sizeBuiltinNode)
{
return $"sizeof({CType.Create(sizeBuiltinNode.TargetType)})";
}
private string EmitSliceArrayIndexAccess(SliceIndexAccessNode sliceIndexAccessNode)
{
var value = EmitExpression(sliceIndexAccessNode.Target);
var index = EmitExpression(sliceIndexAccessNode.Index);
// todo(nub31): We can emit bounds checking here
return $"{value}.data[{index}]";
return $"(({CType.Create(sliceIndexAccessNode.Target.Type)}){value}.data)[{index}]";
}
private string EmitStringLiteral(StringLiteralNode stringLiteralNode)
{
throw new NotImplementedException();
var length = Encoding.UTF8.GetByteCount(stringLiteralNode.Value);
return $"(string){{.length = {length}, .data = \"{stringLiteralNode.Value}\"}}";
}
private string EmitStructFieldAccess(StructFieldAccessNode structFieldAccessNode)