Better type mapping
This commit is contained in:
@@ -5,78 +5,10 @@ using NubLang.Generation;
|
|||||||
using NubLang.Modules;
|
using NubLang.Modules;
|
||||||
using NubLang.Syntax;
|
using NubLang.Syntax;
|
||||||
|
|
||||||
List<string> files = [];
|
|
||||||
List<string> headerFiles = [];
|
|
||||||
|
|
||||||
for (var i = 0; i < args.Length; i++)
|
|
||||||
{
|
|
||||||
if (args[i] == "-h")
|
|
||||||
{
|
|
||||||
i += 1;
|
|
||||||
if (i > args.Length - 1)
|
|
||||||
{
|
|
||||||
Console.Error.WriteLine("Expected argument after -h");
|
|
||||||
}
|
|
||||||
|
|
||||||
headerFiles.Add(args[i]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
files.Add(args[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var diagnostics = new List<Diagnostic>();
|
var diagnostics = new List<Diagnostic>();
|
||||||
var syntaxTrees = new List<SyntaxTree>();
|
var syntaxTrees = new List<SyntaxTree>();
|
||||||
|
|
||||||
foreach (var headerFile in headerFiles)
|
foreach (var file in args)
|
||||||
{
|
|
||||||
using var bindingsGenerateProc = new Process();
|
|
||||||
// todo(nub31): Embed python file to remove absolute path
|
|
||||||
bindingsGenerateProc.StartInfo = new ProcessStartInfo("python3", ["/home/oliste/repos/nub-lang/bindings/generate.py", headerFile])
|
|
||||||
{
|
|
||||||
RedirectStandardOutput = true,
|
|
||||||
RedirectStandardError = true,
|
|
||||||
CreateNoWindow = true,
|
|
||||||
UseShellExecute = false,
|
|
||||||
};
|
|
||||||
|
|
||||||
bindingsGenerateProc.Start();
|
|
||||||
|
|
||||||
var output = await bindingsGenerateProc.StandardOutput.ReadToEndAsync();
|
|
||||||
var error = await bindingsGenerateProc.StandardError.ReadToEndAsync();
|
|
||||||
|
|
||||||
await bindingsGenerateProc.WaitForExitAsync();
|
|
||||||
|
|
||||||
if (bindingsGenerateProc.ExitCode != 0)
|
|
||||||
{
|
|
||||||
Console.Error.WriteLine($"Failed to automatically generate bindings for header file {headerFile}\n{error}");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
var tokenizer = new Tokenizer(headerFile, output);
|
|
||||||
tokenizer.Tokenize();
|
|
||||||
diagnostics.AddRange(tokenizer.Diagnostics);
|
|
||||||
|
|
||||||
if (tokenizer.Diagnostics.Any(x => x.Severity == DiagnosticSeverity.Error))
|
|
||||||
{
|
|
||||||
Console.Error.WriteLine($"Binding generator produced invalid syntax for header file {headerFile}");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
var parser = new Parser();
|
|
||||||
var syntaxTree = parser.Parse(tokenizer.Tokens);
|
|
||||||
|
|
||||||
if (parser.Diagnostics.Any(x => x.Severity == DiagnosticSeverity.Error))
|
|
||||||
{
|
|
||||||
Console.Error.WriteLine($"Binding generator produced invalid syntax tree for header file {headerFile}");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
syntaxTrees.Add(syntaxTree);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var file in files)
|
|
||||||
{
|
{
|
||||||
var tokenizer = new Tokenizer(file, File.ReadAllText(file));
|
var tokenizer = new Tokenizer(file, File.ReadAllText(file));
|
||||||
tokenizer.Tokenize();
|
tokenizer.Tokenize();
|
||||||
|
|||||||
@@ -141,6 +141,19 @@ public class NubArrayType(NubType elementType) : NubType
|
|||||||
public override int GetHashCode() => HashCode.Combine(typeof(NubArrayType), ElementType);
|
public override int GetHashCode() => HashCode.Combine(typeof(NubArrayType), ElementType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class NubConstArrayType(NubType elementType, int size) : NubType
|
||||||
|
{
|
||||||
|
public override bool IsValueType => false;
|
||||||
|
public override bool IsScalar => true;
|
||||||
|
|
||||||
|
public NubType ElementType { get; } = elementType;
|
||||||
|
public int Size { get; } = size;
|
||||||
|
|
||||||
|
public override string ToString() => $"[{Size}]{ElementType}";
|
||||||
|
public override bool Equals(NubType? other) => other is NubConstArrayType array && ElementType.Equals(array.ElementType) && Size == array.Size;
|
||||||
|
public override int GetHashCode() => HashCode.Combine(typeof(NubConstArrayType), ElementType, Size);
|
||||||
|
}
|
||||||
|
|
||||||
public class NubCStringType : NubType
|
public class NubCStringType : NubType
|
||||||
{
|
{
|
||||||
public override bool IsValueType => false;
|
public override bool IsValueType => false;
|
||||||
|
|||||||
@@ -329,7 +329,7 @@ public sealed class TypeChecker
|
|||||||
AddressOfSyntax expression => CheckAddressOf(expression),
|
AddressOfSyntax expression => CheckAddressOf(expression),
|
||||||
ArrayIndexAccessSyntax expression => CheckArrayIndexAccess(expression),
|
ArrayIndexAccessSyntax expression => CheckArrayIndexAccess(expression),
|
||||||
ArrayInitializerSyntax expression => CheckArrayInitializer(expression),
|
ArrayInitializerSyntax expression => CheckArrayInitializer(expression),
|
||||||
BinaryExpressionSyntax expression => CheckBinaryExpression(expression),
|
BinaryExpressionSyntax expression => CheckBinaryExpression(expression, expectedType),
|
||||||
UnaryExpressionSyntax expression => CheckUnaryExpression(expression, expectedType),
|
UnaryExpressionSyntax expression => CheckUnaryExpression(expression, expectedType),
|
||||||
DereferenceSyntax expression => CheckDereference(expression),
|
DereferenceSyntax expression => CheckDereference(expression),
|
||||||
MemberFuncCallSyntax expression => CheckMemberFuncCall(expression),
|
MemberFuncCallSyntax expression => CheckMemberFuncCall(expression),
|
||||||
@@ -427,7 +427,7 @@ public sealed class TypeChecker
|
|||||||
return new ArrayInitializerNode(type, capacity, elementType);
|
return new ArrayInitializerNode(type, capacity, elementType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BinaryExpressionNode CheckBinaryExpression(BinaryExpressionSyntax expression)
|
private BinaryExpressionNode CheckBinaryExpression(BinaryExpressionSyntax expression, NubType? expectedType)
|
||||||
{
|
{
|
||||||
var op = expression.Operator switch
|
var op = expression.Operator switch
|
||||||
{
|
{
|
||||||
@@ -457,6 +457,7 @@ public sealed class TypeChecker
|
|||||||
case BinaryOperatorSyntax.Equal:
|
case BinaryOperatorSyntax.Equal:
|
||||||
case BinaryOperatorSyntax.NotEqual:
|
case BinaryOperatorSyntax.NotEqual:
|
||||||
{
|
{
|
||||||
|
// note(nub31): Expected type should not be passed down since the resulting type is different than operands
|
||||||
var left = CheckExpression(expression.Left);
|
var left = CheckExpression(expression.Left);
|
||||||
if (left.Type is not NubIntType and not NubFloatType and not NubBoolType)
|
if (left.Type is not NubIntType and not NubFloatType and not NubBoolType)
|
||||||
{
|
{
|
||||||
@@ -475,6 +476,7 @@ public sealed class TypeChecker
|
|||||||
case BinaryOperatorSyntax.LessThan:
|
case BinaryOperatorSyntax.LessThan:
|
||||||
case BinaryOperatorSyntax.LessThanOrEqual:
|
case BinaryOperatorSyntax.LessThanOrEqual:
|
||||||
{
|
{
|
||||||
|
// note(nub31): Expected type should not be passed down since the resulting type is different than operands
|
||||||
var left = CheckExpression(expression.Left);
|
var left = CheckExpression(expression.Left);
|
||||||
if (left.Type is not NubIntType and not NubFloatType)
|
if (left.Type is not NubIntType and not NubFloatType)
|
||||||
{
|
{
|
||||||
@@ -491,6 +493,7 @@ public sealed class TypeChecker
|
|||||||
case BinaryOperatorSyntax.LogicalAnd:
|
case BinaryOperatorSyntax.LogicalAnd:
|
||||||
case BinaryOperatorSyntax.LogicalOr:
|
case BinaryOperatorSyntax.LogicalOr:
|
||||||
{
|
{
|
||||||
|
// note(nub31): Expected type should not be passed down since the resulting type is different than operands
|
||||||
var left = CheckExpression(expression.Left);
|
var left = CheckExpression(expression.Left);
|
||||||
if (left.Type is not NubBoolType)
|
if (left.Type is not NubBoolType)
|
||||||
{
|
{
|
||||||
@@ -506,7 +509,7 @@ public sealed class TypeChecker
|
|||||||
}
|
}
|
||||||
case BinaryOperatorSyntax.Plus:
|
case BinaryOperatorSyntax.Plus:
|
||||||
{
|
{
|
||||||
var left = CheckExpression(expression.Left);
|
var left = CheckExpression(expression.Left, expectedType);
|
||||||
if (left.Type is NubIntType or NubFloatType or NubStringType or NubCStringType)
|
if (left.Type is NubIntType or NubFloatType or NubStringType or NubCStringType)
|
||||||
{
|
{
|
||||||
var right = CheckExpression(expression.Right, left.Type);
|
var right = CheckExpression(expression.Right, left.Type);
|
||||||
@@ -523,7 +526,7 @@ public sealed class TypeChecker
|
|||||||
case BinaryOperatorSyntax.Divide:
|
case BinaryOperatorSyntax.Divide:
|
||||||
case BinaryOperatorSyntax.Modulo:
|
case BinaryOperatorSyntax.Modulo:
|
||||||
{
|
{
|
||||||
var left = CheckExpression(expression.Left);
|
var left = CheckExpression(expression.Left, expectedType);
|
||||||
if (left.Type is not NubIntType and not NubFloatType)
|
if (left.Type is not NubIntType and not NubFloatType)
|
||||||
{
|
{
|
||||||
throw new TypeCheckerException(Diagnostic
|
throw new TypeCheckerException(Diagnostic
|
||||||
@@ -542,7 +545,7 @@ public sealed class TypeChecker
|
|||||||
case BinaryOperatorSyntax.BitwiseXor:
|
case BinaryOperatorSyntax.BitwiseXor:
|
||||||
case BinaryOperatorSyntax.BitwiseOr:
|
case BinaryOperatorSyntax.BitwiseOr:
|
||||||
{
|
{
|
||||||
var left = CheckExpression(expression.Left);
|
var left = CheckExpression(expression.Left, expectedType);
|
||||||
if (left.Type is not NubIntType)
|
if (left.Type is not NubIntType)
|
||||||
{
|
{
|
||||||
throw new TypeCheckerException(Diagnostic
|
throw new TypeCheckerException(Diagnostic
|
||||||
@@ -988,6 +991,7 @@ public sealed class TypeChecker
|
|||||||
FloatTypeSyntax f => new NubFloatType(f.Width),
|
FloatTypeSyntax f => new NubFloatType(f.Width),
|
||||||
FuncTypeSyntax func => new NubFuncType(func.Parameters.Select(ResolveType).ToList(), ResolveType(func.ReturnType)),
|
FuncTypeSyntax func => new NubFuncType(func.Parameters.Select(ResolveType).ToList(), ResolveType(func.ReturnType)),
|
||||||
ArrayTypeSyntax arr => new NubArrayType(ResolveType(arr.BaseType)),
|
ArrayTypeSyntax arr => new NubArrayType(ResolveType(arr.BaseType)),
|
||||||
|
ConstArrayTypeSyntax arr => new NubConstArrayType(ResolveType(arr.BaseType), arr.Size),
|
||||||
PointerTypeSyntax ptr => new NubPointerType(ResolveType(ptr.BaseType)),
|
PointerTypeSyntax ptr => new NubPointerType(ResolveType(ptr.BaseType)),
|
||||||
StringTypeSyntax => new NubStringType(),
|
StringTypeSyntax => new NubStringType(),
|
||||||
CustomTypeSyntax c => ResolveCustomType(c),
|
CustomTypeSyntax c => ResolveCustomType(c),
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ public class Diagnostic
|
|||||||
|
|
||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
return ConsoleColors.Colorize("Failed to generate error message", ConsoleColors.Red);
|
return ConsoleColors.Colorize("Failed to generate error message", ConsoleColors.Red);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,9 @@ public class Generator
|
|||||||
private readonly HashSet<NubStructType> _structTypes;
|
private readonly HashSet<NubStructType> _structTypes;
|
||||||
private readonly IndentedTextWriter _writer;
|
private readonly IndentedTextWriter _writer;
|
||||||
private readonly Stack<List<DeferNode>> _deferStack = [];
|
private readonly Stack<List<DeferNode>> _deferStack = [];
|
||||||
|
private readonly Stack<(string Name, NubFuncType FuncType)> _funcDefs = [];
|
||||||
private int _tmpIndex;
|
private int _tmpIndex;
|
||||||
|
private int _funcDefIndex;
|
||||||
|
|
||||||
public Generator(List<DefinitionNode> definitions, HashSet<NubStructType> structTypes)
|
public Generator(List<DefinitionNode> definitions, HashSet<NubStructType> structTypes)
|
||||||
{
|
{
|
||||||
@@ -23,47 +25,69 @@ public class Generator
|
|||||||
return $"_t{++_tmpIndex}";
|
return $"_t{++_tmpIndex}";
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string MapType(NubType nubType)
|
private string MapType(NubType nubType)
|
||||||
{
|
{
|
||||||
return nubType switch
|
return nubType switch
|
||||||
{
|
{
|
||||||
NubArrayType => "uintptr_t",
|
NubArrayType arrayType => MapType(arrayType.ElementType),
|
||||||
|
NubConstArrayType arrayType => MapType(arrayType.ElementType),
|
||||||
NubBoolType => "bool",
|
NubBoolType => "bool",
|
||||||
NubCStringType => "char*",
|
NubCStringType => "char",
|
||||||
NubFloatType floatType => floatType.Width switch
|
NubFloatType floatType => floatType.Width switch
|
||||||
{
|
{
|
||||||
32 => "f32",
|
32 => "f32",
|
||||||
64 => "f64",
|
64 => "f64",
|
||||||
_ => throw new ArgumentOutOfRangeException()
|
_ => throw new ArgumentOutOfRangeException()
|
||||||
},
|
},
|
||||||
NubFuncType => "uintptr_t",
|
NubFuncType funcType => MapFuncType(funcType),
|
||||||
NubIntType intType => intType.Signed switch
|
NubIntType intType => (intType.Signed, intType.Width) switch
|
||||||
{
|
{
|
||||||
true => intType.Width switch
|
(false, 8) => "u8",
|
||||||
{
|
(false, 16) => "u16",
|
||||||
8 => "i8",
|
(false, 32) => "u32",
|
||||||
16 => "i16",
|
(false, 64) => "u64",
|
||||||
32 => "i32",
|
(true, 8) => "i8",
|
||||||
64 => "i64",
|
(true, 16) => "i16",
|
||||||
|
(true, 32) => "i32",
|
||||||
|
(true, 64) => "i64",
|
||||||
_ => throw new ArgumentOutOfRangeException()
|
_ => throw new ArgumentOutOfRangeException()
|
||||||
},
|
},
|
||||||
false => intType.Width switch
|
NubPointerType pointerType => MapType(pointerType.BaseType),
|
||||||
{
|
NubStringType => throw new NotImplementedException(),
|
||||||
8 => "u8",
|
|
||||||
16 => "u16",
|
|
||||||
32 => "u32",
|
|
||||||
64 => "u64",
|
|
||||||
_ => throw new ArgumentOutOfRangeException()
|
|
||||||
},
|
|
||||||
},
|
|
||||||
NubPointerType => "uintptr_t",
|
|
||||||
NubStringType => "uintptr_t",
|
|
||||||
NubStructType structType => StructName(structType.Module, structType.Name),
|
NubStructType structType => StructName(structType.Module, structType.Name),
|
||||||
NubVoidType => "void",
|
NubVoidType => "void",
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(nubType))
|
_ => throw new ArgumentOutOfRangeException(nameof(nubType))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 = "";
|
||||||
|
var postfix = "";
|
||||||
|
|
||||||
|
switch (nubType)
|
||||||
|
{
|
||||||
|
case NubCStringType or NubPointerType:
|
||||||
|
prefix = "*";
|
||||||
|
break;
|
||||||
|
case NubArrayType:
|
||||||
|
postfix = "[]";
|
||||||
|
break;
|
||||||
|
case NubConstArrayType constArrayType:
|
||||||
|
postfix = $"[{constArrayType.Size}]";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $"{MapType(nubType)} {prefix}{name}{postfix}";
|
||||||
|
}
|
||||||
|
|
||||||
private static string FuncName(string module, string name, string? externSymbol)
|
private static string FuncName(string module, string name, string? externSymbol)
|
||||||
{
|
{
|
||||||
return externSymbol ?? $"{module}_{name}";
|
return externSymbol ?? $"{module}_{name}";
|
||||||
@@ -81,7 +105,7 @@ public class Generator
|
|||||||
|
|
||||||
public string Emit()
|
public string Emit()
|
||||||
{
|
{
|
||||||
_writer.WriteLine("""
|
var header = """
|
||||||
typedef __builtin_va_list va_list;
|
typedef __builtin_va_list va_list;
|
||||||
|
|
||||||
#define va_start(ap, last) __builtin_va_start(ap, last)
|
#define va_start(ap, last) __builtin_va_start(ap, last)
|
||||||
@@ -119,8 +143,7 @@ public class Generator
|
|||||||
|
|
||||||
#define I64_C(x) x##LL
|
#define I64_C(x) x##LL
|
||||||
#define U64_C(x) x##ULL
|
#define U64_C(x) x##ULL
|
||||||
""");
|
""";
|
||||||
_writer.WriteLine();
|
|
||||||
|
|
||||||
foreach (var structType in _structTypes)
|
foreach (var structType in _structTypes)
|
||||||
{
|
{
|
||||||
@@ -130,7 +153,7 @@ public class Generator
|
|||||||
{
|
{
|
||||||
foreach (var field in structType.Fields)
|
foreach (var field in structType.Fields)
|
||||||
{
|
{
|
||||||
_writer.WriteLine($"{MapType(field.Type)} {field.Name};");
|
_writer.WriteLine($"{MapNameWithType(field.Type, field.Name)};");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,11 +167,11 @@ public class Generator
|
|||||||
{
|
{
|
||||||
appendNewLine = true;
|
appendNewLine = true;
|
||||||
var parameters = funcNode.Signature.Parameters.Count != 0
|
var parameters = funcNode.Signature.Parameters.Count != 0
|
||||||
? string.Join(", ", funcNode.Signature.Parameters.Select(x => $"{MapType(x.Type)} {x.Name}"))
|
? string.Join(", ", funcNode.Signature.Parameters.Select(x => MapNameWithType(x.Type, x.Name)))
|
||||||
: "void";
|
: "void";
|
||||||
|
|
||||||
var name = FuncName(funcNode.Module, funcNode.Name, funcNode.ExternSymbol);
|
var name = FuncName(funcNode.Module, funcNode.Name, funcNode.ExternSymbol);
|
||||||
_writer.WriteLine($"{MapType(funcNode.Signature.ReturnType)} {name}({parameters});");
|
_writer.WriteLine($"{MapNameWithType(funcNode.Signature.ReturnType, name)}({parameters});");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (appendNewLine)
|
if (appendNewLine)
|
||||||
@@ -161,11 +184,11 @@ public class Generator
|
|||||||
foreach (var structFuncNode in structNode.Functions)
|
foreach (var structFuncNode in structNode.Functions)
|
||||||
{
|
{
|
||||||
var parameters = structFuncNode.Signature.Parameters.Count != 0
|
var parameters = structFuncNode.Signature.Parameters.Count != 0
|
||||||
? string.Join(", ", structFuncNode.Signature.Parameters.Select(x => $"{MapType(x.Type)} {x.Name}"))
|
? string.Join(", ", structFuncNode.Signature.Parameters.Select(x => MapNameWithType(x.Type, x.Name)))
|
||||||
: "void";
|
: "void";
|
||||||
|
|
||||||
var name = StructFuncName(structNode.Module, structNode.Name, structFuncNode.Name);
|
var name = StructFuncName(structNode.Module, structNode.Name, structFuncNode.Name);
|
||||||
_writer.WriteLine($"{MapType(structFuncNode.Signature.ReturnType)} {name}({parameters})");
|
_writer.WriteLine($"{MapNameWithType(structFuncNode.Signature.ReturnType, name)}({parameters})");
|
||||||
EmitBlock(structFuncNode.Body);
|
EmitBlock(structFuncNode.Body);
|
||||||
_writer.WriteLine();
|
_writer.WriteLine();
|
||||||
}
|
}
|
||||||
@@ -176,7 +199,7 @@ public class Generator
|
|||||||
if (funcNode.Body == null) continue;
|
if (funcNode.Body == null) continue;
|
||||||
|
|
||||||
var parameters = funcNode.Signature.Parameters.Count != 0
|
var parameters = funcNode.Signature.Parameters.Count != 0
|
||||||
? string.Join(", ", funcNode.Signature.Parameters.Select(x => $"{MapType(x.Type)} {x.Name}"))
|
? string.Join(", ", funcNode.Signature.Parameters.Select(x => MapNameWithType(x.Type, x.Name)))
|
||||||
: "void";
|
: "void";
|
||||||
|
|
||||||
if (funcNode.ExternSymbol == null)
|
if (funcNode.ExternSymbol == null)
|
||||||
@@ -185,12 +208,26 @@ public class Generator
|
|||||||
}
|
}
|
||||||
|
|
||||||
var name = FuncName(funcNode.Module, funcNode.Name, funcNode.ExternSymbol);
|
var name = FuncName(funcNode.Module, funcNode.Name, funcNode.ExternSymbol);
|
||||||
_writer.WriteLine($"{MapType(funcNode.Signature.ReturnType)} {name}({parameters})");
|
_writer.WriteLine($"{MapNameWithType(funcNode.Signature.ReturnType, name)}({parameters})");
|
||||||
EmitBlock(funcNode.Body);
|
EmitBlock(funcNode.Body);
|
||||||
_writer.WriteLine();
|
_writer.WriteLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
return _writer.ToString();
|
List<string> typedefs = [];
|
||||||
|
|
||||||
|
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";
|
||||||
|
}
|
||||||
|
|
||||||
|
typedefs.Add($"typedef {returnType} (*{funcTypeDef.Name})({paramList});");
|
||||||
|
}
|
||||||
|
|
||||||
|
return header + "\n\n" + string.Join('\n', typedefs) + "\n\n" + _writer;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EmitStatement(StatementNode statementNode)
|
private void EmitStatement(StatementNode statementNode)
|
||||||
@@ -296,7 +333,7 @@ public class Generator
|
|||||||
if (_deferStack.Peek().Count != 0)
|
if (_deferStack.Peek().Count != 0)
|
||||||
{
|
{
|
||||||
var tmp = NewTmp();
|
var tmp = NewTmp();
|
||||||
_writer.WriteLine($"{MapType(returnNode.Value.Type)} {tmp} = {returnValue};");
|
_writer.WriteLine($"{MapNameWithType(returnNode.Value.Type, tmp)} = {returnValue};");
|
||||||
|
|
||||||
var blockDefers = _deferStack.Peek();
|
var blockDefers = _deferStack.Peek();
|
||||||
for (var i = blockDefers.Count - 1; i >= 0; i--)
|
for (var i = blockDefers.Count - 1; i >= 0; i--)
|
||||||
@@ -330,11 +367,11 @@ public class Generator
|
|||||||
if (variableDeclarationNode.Assignment != null)
|
if (variableDeclarationNode.Assignment != null)
|
||||||
{
|
{
|
||||||
var value = EmitExpression(variableDeclarationNode.Assignment);
|
var value = EmitExpression(variableDeclarationNode.Assignment);
|
||||||
_writer.WriteLine($"{MapType(variableDeclarationNode.Type)} {variableDeclarationNode.Name} = {value};");
|
_writer.WriteLine($"{MapNameWithType(variableDeclarationNode.Type, variableDeclarationNode.Name)} = {value};");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_writer.WriteLine($"{MapType(variableDeclarationNode.Type)} {variableDeclarationNode.Name};");
|
_writer.WriteLine($"{MapNameWithType(variableDeclarationNode.Type, variableDeclarationNode.Name)};");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -383,14 +420,12 @@ public class Generator
|
|||||||
{
|
{
|
||||||
var array = EmitExpression(arrayIndexAccessNode.Target);
|
var array = EmitExpression(arrayIndexAccessNode.Target);
|
||||||
var index = EmitExpression(arrayIndexAccessNode.Index);
|
var index = EmitExpression(arrayIndexAccessNode.Index);
|
||||||
return $"(({MapType(arrayIndexAccessNode.Type)}*){array})[{index}]";
|
return $"{array}[{index}]";
|
||||||
}
|
}
|
||||||
|
|
||||||
private string EmitArrayInitializer(ArrayInitializerNode arrayInitializerNode)
|
private string EmitArrayInitializer(ArrayInitializerNode arrayInitializerNode)
|
||||||
{
|
{
|
||||||
var capacity = EmitExpression(arrayInitializerNode.Capacity);
|
throw new NotImplementedException();
|
||||||
var elementType = MapType(arrayInitializerNode.ElementType);
|
|
||||||
return $"({elementType}[{capacity}]){{0}}";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private string EmitBinaryExpression(BinaryExpressionNode binaryExpressionNode)
|
private string EmitBinaryExpression(BinaryExpressionNode binaryExpressionNode)
|
||||||
@@ -432,13 +467,32 @@ public class Generator
|
|||||||
private string EmitConvertFloat(ConvertFloatNode convertFloatNode)
|
private string EmitConvertFloat(ConvertFloatNode convertFloatNode)
|
||||||
{
|
{
|
||||||
var value = EmitExpression(convertFloatNode.Value);
|
var value = EmitExpression(convertFloatNode.Value);
|
||||||
return $"({MapType(convertFloatNode.Type)}){value}";
|
var targetCast = convertFloatNode.TargetType.Width switch
|
||||||
|
{
|
||||||
|
32 => "f32",
|
||||||
|
64 => "f64",
|
||||||
|
_ => throw new ArgumentOutOfRangeException()
|
||||||
|
};
|
||||||
|
|
||||||
|
return $"({targetCast}){value}";
|
||||||
}
|
}
|
||||||
|
|
||||||
private string EmitConvertInt(ConvertIntNode convertIntNode)
|
private string EmitConvertInt(ConvertIntNode convertIntNode)
|
||||||
{
|
{
|
||||||
var value = EmitExpression(convertIntNode.Value);
|
var value = EmitExpression(convertIntNode.Value);
|
||||||
return $"({MapType(convertIntNode.Type)}){value}";
|
var targetType = (convertIntNode.TargetType.Signed, 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",
|
||||||
|
_ => throw new ArgumentOutOfRangeException()
|
||||||
|
};
|
||||||
|
return $"({targetType}){value}";
|
||||||
}
|
}
|
||||||
|
|
||||||
private string EmitCStringLiteral(CStringLiteralNode cStringLiteralNode)
|
private string EmitCStringLiteral(CStringLiteralNode cStringLiteralNode)
|
||||||
@@ -449,7 +503,7 @@ public class Generator
|
|||||||
private string EmitDereference(DereferenceNode dereferenceNode)
|
private string EmitDereference(DereferenceNode dereferenceNode)
|
||||||
{
|
{
|
||||||
var pointer = EmitExpression(dereferenceNode.Target);
|
var pointer = EmitExpression(dereferenceNode.Target);
|
||||||
return $"*({MapType(dereferenceNode.Type)}*){pointer}";
|
return $"*{pointer}";
|
||||||
}
|
}
|
||||||
|
|
||||||
private string EmitFloat32Literal(Float32LiteralNode float32LiteralNode)
|
private string EmitFloat32Literal(Float32LiteralNode float32LiteralNode)
|
||||||
@@ -477,7 +531,19 @@ public class Generator
|
|||||||
private string EmitFloatToIntBuiltin(FloatToIntBuiltinNode floatToIntBuiltinNode)
|
private string EmitFloatToIntBuiltin(FloatToIntBuiltinNode floatToIntBuiltinNode)
|
||||||
{
|
{
|
||||||
var value = EmitExpression(floatToIntBuiltinNode.Value);
|
var value = EmitExpression(floatToIntBuiltinNode.Value);
|
||||||
return $"({MapType(floatToIntBuiltinNode.Type)}){value}";
|
var targetType = (floatToIntBuiltinNode.TargetType.Signed, 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",
|
||||||
|
_ => throw new ArgumentOutOfRangeException()
|
||||||
|
};
|
||||||
|
return $"({targetType}){value}";
|
||||||
}
|
}
|
||||||
|
|
||||||
private string EmitFuncCall(FuncCallNode funcCallNode)
|
private string EmitFuncCall(FuncCallNode funcCallNode)
|
||||||
@@ -508,7 +574,7 @@ public class Generator
|
|||||||
private string EmitAddressOf(AddressOfNode addressOfNode)
|
private string EmitAddressOf(AddressOfNode addressOfNode)
|
||||||
{
|
{
|
||||||
var value = EmitExpression(addressOfNode.LValue);
|
var value = EmitExpression(addressOfNode.LValue);
|
||||||
return $"(uintptr_t)&{value}";
|
return $"&{value}";
|
||||||
}
|
}
|
||||||
|
|
||||||
private string EmitLValueIdentifier(LValueIdentifierNode lValueIdentifierNode)
|
private string EmitLValueIdentifier(LValueIdentifierNode lValueIdentifierNode)
|
||||||
@@ -523,6 +589,11 @@ public class Generator
|
|||||||
|
|
||||||
private string EmitSizeBuiltin(SizeBuiltinNode sizeBuiltinNode)
|
private string EmitSizeBuiltin(SizeBuiltinNode sizeBuiltinNode)
|
||||||
{
|
{
|
||||||
|
if (sizeBuiltinNode.TargetType is NubConstArrayType constArrayType)
|
||||||
|
{
|
||||||
|
return $"sizeof({MapType(constArrayType.ElementType)}) * {constArrayType.Size}";
|
||||||
|
}
|
||||||
|
|
||||||
return $"sizeof({MapType(sizeBuiltinNode.TargetType)})";
|
return $"sizeof({MapType(sizeBuiltinNode.TargetType)})";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -539,9 +610,10 @@ public class Generator
|
|||||||
|
|
||||||
private string EmitStructFuncCall(StructFuncCallNode structFuncCallNode)
|
private string EmitStructFuncCall(StructFuncCallNode structFuncCallNode)
|
||||||
{
|
{
|
||||||
|
var thisParameter = EmitExpression(structFuncCallNode.StructExpression);
|
||||||
var name = StructFuncName(structFuncCallNode.Module, structFuncCallNode.StructName, structFuncCallNode.FuncName);
|
var name = StructFuncName(structFuncCallNode.Module, structFuncCallNode.StructName, structFuncCallNode.FuncName);
|
||||||
var parameterNames = structFuncCallNode.Parameters.Select(EmitExpression).ToList();
|
var parameterNames = structFuncCallNode.Parameters.Select(EmitExpression).ToList();
|
||||||
return $"{name}({string.Join(", ", parameterNames)})";
|
return $"{name}({thisParameter}, {string.Join(", ", parameterNames)})";
|
||||||
}
|
}
|
||||||
|
|
||||||
private string EmitStructInitializer(StructInitializerNode structInitializerNode)
|
private string EmitStructInitializer(StructInitializerNode structInitializerNode)
|
||||||
@@ -557,7 +629,7 @@ public class Generator
|
|||||||
? "0"
|
? "0"
|
||||||
: string.Join(", ", initValues);
|
: string.Join(", ", initValues);
|
||||||
|
|
||||||
return $"({MapType(structInitializerNode.Type)}){{{initString}}}";
|
return $"({StructName(structInitializerNode.StructType.Module, structInitializerNode.StructType.Name)}){{{initString}}}";
|
||||||
}
|
}
|
||||||
|
|
||||||
private string EmitUIntLiteral(UIntLiteralNode uIntLiteralNode)
|
private string EmitUIntLiteral(UIntLiteralNode uIntLiteralNode)
|
||||||
|
|||||||
@@ -806,11 +806,20 @@ public sealed class Parser
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (TryExpectSymbol(Symbol.OpenBracket))
|
if (TryExpectSymbol(Symbol.OpenBracket))
|
||||||
|
{
|
||||||
|
if (TryExpectIntLiteral(out var intLiteral))
|
||||||
|
{
|
||||||
|
ExpectSymbol(Symbol.CloseBracket);
|
||||||
|
var baseType = ParseType();
|
||||||
|
return new ConstArrayTypeSyntax(GetTokens(startIndex), baseType, int.Parse(intLiteral.Value));
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
ExpectSymbol(Symbol.CloseBracket);
|
ExpectSymbol(Symbol.CloseBracket);
|
||||||
var baseType = ParseType();
|
var baseType = ParseType();
|
||||||
return new ArrayTypeSyntax(GetTokens(startIndex), baseType);
|
return new ArrayTypeSyntax(GetTokens(startIndex), baseType);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
throw new ParseException(Diagnostic
|
throw new ParseException(Diagnostic
|
||||||
.Error("Invalid type syntax")
|
.Error("Invalid type syntax")
|
||||||
@@ -930,6 +939,19 @@ public sealed class Parser
|
|||||||
return identifier;
|
return identifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool TryExpectIntLiteral([NotNullWhen(true)] out IntLiteralToken? stringLiteral)
|
||||||
|
{
|
||||||
|
if (CurrentToken is IntLiteralToken token)
|
||||||
|
{
|
||||||
|
stringLiteral = token;
|
||||||
|
Next();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
stringLiteral = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private FloatLiteralToken ExpectFloatLiteral()
|
private FloatLiteralToken ExpectFloatLiteral()
|
||||||
{
|
{
|
||||||
var token = ExpectToken();
|
var token = ExpectToken();
|
||||||
|
|||||||
@@ -144,6 +144,8 @@ public record CStringTypeSyntax(List<Token> Tokens) : TypeSyntax(Tokens);
|
|||||||
|
|
||||||
public record ArrayTypeSyntax(List<Token> Tokens, TypeSyntax BaseType) : TypeSyntax(Tokens);
|
public record ArrayTypeSyntax(List<Token> Tokens, TypeSyntax BaseType) : TypeSyntax(Tokens);
|
||||||
|
|
||||||
|
public record ConstArrayTypeSyntax(List<Token> Tokens, TypeSyntax BaseType, int Size) : TypeSyntax(Tokens);
|
||||||
|
|
||||||
public record CustomTypeSyntax(List<Token> Tokens, string Module, string Name) : TypeSyntax(Tokens);
|
public record CustomTypeSyntax(List<Token> Tokens, string Module, string Name) : TypeSyntax(Tokens);
|
||||||
|
|
||||||
public record StructTemplateTypeSyntax(List<Token> Tokens, List<TypeSyntax> TemplateParameters, string Module, string Name) : TypeSyntax(Tokens);
|
public record StructTemplateTypeSyntax(List<Token> Tokens, List<TypeSyntax> TemplateParameters, string Module, string Name) : TypeSyntax(Tokens);
|
||||||
|
|||||||
Reference in New Issue
Block a user