...
This commit is contained in:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user