...
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
using System.Text;
|
||||
using NubLang.Ast;
|
||||
using NubLang.Syntax;
|
||||
|
||||
@@ -6,17 +5,14 @@ namespace NubLang.Generation;
|
||||
|
||||
public class Generator
|
||||
{
|
||||
private readonly List<DefinitionNode> _definitions;
|
||||
private readonly CompilationUnit _compilationUnit;
|
||||
private readonly IndentedTextWriter _writer;
|
||||
private readonly Stack<List<DeferNode>> _deferStack = [];
|
||||
private readonly Stack<(string Name, NubFuncType FuncType)> _funcDefs = [];
|
||||
private readonly List<NubStructType> _structTypes = [];
|
||||
private int _tmpIndex;
|
||||
private int _funcDefIndex;
|
||||
|
||||
public Generator(List<DefinitionNode> definitions)
|
||||
public Generator(CompilationUnit compilationUnit)
|
||||
{
|
||||
_definitions = definitions;
|
||||
_compilationUnit = compilationUnit;
|
||||
_writer = new IndentedTextWriter();
|
||||
}
|
||||
|
||||
@@ -26,54 +22,6 @@ public class Generator
|
||||
return $"_t{++_tmpIndex}";
|
||||
}
|
||||
|
||||
private string MapType(NubType nubType)
|
||||
{
|
||||
return nubType switch
|
||||
{
|
||||
NubArrayType arrayType => MapType(arrayType.ElementType),
|
||||
NubConstArrayType arrayType => MapType(arrayType.ElementType),
|
||||
NubBoolType => "bool",
|
||||
NubCStringType => "char",
|
||||
NubFloatType floatType => floatType.Width switch
|
||||
{
|
||||
32 => "f32",
|
||||
64 => "f64",
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
},
|
||||
NubFuncType funcType => MapFuncType(funcType),
|
||||
NubIntType intType => (intType.Signed, intType.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",
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
},
|
||||
NubPointerType pointerType => MapType(pointerType.BaseType),
|
||||
NubStringType => throw new NotImplementedException(),
|
||||
NubStructType structType => MapStructType(structType),
|
||||
NubVoidType => "void",
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(nubType))
|
||||
};
|
||||
}
|
||||
|
||||
private string MapStructType(NubStructType structType)
|
||||
{
|
||||
_structTypes.Add(structType);
|
||||
return StructName(structType.Module, structType.Name);
|
||||
}
|
||||
|
||||
private string MapFuncType(NubFuncType funcType)
|
||||
{
|
||||
var name = $"_func_type_def{++_funcDefIndex}";
|
||||
_funcDefs.Push((name, funcType));
|
||||
return name;
|
||||
}
|
||||
|
||||
private string MapNameWithType(NubType nubType, string name)
|
||||
{
|
||||
var prefix = "";
|
||||
@@ -81,7 +29,7 @@ public class Generator
|
||||
|
||||
switch (nubType)
|
||||
{
|
||||
case NubCStringType or NubPointerType:
|
||||
case NubCStringType or NubPointerType or NubFuncType:
|
||||
prefix = "*";
|
||||
break;
|
||||
case NubArrayType:
|
||||
@@ -92,7 +40,42 @@ public class Generator
|
||||
break;
|
||||
}
|
||||
|
||||
return $"{MapType(nubType)} {prefix}{name}{postfix}";
|
||||
return $"{MapBaseType(nubType)} {prefix}{name}{postfix}";
|
||||
|
||||
string MapBaseType(NubType type)
|
||||
{
|
||||
return type switch
|
||||
{
|
||||
NubArrayType arrayType => MapBaseType(arrayType.ElementType),
|
||||
NubConstArrayType arrayType => MapBaseType(arrayType.ElementType),
|
||||
NubBoolType => "bool",
|
||||
NubCStringType => "char",
|
||||
NubFloatType floatType => floatType.Width switch
|
||||
{
|
||||
32 => "f32",
|
||||
64 => "f64",
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
},
|
||||
NubFuncType funcType => "void",
|
||||
NubIntType intType => (intType.Signed, intType.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",
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
},
|
||||
NubPointerType pointerType => MapBaseType(pointerType.BaseType),
|
||||
NubStringType => throw new NotImplementedException(),
|
||||
NubStructType structType => StructName(structType.Module, structType.Name),
|
||||
NubVoidType => "void",
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(type))
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private static string FuncName(string module, string name, string? externSymbol)
|
||||
@@ -105,139 +88,101 @@ public class Generator
|
||||
return $"{module}_{name}";
|
||||
}
|
||||
|
||||
private static string StructFuncName(string module, string name, string function)
|
||||
{
|
||||
return $"{module}_{name}_{function}";
|
||||
}
|
||||
|
||||
public string Emit()
|
||||
{
|
||||
const string header = """
|
||||
typedef __builtin_va_list va_list;
|
||||
|
||||
#define va_start(ap, last) __builtin_va_start(ap, last)
|
||||
#define va_arg(ap, type) __builtin_va_arg(ap, type)
|
||||
#define va_end(ap) __builtin_va_end(ap)
|
||||
#define va_copy(dest, src) __builtin_va_copy(dest, src)
|
||||
|
||||
#define NULL ((void*)0)
|
||||
|
||||
typedef unsigned long size_t;
|
||||
typedef unsigned long uintptr_t;
|
||||
|
||||
#define offsetof(type, member) __builtin_offsetof(type, member)
|
||||
|
||||
typedef unsigned char u8;
|
||||
typedef signed char i8;
|
||||
typedef unsigned short u16;
|
||||
typedef signed short i16;
|
||||
typedef unsigned int u32;
|
||||
typedef signed int i32;
|
||||
typedef unsigned long long u64;
|
||||
typedef signed long long i64;
|
||||
|
||||
typedef float f32;
|
||||
typedef double f64;
|
||||
|
||||
#define I8_C(x) x
|
||||
#define U8_C(x) x##U
|
||||
|
||||
#define I16_C(x) x
|
||||
#define U16_C(x) x##U
|
||||
|
||||
#define I32_C(x) x
|
||||
#define U32_C(x) x##U
|
||||
|
||||
#define I64_C(x) x##LL
|
||||
#define U64_C(x) x##ULL
|
||||
""";
|
||||
|
||||
_writer.WriteLine();
|
||||
|
||||
var appendNewLine = false;
|
||||
|
||||
foreach (var funcNode in _definitions.OfType<FuncNode>())
|
||||
// note(nub31): Struct definitions
|
||||
foreach (var structType in _compilationUnit.ImportedStructTypes)
|
||||
{
|
||||
EmitLine(funcNode.Tokens.FirstOrDefault());
|
||||
appendNewLine = true;
|
||||
var parameters = funcNode.Signature.Parameters.Count != 0
|
||||
? string.Join(", ", funcNode.Signature.Parameters.Select(x => MapNameWithType(x.Type, x.Name)))
|
||||
: "void";
|
||||
_writer.WriteLine("typedef struct");
|
||||
_writer.WriteLine("{");
|
||||
using (_writer.Indent())
|
||||
{
|
||||
foreach (var field in structType.Fields)
|
||||
{
|
||||
_writer.WriteLine($"{MapNameWithType(field.Type, field.Name)};");
|
||||
}
|
||||
}
|
||||
|
||||
var name = FuncName(funcNode.Module, funcNode.Name, funcNode.ExternSymbol);
|
||||
_writer.WriteLine($"{MapNameWithType(funcNode.Signature.ReturnType, name)}({parameters});");
|
||||
}
|
||||
|
||||
if (appendNewLine)
|
||||
{
|
||||
_writer.WriteLine($"}} {StructName(structType.Module, structType.Name)};");
|
||||
_writer.WriteLine();
|
||||
}
|
||||
|
||||
foreach (var structNode in _definitions.OfType<StructNode>())
|
||||
// note(nub31): Forward declarations
|
||||
foreach (var prototype in _compilationUnit.ImportedFunctions)
|
||||
{
|
||||
foreach (var structFuncNode in structNode.Functions)
|
||||
{
|
||||
EmitLine(structFuncNode.Tokens.FirstOrDefault());
|
||||
var parameters = structFuncNode.Signature.Parameters.Count != 0
|
||||
? string.Join(", ", structFuncNode.Signature.Parameters.Select(x => MapNameWithType(x.Type, x.Name)))
|
||||
: "void";
|
||||
EmitLine(prototype.Tokens.FirstOrDefault());
|
||||
var parameters = prototype.Parameters.Count != 0
|
||||
? string.Join(", ", prototype.Parameters.Select(x => MapNameWithType(x.Type, x.Name)))
|
||||
: "void";
|
||||
|
||||
var name = StructFuncName(structNode.Module, structNode.Name, structFuncNode.Name);
|
||||
_writer.WriteLine($"{MapNameWithType(structFuncNode.Signature.ReturnType, name)}({parameters})");
|
||||
EmitBlock(structFuncNode.Body);
|
||||
_writer.WriteLine();
|
||||
}
|
||||
var name = FuncName(prototype.Module, prototype.Name, prototype.ExternSymbol);
|
||||
_writer.WriteLine($"{MapNameWithType(prototype.ReturnType, name)}({parameters});");
|
||||
}
|
||||
|
||||
foreach (var funcNode in _definitions.OfType<FuncNode>())
|
||||
_writer.WriteLine();
|
||||
|
||||
// note(nub31): Normal functions
|
||||
foreach (var funcNode in _compilationUnit.Functions)
|
||||
{
|
||||
if (funcNode.Body == null) continue;
|
||||
|
||||
EmitLine(funcNode.Tokens.FirstOrDefault());
|
||||
var parameters = funcNode.Signature.Parameters.Count != 0
|
||||
? string.Join(", ", funcNode.Signature.Parameters.Select(x => MapNameWithType(x.Type, x.Name)))
|
||||
var parameters = funcNode.Prototype.Parameters.Count != 0
|
||||
? string.Join(", ", funcNode.Prototype.Parameters.Select(x => MapNameWithType(x.Type, x.Name)))
|
||||
: "void";
|
||||
|
||||
if (funcNode.ExternSymbol == null)
|
||||
if (funcNode.Prototype.ExternSymbol == null)
|
||||
{
|
||||
_writer.Write("static ");
|
||||
}
|
||||
|
||||
var name = FuncName(funcNode.Module, funcNode.Name, funcNode.ExternSymbol);
|
||||
_writer.WriteLine($"{MapNameWithType(funcNode.Signature.ReturnType, name)}({parameters})");
|
||||
var name = FuncName(funcNode.Module, funcNode.Name, funcNode.Prototype.ExternSymbol);
|
||||
_writer.WriteLine($"{MapNameWithType(funcNode.Prototype.ReturnType, name)}({parameters})");
|
||||
EmitBlock(funcNode.Body);
|
||||
_writer.WriteLine();
|
||||
}
|
||||
|
||||
List<string> typedefs = [];
|
||||
return $"""
|
||||
typedef __builtin_va_list va_list;
|
||||
|
||||
while (_funcDefs.TryPop(out var funcTypeDef))
|
||||
{
|
||||
var returnType = MapType(funcTypeDef.FuncType.ReturnType);
|
||||
var paramList = string.Join(", ", funcTypeDef.FuncType.Parameters.Select((type, i) => MapNameWithType(type, $"arg{i}")));
|
||||
if (funcTypeDef.FuncType.Parameters.Count == 0)
|
||||
{
|
||||
paramList = "void";
|
||||
}
|
||||
#define va_start(ap, last) __builtin_va_start(ap, last)
|
||||
#define va_arg(ap, type) __builtin_va_arg(ap, type)
|
||||
#define va_end(ap) __builtin_va_end(ap)
|
||||
#define va_copy(dest, src) __builtin_va_copy(dest, src)
|
||||
|
||||
typedefs.Add($"typedef {returnType} (*{funcTypeDef.Name})({paramList});");
|
||||
}
|
||||
#define NULL ((void*)0)
|
||||
|
||||
var structDefSb = new StringBuilder();
|
||||
foreach (var structType in _structTypes)
|
||||
{
|
||||
structDefSb.AppendLine("typedef struct");
|
||||
structDefSb.AppendLine("{");
|
||||
foreach (var field in structType.Fields)
|
||||
{
|
||||
structDefSb.AppendLine($" {MapNameWithType(field.Type, field.Name)};");
|
||||
}
|
||||
typedef unsigned long size_t;
|
||||
typedef unsigned long uintptr_t;
|
||||
|
||||
structDefSb.AppendLine($"}} {StructName(structType.Module, structType.Name)};");
|
||||
structDefSb.AppendLine();
|
||||
}
|
||||
#define offsetof(type, member) __builtin_offsetof(type, member)
|
||||
|
||||
return header + structDefSb + "\n\n" + string.Join('\n', typedefs) + "\n\n" + _writer;
|
||||
typedef unsigned char u8;
|
||||
typedef signed char i8;
|
||||
typedef unsigned short u16;
|
||||
typedef signed short i16;
|
||||
typedef unsigned int u32;
|
||||
typedef signed int i32;
|
||||
typedef unsigned long long u64;
|
||||
typedef signed long long i64;
|
||||
|
||||
typedef float f32;
|
||||
typedef double f64;
|
||||
|
||||
#define I8_C(x) x
|
||||
#define U8_C(x) x##U
|
||||
|
||||
#define I16_C(x) x
|
||||
#define U16_C(x) x##U
|
||||
|
||||
#define I32_C(x) x
|
||||
#define U32_C(x) x##U
|
||||
|
||||
#define I64_C(x) x##LL
|
||||
#define U64_C(x) x##ULL
|
||||
|
||||
{_writer}
|
||||
""";
|
||||
}
|
||||
|
||||
private void EmitStatement(StatementNode statementNode)
|
||||
@@ -269,9 +214,6 @@ public class Generator
|
||||
case StatementFuncCallNode statementFuncCallNode:
|
||||
EmitStatementFuncCall(statementFuncCallNode);
|
||||
break;
|
||||
case StatementStructFuncCallNode statementStructFuncCallNode:
|
||||
EmitStatementStructFuncCall(statementStructFuncCallNode);
|
||||
break;
|
||||
case VariableDeclarationNode variableDeclarationNode:
|
||||
EmitVariableDeclaration(variableDeclarationNode);
|
||||
break;
|
||||
@@ -316,7 +258,7 @@ public class Generator
|
||||
private void EmitIf(IfNode ifNode, bool elseIf = false)
|
||||
{
|
||||
var condition = EmitExpression(ifNode.Condition);
|
||||
_writer.WriteLine($"{(elseIf ? "else" : "")} if ({condition})");
|
||||
_writer.WriteLine($"{(elseIf ? "else " : "")}if ({condition})");
|
||||
EmitBlock(ifNode.Body);
|
||||
ifNode.Else?.Match
|
||||
(
|
||||
@@ -373,12 +315,6 @@ public class Generator
|
||||
_writer.WriteLine($"{funcCall};");
|
||||
}
|
||||
|
||||
private void EmitStatementStructFuncCall(StatementStructFuncCallNode statementStructFuncCallNode)
|
||||
{
|
||||
var structFuncCall = EmitStructFuncCall(statementStructFuncCallNode.StructFuncCall);
|
||||
_writer.WriteLine($"{structFuncCall};");
|
||||
}
|
||||
|
||||
private void EmitVariableDeclaration(VariableDeclarationNode variableDeclarationNode)
|
||||
{
|
||||
if (variableDeclarationNode.Assignment != null)
|
||||
@@ -423,7 +359,6 @@ public class Generator
|
||||
SizeBuiltinNode sizeBuiltinNode => EmitSizeBuiltin(sizeBuiltinNode),
|
||||
StringLiteralNode stringLiteralNode => EmitStringLiteral(stringLiteralNode),
|
||||
StructFieldAccessNode structFieldAccessNode => EmitStructFieldAccess(structFieldAccessNode),
|
||||
StructFuncCallNode structFuncCallNode => EmitStructFuncCall(structFuncCallNode),
|
||||
StructInitializerNode structInitializerNode => EmitStructInitializer(structInitializerNode),
|
||||
UIntLiteralNode uIntLiteralNode => EmitUIntLiteral(uIntLiteralNode),
|
||||
UnaryExpressionNode unaryExpressionNode => EmitUnaryExpression(unaryExpressionNode),
|
||||
@@ -606,12 +541,7 @@ public class Generator
|
||||
|
||||
private string EmitSizeBuiltin(SizeBuiltinNode sizeBuiltinNode)
|
||||
{
|
||||
if (sizeBuiltinNode.TargetType is NubConstArrayType constArrayType)
|
||||
{
|
||||
return $"sizeof({MapType(constArrayType.ElementType)}) * {constArrayType.Size}";
|
||||
}
|
||||
|
||||
return $"sizeof({MapType(sizeBuiltinNode.TargetType)})";
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private string EmitStringLiteral(StringLiteralNode stringLiteralNode)
|
||||
@@ -625,14 +555,6 @@ public class Generator
|
||||
return $"{structExpr}.{structFieldAccessNode.Field}";
|
||||
}
|
||||
|
||||
private string EmitStructFuncCall(StructFuncCallNode structFuncCallNode)
|
||||
{
|
||||
var thisParameter = EmitExpression(structFuncCallNode.StructExpression);
|
||||
var name = StructFuncName(structFuncCallNode.Module, structFuncCallNode.StructName, structFuncCallNode.FuncName);
|
||||
var parameterNames = structFuncCallNode.Parameters.Select(EmitExpression).ToList();
|
||||
return $"{name}({thisParameter}, {string.Join(", ", parameterNames)})";
|
||||
}
|
||||
|
||||
private string EmitStructInitializer(StructInitializerNode structInitializerNode)
|
||||
{
|
||||
var initValues = new List<string>();
|
||||
|
||||
Reference in New Issue
Block a user