Compare commits

...

7 Commits

Author SHA1 Message Date
nub31
560e6428ff ... 2025-10-26 22:28:48 +01:00
nub31
27bc4da4fd ... 2025-10-26 20:04:57 +01:00
nub31
d11df414ad Refs working? 2025-10-26 17:05:56 +01:00
nub31
3febaaea81 ref 2025-10-26 16:07:49 +01:00
nub31
828e20ddb6 ... 2025-10-26 14:15:25 +01:00
nub31
396ddf93a2 ... 2025-10-25 18:07:34 +02:00
nub31
3f18aa4782 ... 2025-10-24 15:38:51 +02:00
35 changed files with 1785 additions and 1387 deletions

5
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,5 @@
{
"files.associations": {
"ref.h": "c"
}
}

View File

@@ -21,7 +21,7 @@ foreach (var file in args)
} }
var modules = Module.Collect(syntaxTrees); var modules = Module.Collect(syntaxTrees);
var compilationUnits = new List<CompilationUnit>(); var compilationUnits = new List<List<TopLevelNode>>();
for (var i = 0; i < args.Length; i++) for (var i = 0; i < args.Length; i++)
{ {
@@ -46,6 +46,43 @@ var cPaths = new List<string>();
Directory.CreateDirectory(".build"); Directory.CreateDirectory(".build");
var typedModules = modules.Select(x => (x.Key, TypedModule.FromModule(x.Key, x.Value, modules))).ToDictionary();
var moduleHeaders = new List<string>();
var commonHeaderOut = Path.Combine(".build", "runtime.h");
File.WriteAllText(commonHeaderOut, """
#include <stddef.h>
void *rc_alloc(size_t size, void (*destructor)(void *self));
void rc_retain(void *obj);
void rc_release(void *obj);
typedef struct
{
unsigned long long length;
char *data;
} nub_string;
typedef struct
{
unsigned long long length;
void *data;
} nub_slice;
""");
moduleHeaders.Add(commonHeaderOut);
foreach (var typedModule in typedModules)
{
var header = HeaderGenerator.Generate(typedModule.Key, typedModule.Value);
var headerOut = Path.Combine(".build", "modules", typedModule.Key + ".h");
Directory.CreateDirectory(Path.Combine(".build", "modules"));
File.WriteAllText(headerOut, header);
moduleHeaders.Add(headerOut);
}
for (var i = 0; i < args.Length; i++) for (var i = 0; i < args.Length; i++)
{ {
var file = args[i]; var file = args[i];
@@ -69,6 +106,7 @@ foreach (var cPath in cPaths)
{ {
var objectPath = Path.ChangeExtension(cPath, "o"); var objectPath = Path.ChangeExtension(cPath, "o");
using var compileProcess = Process.Start("clang", [ using var compileProcess = Process.Start("clang", [
..moduleHeaders.SelectMany(x => new[] { "-include", x }),
"-ffreestanding", "-std=c23", "-ffreestanding", "-std=c23",
"-g", "-c", "-g", "-c",
"-o", objectPath, "-o", objectPath,

View File

@@ -1,5 +1,4 @@
using NubLang.Ast; using NubLang.Ast;
using NubLang.Syntax;
using OmniSharp.Extensions.LanguageServer.Protocol.Models; using OmniSharp.Extensions.LanguageServer.Protocol.Models;
using Range = OmniSharp.Extensions.LanguageServer.Protocol.Models.Range; using Range = OmniSharp.Extensions.LanguageServer.Protocol.Models.Range;
@@ -58,16 +57,16 @@ public static class AstExtensions
return false; return false;
} }
public static FuncNode? FunctionAtPosition(this CompilationUnit compilationUnit, int line, int character) public static FuncNode? FunctionAtPosition(this List<TopLevelNode> compilationUnit, int line, int character)
{ {
return compilationUnit return compilationUnit
.Functions .OfType<FuncNode>()
.FirstOrDefault(x => x.ContainsPosition(line, character)); .FirstOrDefault(x => x.ContainsPosition(line, character));
} }
public static Node? DeepestNodeAtPosition(this CompilationUnit compilationUnit, int line, int character) public static Node? DeepestNodeAtPosition(this List<TopLevelNode> compilationUnit, int line, int character)
{ {
return compilationUnit.Functions return compilationUnit
.SelectMany(x => x.DescendantsAndSelf()) .SelectMany(x => x.DescendantsAndSelf())
.Where(n => n.ContainsPosition(line, character)) .Where(n => n.ContainsPosition(line, character))
.OrderBy(n => n.Tokens.First().Span.Start.Line) .OrderBy(n => n.Tokens.First().Span.Start.Line)

View File

@@ -118,35 +118,38 @@ internal class CompletionHandler(WorkspaceManager workspaceManager) : Completion
var compilationUnit = workspaceManager.GetCompilationUnit(uri); var compilationUnit = workspaceManager.GetCompilationUnit(uri);
if (compilationUnit != null) if (compilationUnit != null)
{ {
var function = compilationUnit.Functions.FirstOrDefault(x => x.Body != null && x.Body.ContainsPosition(position.Line, position.Character)); var function = compilationUnit.OfType<FuncNode>().FirstOrDefault(x => x.Body != null && x.Body.ContainsPosition(position.Line, position.Character));
if (function != null) if (function != null)
{ {
completions.AddRange(_statementSnippets); completions.AddRange(_statementSnippets);
foreach (var prototype in compilationUnit.ImportedFunctions) // foreach (var (module, prototypes) in compilationUnit.ImportedFunctions)
{ // {
var parameterStrings = new List<string>(); // foreach (var prototype in prototypes)
foreach (var (index, parameter) in prototype.Parameters.Index()) // {
{ // var parameterStrings = new List<string>();
parameterStrings.AddRange($"${{{index + 1}:{parameter.Name}}}"); // foreach (var (index, parameter) in prototype.Parameters.Index())
} // {
// parameterStrings.AddRange($"${{{index + 1}:{parameter.NameToken.Value}}}");
completions.Add(new CompletionItem // }
{ //
Kind = CompletionItemKind.Function, // completions.Add(new CompletionItem
Label = $"{prototype.Module}::{prototype.Name}", // {
InsertTextFormat = InsertTextFormat.Snippet, // Kind = CompletionItemKind.Function,
InsertText = $"{prototype.Module}::{prototype.Name}({string.Join(", ", parameterStrings)})", // Label = $"{module.Value}::{prototype.NameToken.Value}",
}); // InsertTextFormat = InsertTextFormat.Snippet,
} // InsertText = $"{module.Value}::{prototype.NameToken.Value}({string.Join(", ", parameterStrings)})",
// });
// }
// }
foreach (var parameter in function.Prototype.Parameters) foreach (var parameter in function.Prototype.Parameters)
{ {
completions.Add(new CompletionItem completions.Add(new CompletionItem
{ {
Kind = CompletionItemKind.Variable, Kind = CompletionItemKind.Variable,
Label = parameter.Name, Label = parameter.NameToken.Value,
InsertText = parameter.Name, InsertText = parameter.NameToken.Value,
}); });
} }
@@ -159,8 +162,8 @@ internal class CompletionHandler(WorkspaceManager workspaceManager) : Completion
completions.Add(new CompletionItem completions.Add(new CompletionItem
{ {
Kind = CompletionItemKind.Variable, Kind = CompletionItemKind.Variable,
Label = variable.Name, Label = variable.NameToken.Value,
InsertText = variable.Name, InsertText = variable.NameToken.Value,
}); });
} }
} }

View File

@@ -37,7 +37,7 @@ internal class DefinitionHandler(WorkspaceManager workspaceManager) : Definition
{ {
var function = compilationUnit.FunctionAtPosition(line, character); var function = compilationUnit.FunctionAtPosition(line, character);
var parameter = function?.Prototype.Parameters.FirstOrDefault(x => x.Name == variableIdentifierNode.Name); var parameter = function?.Prototype.Parameters.FirstOrDefault(x => x.NameToken.Value == variableIdentifierNode.NameToken.Value);
if (parameter != null) if (parameter != null)
{ {
return new LocationOrLocationLinks(parameter.ToLocation()); return new LocationOrLocationLinks(parameter.ToLocation());
@@ -46,7 +46,7 @@ internal class DefinitionHandler(WorkspaceManager workspaceManager) : Definition
var variable = function?.Body? var variable = function?.Body?
.Descendants() .Descendants()
.OfType<VariableDeclarationNode>() .OfType<VariableDeclarationNode>()
.FirstOrDefault(x => x.Name == variableIdentifierNode.Name); .FirstOrDefault(x => x.NameToken.Value == variableIdentifierNode.NameToken.Value);
if (variable != null) if (variable != null)
{ {
@@ -57,11 +57,16 @@ internal class DefinitionHandler(WorkspaceManager workspaceManager) : Definition
} }
case FuncIdentifierNode funcIdentifierNode: case FuncIdentifierNode funcIdentifierNode:
{ {
var prototype = compilationUnit.ImportedFunctions.FirstOrDefault(x => x.Module == funcIdentifierNode.Module && x.Name == funcIdentifierNode.Name); // var prototype = compilationUnit
if (prototype != null) // .ImportedFunctions
{ // .Where(x => x.Key.Value == funcIdentifierNode.ModuleToken.Value)
return new LocationOrLocationLinks(prototype.ToLocation()); // .SelectMany(x => x.Value)
} // .FirstOrDefault(x => x.NameToken.Value == funcIdentifierNode.NameToken.Value);
//
// if (prototype != null)
// {
// return new LocationOrLocationLinks(prototype.ToLocation());
// }
return null; return null;
} }

View File

@@ -39,104 +39,110 @@ internal class HoverHandler(WorkspaceManager workspaceManager) : HoverHandlerBas
return null; return null;
} }
var message = CreateMessage(hoveredNode, compilationUnit); // var message = CreateMessage(hoveredNode, compilationUnit);
if (message == null) // if (message == null)
{ // {
return null; // return null;
} // }
//
// return new Hover
// {
// Contents = new MarkedStringsOrMarkupContent(new MarkupContent
// {
// Value = message,
// Kind = MarkupKind.Markdown,
// })
// };
return new Hover return null;
{
Contents = new MarkedStringsOrMarkupContent(new MarkupContent
{
Value = message,
Kind = MarkupKind.Markdown,
})
};
} }
private static string? CreateMessage(Node hoveredNode, CompilationUnit compilationUnit) // private static string? CreateMessage(Node hoveredNode, CompilationUnit compilationUnit)
{ // {
return hoveredNode switch // return hoveredNode switch
{ // {
FuncNode funcNode => CreateFuncPrototypeMessage(funcNode.Prototype), // FuncNode funcNode => CreateFuncPrototypeMessage(funcNode.Prototype),
FuncPrototypeNode funcPrototypeNode => CreateFuncPrototypeMessage(funcPrototypeNode), // FuncPrototypeNode funcPrototypeNode => CreateFuncPrototypeMessage(funcPrototypeNode),
FuncIdentifierNode funcIdentifierNode => CreateFuncIdentifierMessage(funcIdentifierNode, compilationUnit), // FuncIdentifierNode funcIdentifierNode => CreateFuncIdentifierMessage(funcIdentifierNode, compilationUnit),
FuncParameterNode funcParameterNode => CreateTypeNameMessage("Function parameter", funcParameterNode.Name, funcParameterNode.Type), // FuncParameterNode funcParameterNode => CreateTypeNameMessage("Function parameter", funcParameterNode.NameToken.Value, funcParameterNode.Type),
VariableIdentifierNode variableIdentifierNode => CreateTypeNameMessage("Variable", variableIdentifierNode.Name, variableIdentifierNode.Type), // VariableIdentifierNode variableIdentifierNode => CreateTypeNameMessage("Variable", variableIdentifierNode.NameToken.Value, variableIdentifierNode.Type),
VariableDeclarationNode variableDeclarationNode => CreateTypeNameMessage("Variable declaration", variableDeclarationNode.Name, variableDeclarationNode.Type), // VariableDeclarationNode variableDeclarationNode => CreateTypeNameMessage("Variable declaration", variableDeclarationNode.NameToken.Value, variableDeclarationNode.Type),
StructFieldAccessNode structFieldAccessNode => CreateTypeNameMessage("Struct field", $"{structFieldAccessNode.Target.Type}.{structFieldAccessNode.Field}", structFieldAccessNode.Type), // StructFieldAccessNode structFieldAccessNode => CreateTypeNameMessage("Struct field", $"{structFieldAccessNode.Target.Type}.{structFieldAccessNode.FieldToken.Value}", structFieldAccessNode.Type),
CStringLiteralNode cStringLiteralNode => CreateLiteralMessage(cStringLiteralNode.Type, '"' + cStringLiteralNode.Value + '"'), // CStringLiteralNode cStringLiteralNode => CreateLiteralMessage(cStringLiteralNode.Type, '"' + cStringLiteralNode.Value + '"'),
StringLiteralNode stringLiteralNode => CreateLiteralMessage(stringLiteralNode.Type, '"' + stringLiteralNode.Value + '"'), // StringLiteralNode stringLiteralNode => CreateLiteralMessage(stringLiteralNode.Type, '"' + stringLiteralNode.Value + '"'),
BoolLiteralNode boolLiteralNode => CreateLiteralMessage(boolLiteralNode.Type, boolLiteralNode.Value.ToString()), // BoolLiteralNode boolLiteralNode => CreateLiteralMessage(boolLiteralNode.Type, boolLiteralNode.Value.ToString()),
Float32LiteralNode float32LiteralNode => CreateLiteralMessage(float32LiteralNode.Type, float32LiteralNode.Value.ToString(CultureInfo.InvariantCulture)), // Float32LiteralNode float32LiteralNode => CreateLiteralMessage(float32LiteralNode.Type, float32LiteralNode.Value.ToString(CultureInfo.InvariantCulture)),
Float64LiteralNode float64LiteralNode => CreateLiteralMessage(float64LiteralNode.Type, float64LiteralNode.Value.ToString(CultureInfo.InvariantCulture)), // Float64LiteralNode float64LiteralNode => CreateLiteralMessage(float64LiteralNode.Type, float64LiteralNode.Value.ToString(CultureInfo.InvariantCulture)),
I8LiteralNode i8LiteralNode => CreateLiteralMessage(i8LiteralNode.Type, i8LiteralNode.Value.ToString()), // I8LiteralNode i8LiteralNode => CreateLiteralMessage(i8LiteralNode.Type, i8LiteralNode.Value.ToString()),
I16LiteralNode i16LiteralNode => CreateLiteralMessage(i16LiteralNode.Type, i16LiteralNode.Value.ToString()), // I16LiteralNode i16LiteralNode => CreateLiteralMessage(i16LiteralNode.Type, i16LiteralNode.Value.ToString()),
I32LiteralNode i32LiteralNode => CreateLiteralMessage(i32LiteralNode.Type, i32LiteralNode.Value.ToString()), // I32LiteralNode i32LiteralNode => CreateLiteralMessage(i32LiteralNode.Type, i32LiteralNode.Value.ToString()),
I64LiteralNode i64LiteralNode => CreateLiteralMessage(i64LiteralNode.Type, i64LiteralNode.Value.ToString()), // I64LiteralNode i64LiteralNode => CreateLiteralMessage(i64LiteralNode.Type, i64LiteralNode.Value.ToString()),
U8LiteralNode u8LiteralNode => CreateLiteralMessage(u8LiteralNode.Type, u8LiteralNode.Value.ToString()), // U8LiteralNode u8LiteralNode => CreateLiteralMessage(u8LiteralNode.Type, u8LiteralNode.Value.ToString()),
U16LiteralNode u16LiteralNode => CreateLiteralMessage(u16LiteralNode.Type, u16LiteralNode.Value.ToString()), // U16LiteralNode u16LiteralNode => CreateLiteralMessage(u16LiteralNode.Type, u16LiteralNode.Value.ToString()),
U32LiteralNode u32LiteralNode => CreateLiteralMessage(u32LiteralNode.Type, u32LiteralNode.Value.ToString()), // U32LiteralNode u32LiteralNode => CreateLiteralMessage(u32LiteralNode.Type, u32LiteralNode.Value.ToString()),
U64LiteralNode u64LiteralNode => CreateLiteralMessage(u64LiteralNode.Type, u64LiteralNode.Value.ToString()), // U64LiteralNode u64LiteralNode => CreateLiteralMessage(u64LiteralNode.Type, u64LiteralNode.Value.ToString()),
// Expressions can have a generic fallback showing the resulting type // // Expressions can have a generic fallback showing the resulting type
ExpressionNode expressionNode => $""" // ExpressionNode expressionNode => $"""
**Expression** `{expressionNode.GetType().Name}` // **Expression** `{expressionNode.GetType().Name}`
```nub // ```nub
{expressionNode.Type} // {expressionNode.Type}
``` // ```
""", // """,
BlockNode => null, // BlockNode => null,
_ => hoveredNode.GetType().Name // _ => hoveredNode.GetType().Name
}; // };
} // }
//
private static string CreateLiteralMessage(NubType type, string value) // private static string CreateLiteralMessage(NubType type, string value)
{ // {
return $""" // return $"""
**Literal** `{type}` // **Literal** `{type}`
```nub // ```nub
{value}: {type} // {value}: {type}
``` // ```
"""; // """;
} // }
//
private static string CreateTypeNameMessage(string description, string name, NubType type) // private static string CreateTypeNameMessage(string description, string name, NubType type)
{ // {
return $""" // return $"""
**{description}** `{name}` // **{description}** `{name}`
```nub // ```nub
{name}: {type} // {name}: {type}
``` // ```
"""; // """;
} // }
//
private static string CreateFuncIdentifierMessage(FuncIdentifierNode funcIdentifierNode, CompilationUnit compilationUnit) // private static string CreateFuncIdentifierMessage(FuncIdentifierNode funcIdentifierNode, CompilationUnit compilationUnit)
{ // {
var func = compilationUnit.ImportedFunctions.FirstOrDefault(x => x.Module == funcIdentifierNode.Module && x.Name == funcIdentifierNode.Name); // var func = compilationUnit.ImportedFunctions
if (func == null) // .Where(x => x.Key.Value == funcIdentifierNode.ModuleToken.Value)
{ // .SelectMany(x => x.Value)
return $""" // .FirstOrDefault(x => x.NameToken.Value == funcIdentifierNode.NameToken.Value);
**Function** `{funcIdentifierNode.Module}::{funcIdentifierNode.Name}` //
```nub // if (func == null)
// Declaration not found // {
``` // return $"""
"""; // **Function** `{funcIdentifierNode.ModuleToken.Value}::{funcIdentifierNode.NameToken.Value}`
} // ```nub
// // Declaration not found
return CreateFuncPrototypeMessage(func); // ```
} // """;
// }
private static string CreateFuncPrototypeMessage(FuncPrototypeNode funcPrototypeNode) //
{ // return CreateFuncPrototypeMessage(func);
var parameterText = string.Join(", ", funcPrototypeNode.Parameters.Select(x => $"{x.Name}: {x.Type}")); // }
var externText = funcPrototypeNode.ExternSymbol != null ? $"extern \"{funcPrototypeNode.ExternSymbol}\" " : ""; //
// private static string CreateFuncPrototypeMessage(FuncPrototypeNode funcPrototypeNode)
return $""" // {
**Function** `{funcPrototypeNode.Module}::{funcPrototypeNode.Name}` // var parameterText = string.Join(", ", funcPrototypeNode.Parameters.Select(x => $"{x.NameToken.Value}: {x.Type}"));
```nub // var externText = funcPrototypeNode.ExternSymbolToken != null ? $"extern \"{funcPrototypeNode.ExternSymbolToken.Value}\" " : "";
{externText}func {funcPrototypeNode.Module}::{funcPrototypeNode.Name}({parameterText}): {funcPrototypeNode.ReturnType} //
``` // return $"""
"""; // **Function** `{funcPrototypeNode.NameToken.Value}`
} // ```nub
// {externText}func {funcPrototypeNode.NameToken.Value}({parameterText}): {funcPrototypeNode.ReturnType}
// ```
// """;
// }
} }

View File

@@ -7,7 +7,7 @@ namespace NubLang.LSP;
public class WorkspaceManager(DiagnosticsPublisher diagnosticsPublisher) public class WorkspaceManager(DiagnosticsPublisher diagnosticsPublisher)
{ {
private readonly Dictionary<string, SyntaxTree> _syntaxTrees = new(); private readonly Dictionary<string, SyntaxTree> _syntaxTrees = new();
private readonly Dictionary<string, CompilationUnit> _compilationUnits = new(); private readonly Dictionary<string, List<TopLevelNode>> _compilationUnits = new();
public void Init(string rootPath) public void Init(string rootPath)
{ {
@@ -34,6 +34,7 @@ public class WorkspaceManager(DiagnosticsPublisher diagnosticsPublisher)
var typeChecker = new TypeChecker(syntaxTree, modules); var typeChecker = new TypeChecker(syntaxTree, modules);
var result = typeChecker.Check(); var result = typeChecker.Check();
diagnosticsPublisher.Publish(fsPath, typeChecker.Diagnostics); diagnosticsPublisher.Publish(fsPath, typeChecker.Diagnostics);
_compilationUnits[fsPath] = result; _compilationUnits[fsPath] = result;
} }
} }
@@ -57,6 +58,7 @@ public class WorkspaceManager(DiagnosticsPublisher diagnosticsPublisher)
var typeChecker = new TypeChecker(syntaxTree, modules); var typeChecker = new TypeChecker(syntaxTree, modules);
var result = typeChecker.Check(); var result = typeChecker.Check();
diagnosticsPublisher.Publish(fsPath, typeChecker.Diagnostics); diagnosticsPublisher.Publish(fsPath, typeChecker.Diagnostics);
_compilationUnits[fsPath] = result; _compilationUnits[fsPath] = result;
} }
@@ -67,7 +69,7 @@ public class WorkspaceManager(DiagnosticsPublisher diagnosticsPublisher)
_compilationUnits.Remove(fsPath); _compilationUnits.Remove(fsPath);
} }
public CompilationUnit? GetCompilationUnit(DocumentUri path) public List<TopLevelNode>? GetCompilationUnit(DocumentUri path)
{ {
return _compilationUnits.GetValueOrDefault(path.GetFileSystemPath()); return _compilationUnits.GetValueOrDefault(path.GetFileSystemPath());
} }

View File

@@ -1,15 +1,12 @@
using NubLang.Syntax;
namespace NubLang.Ast; namespace NubLang.Ast;
public sealed class CompilationUnit // public sealed class CompilationUnit(IdentifierToken module, List<FuncNode> functions, List<StructNode> structTypes, Dictionary<IdentifierToken, List<NubStructType>> importedStructTypes, Dictionary<IdentifierToken, List<FuncPrototypeNode>> importedFunctions)
{ // {
public CompilationUnit(List<FuncNode> functions, List<NubStructType> importedStructTypes, List<FuncPrototypeNode> importedFunctions) // public IdentifierToken Module { get; } = module;
{ // public List<FuncNode> Functions { get; } = functions;
Functions = functions; // public List<StructNode> Structs { get; } = structTypes;
ImportedStructTypes = importedStructTypes; // public Dictionary<IdentifierToken, List<NubStructType>> ImportedStructTypes { get; } = importedStructTypes;
ImportedFunctions = importedFunctions; // public Dictionary<IdentifierToken, List<FuncPrototypeNode>> ImportedFunctions { get; } = importedFunctions;
} // }
public List<FuncNode> Functions { get; }
public List<NubStructType> ImportedStructTypes { get; }
public List<FuncPrototypeNode> ImportedFunctions { get; }
}

View File

@@ -29,17 +29,38 @@ public abstract class Node(List<Token> tokens)
} }
} }
#region Definitions public abstract class TopLevelNode(List<Token> tokens) : Node(tokens);
public abstract class DefinitionNode(List<Token> tokens, string module, string name) : Node(tokens) public class ImportNode(List<Token> tokens, IdentifierToken nameToken) : TopLevelNode(tokens)
{ {
public string Module { get; } = module; public IdentifierToken NameToken { get; } = nameToken;
public string Name { get; } = name;
public override IEnumerable<Node> Children()
{
return [];
}
} }
public class FuncParameterNode(List<Token> tokens, string name, NubType type) : Node(tokens) public class ModuleNode(List<Token> tokens, IdentifierToken nameToken) : TopLevelNode(tokens)
{ {
public string Name { get; } = name; public IdentifierToken NameToken { get; } = nameToken;
public override IEnumerable<Node> Children()
{
return [];
}
}
#region Definitions
public abstract class DefinitionNode(List<Token> tokens, IdentifierToken nameToken) : TopLevelNode(tokens)
{
public IdentifierToken NameToken { get; } = nameToken;
}
public class FuncParameterNode(List<Token> tokens, IdentifierToken nameToken, NubType type) : Node(tokens)
{
public IdentifierToken NameToken { get; } = nameToken;
public NubType Type { get; } = type; public NubType Type { get; } = type;
public override IEnumerable<Node> Children() public override IEnumerable<Node> Children()
@@ -48,11 +69,10 @@ public class FuncParameterNode(List<Token> tokens, string name, NubType type) :
} }
} }
public class FuncPrototypeNode(List<Token> tokens, string module, string name, string? externSymbol, List<FuncParameterNode> parameters, NubType returnType) : Node(tokens) public class FuncPrototypeNode(List<Token> tokens, IdentifierToken nameToken, StringLiteralToken? externSymbolToken, List<FuncParameterNode> parameters, NubType returnType) : Node(tokens)
{ {
public string Module { get; } = module; public IdentifierToken NameToken { get; } = nameToken;
public string Name { get; } = name; public StringLiteralToken? ExternSymbolToken { get; } = externSymbolToken;
public string? ExternSymbol { get; } = externSymbol;
public List<FuncParameterNode> Parameters { get; } = parameters; public List<FuncParameterNode> Parameters { get; } = parameters;
public NubType ReturnType { get; } = returnType; public NubType ReturnType { get; } = returnType;
@@ -62,7 +82,7 @@ public class FuncPrototypeNode(List<Token> tokens, string module, string name, s
} }
} }
public class FuncNode(List<Token> tokens, FuncPrototypeNode prototype, BlockNode? body) : DefinitionNode(tokens, prototype.Module, prototype.Name) public class FuncNode(List<Token> tokens, FuncPrototypeNode prototype, BlockNode? body) : DefinitionNode(tokens, prototype.NameToken)
{ {
public FuncPrototypeNode Prototype { get; } = prototype; public FuncPrototypeNode Prototype { get; } = prototype;
public BlockNode? Body { get; } = body; public BlockNode? Body { get; } = body;
@@ -77,6 +97,35 @@ public class FuncNode(List<Token> tokens, FuncPrototypeNode prototype, BlockNode
} }
} }
public class StructFieldNode(List<Token> tokens, IdentifierToken nameToken, NubType type, ExpressionNode? value) : Node(tokens)
{
public IdentifierToken NameToken { get; } = nameToken;
public NubType Type { get; } = type;
public ExpressionNode? Value { get; } = value;
public override IEnumerable<Node> Children()
{
if (Value != null)
{
yield return Value;
}
}
}
public class StructNode(List<Token> tokens, IdentifierToken name, NubStructType structType, List<StructFieldNode> fields) : DefinitionNode(tokens, name)
{
public NubStructType StructType { get; } = structType;
public List<StructFieldNode> Fields { get; } = fields;
public override IEnumerable<Node> Children()
{
foreach (var field in Fields)
{
yield return field;
}
}
}
#endregion #endregion
#region Statements #region Statements
@@ -144,9 +193,9 @@ public class IfNode(List<Token> tokens, ExpressionNode condition, BlockNode body
} }
} }
public class VariableDeclarationNode(List<Token> tokens, string name, ExpressionNode? assignment, NubType type) : StatementNode(tokens) public class VariableDeclarationNode(List<Token> tokens, IdentifierToken nameToken, ExpressionNode? assignment, NubType type) : StatementNode(tokens)
{ {
public string Name { get; } = name; public IdentifierToken NameToken { get; } = nameToken;
public ExpressionNode? Assignment { get; } = assignment; public ExpressionNode? Assignment { get; } = assignment;
public NubType Type { get; } = type; public NubType Type { get; } = type;
@@ -184,10 +233,10 @@ public class WhileNode(List<Token> tokens, ExpressionNode condition, BlockNode b
} }
} }
public class ForSliceNode(List<Token> tokens, string elementName, string? indexName, ExpressionNode target, BlockNode body) : StatementNode(tokens) public class ForSliceNode(List<Token> tokens, IdentifierToken elementNameToken, IdentifierToken? indexNameToken, ExpressionNode target, BlockNode body) : StatementNode(tokens)
{ {
public string ElementName { get; } = elementName; public IdentifierToken ElementNameToken { get; } = elementNameToken;
public string? IndexName { get; } = indexName; public IdentifierToken? IndexNameToken { get; } = indexNameToken;
public ExpressionNode Target { get; } = target; public ExpressionNode Target { get; } = target;
public BlockNode Body { get; } = body; public BlockNode Body { get; } = body;
@@ -198,10 +247,10 @@ public class ForSliceNode(List<Token> tokens, string elementName, string? indexN
} }
} }
public class ForConstArrayNode(List<Token> tokens, string elementName, string? indexName, ExpressionNode target, BlockNode body) : StatementNode(tokens) public class ForConstArrayNode(List<Token> tokens, IdentifierToken elementNameToken, IdentifierToken? indexNameToken, ExpressionNode target, BlockNode body) : StatementNode(tokens)
{ {
public string ElementName { get; } = elementName; public IdentifierToken ElementNameToken { get; } = elementNameToken;
public string? IndexName { get; } = indexName; public IdentifierToken? IndexNameToken { get; } = indexNameToken;
public ExpressionNode Target { get; } = target; public ExpressionNode Target { get; } = target;
public BlockNode Body { get; } = body; public BlockNode Body { get; } = body;
@@ -385,7 +434,7 @@ public class Float64LiteralNode(List<Token> tokens, double value) : RValueExpres
} }
} }
public class BoolLiteralNode(List<Token> tokens, NubType type, bool value) : RValueExpressionNode(tokens, type) public class BoolLiteralNode(List<Token> tokens, bool value) : RValueExpressionNode(tokens, new NubBoolType())
{ {
public bool Value { get; } = value; public bool Value { get; } = value;
@@ -434,9 +483,9 @@ public class FuncCallNode(List<Token> tokens, NubType type, ExpressionNode expre
} }
} }
public class VariableIdentifierNode(List<Token> tokens, NubType type, string name) : LValueExpressionNode(tokens, type) public class VariableIdentifierNode(List<Token> tokens, NubType type, IdentifierToken nameToken) : LValueExpressionNode(tokens, type)
{ {
public string Name { get; } = name; public IdentifierToken NameToken { get; } = nameToken;
public override IEnumerable<Node> Children() public override IEnumerable<Node> Children()
{ {
@@ -444,11 +493,11 @@ public class VariableIdentifierNode(List<Token> tokens, NubType type, string nam
} }
} }
public class FuncIdentifierNode(List<Token> tokens, NubType type, string module, string name, string? externSymbol) : RValueExpressionNode(tokens, type) public class FuncIdentifierNode(List<Token> tokens, NubType type, IdentifierToken moduleToken, IdentifierToken nameToken, StringLiteralToken? externSymbolToken) : RValueExpressionNode(tokens, type)
{ {
public string Module { get; } = module; public IdentifierToken ModuleToken { get; } = moduleToken;
public string Name { get; } = name; public IdentifierToken NameToken { get; } = nameToken;
public string? ExternSymbol { get; } = externSymbol; public StringLiteralToken? ExternSymbolToken { get; } = externSymbolToken;
public override IEnumerable<Node> Children() public override IEnumerable<Node> Children()
{ {
@@ -522,10 +571,10 @@ public class AddressOfNode(List<Token> tokens, NubType type, LValueExpressionNod
} }
} }
public class StructFieldAccessNode(List<Token> tokens, NubType type, ExpressionNode target, string field) : LValueExpressionNode(tokens, type) public class StructFieldAccessNode(List<Token> tokens, NubType type, ExpressionNode target, IdentifierToken fieldToken) : LValueExpressionNode(tokens, type)
{ {
public ExpressionNode Target { get; } = target; public ExpressionNode Target { get; } = target;
public string Field { get; } = field; public IdentifierToken FieldToken { get; } = fieldToken;
public override IEnumerable<Node> Children() public override IEnumerable<Node> Children()
{ {
@@ -533,9 +582,9 @@ public class StructFieldAccessNode(List<Token> tokens, NubType type, ExpressionN
} }
} }
public class StructInitializerNode(List<Token> tokens, NubType type, Dictionary<string, ExpressionNode> initializers) : RValueExpressionNode(tokens, type) public class StructInitializerNode(List<Token> tokens, NubType type, Dictionary<IdentifierToken, ExpressionNode> initializers) : RValueExpressionNode(tokens, type)
{ {
public Dictionary<string, ExpressionNode> Initializers { get; } = initializers; public Dictionary<IdentifierToken, ExpressionNode> Initializers { get; } = initializers;
public override IEnumerable<Node> Children() public override IEnumerable<Node> Children()
{ {
@@ -556,6 +605,16 @@ public class DereferenceNode(List<Token> tokens, NubType type, ExpressionNode ta
} }
} }
public class RefDereferenceNode(List<Token> tokens, NubType type, ExpressionNode target) : LValueExpressionNode(tokens, type)
{
public ExpressionNode Target { get; } = target;
public override IEnumerable<Node> Children()
{
yield return Target;
}
}
public class SizeNode(List<Token> tokens, NubType TargetType) : RValueExpressionNode(tokens, new NubIntType(false, 64)) public class SizeNode(List<Token> tokens, NubType TargetType) : RValueExpressionNode(tokens, new NubIntType(false, 64))
{ {
public NubType TargetType { get; } = TargetType; public NubType TargetType { get; } = TargetType;
@@ -576,10 +635,23 @@ public class CastNode(List<Token> tokens, NubType type, ExpressionNode value) :
} }
} }
public class EnumReferenceIntermediateNode(List<Token> tokens, string module, string name) : IntermediateExpression(tokens) public class RefStructInitializerNode(List<Token> tokens, NubType type, Dictionary<IdentifierToken, ExpressionNode> initializers) : RValueExpressionNode(tokens, type)
{ {
public string Module { get; } = module; public Dictionary<IdentifierToken, ExpressionNode> Initializers { get; } = initializers;
public string Name { get; } = name;
public override IEnumerable<Node> Children()
{
foreach (var initializer in Initializers)
{
yield return initializer.Value;
}
}
}
public class EnumReferenceIntermediateNode(List<Token> tokens, IdentifierToken moduleToken, IdentifierToken nameToken) : IntermediateExpression(tokens)
{
public IdentifierToken ModuleToken { get; } = moduleToken;
public IdentifierToken NameToken { get; } = nameToken;
public override IEnumerable<Node> Children() public override IEnumerable<Node> Children()
{ {

View File

@@ -57,6 +57,15 @@ public sealed class NubPointerType(NubType baseType) : NubType
public override int GetHashCode() => HashCode.Combine(typeof(NubPointerType), BaseType); public override int GetHashCode() => HashCode.Combine(typeof(NubPointerType), BaseType);
} }
public class NubRefType(NubType baseType) : NubType
{
public NubType BaseType { get; } = baseType;
public override string ToString() => "&" + BaseType;
public override bool Equals(NubType? other) => other is NubRefType;
public override int GetHashCode() => HashCode.Combine(typeof(NubRefType));
}
public class NubFuncType(List<NubType> parameters, NubType returnType) : NubType public class NubFuncType(List<NubType> parameters, NubType returnType) : NubType
{ {
public List<NubType> Parameters { get; } = parameters; public List<NubType> Parameters { get; } = parameters;
@@ -106,10 +115,10 @@ public class NubSliceType(NubType elementType) : NubType
public override int GetHashCode() => HashCode.Combine(typeof(NubSliceType), ElementType); public override int GetHashCode() => HashCode.Combine(typeof(NubSliceType), ElementType);
} }
public class NubConstArrayType(NubType elementType, long size) : NubType public class NubConstArrayType(NubType elementType, ulong size) : NubType
{ {
public NubType ElementType { get; } = elementType; public NubType ElementType { get; } = elementType;
public long Size { get; } = size; public ulong Size { get; } = size;
public override string ToString() => $"[{Size}]{ElementType}"; 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 bool Equals(NubType? other) => other is NubConstArrayType array && ElementType.Equals(array.ElementType) && Size == array.Size;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,97 @@
using NubLang.Diagnostics;
using NubLang.Syntax;
namespace NubLang.Ast;
public class TypeResolver
{
private readonly Dictionary<string, Module> _modules;
private readonly Dictionary<(string Module, string Name), NubType> _typeCache = new();
private readonly HashSet<(string Module, string Name)> _resolvingTypes = [];
public TypeResolver(Dictionary<string, Module> modules)
{
_modules = modules;
}
public NubType ResolveType(TypeSyntax type, string currentModule)
{
return type switch
{
ArrayTypeSyntax arr => new NubArrayType(ResolveType(arr.BaseType, currentModule)),
BoolTypeSyntax => new NubBoolType(),
IntTypeSyntax i => new NubIntType(i.Signed, i.Width),
FloatTypeSyntax f => new NubFloatType(f.Width),
FuncTypeSyntax func => new NubFuncType(func.Parameters.Select(x => ResolveType(x, currentModule)).ToList(), ResolveType(func.ReturnType, currentModule)),
SliceTypeSyntax slice => new NubSliceType(ResolveType(slice.BaseType, currentModule)),
ConstArrayTypeSyntax arr => new NubConstArrayType(ResolveType(arr.BaseType, currentModule), arr.Size),
PointerTypeSyntax ptr => new NubPointerType(ResolveType(ptr.BaseType, currentModule)),
RefTypeSyntax r => new NubRefType(ResolveType(r.BaseType, currentModule)),
StringTypeSyntax => new NubStringType(),
CustomTypeSyntax c => ResolveCustomType(c, currentModule),
VoidTypeSyntax => new NubVoidType(),
_ => throw new NotSupportedException($"Unknown type syntax: {type}")
};
}
private NubType ResolveCustomType(CustomTypeSyntax customType, string currentModule)
{
var module = _modules[customType.ModuleToken?.Value ?? currentModule];
var enumDef = module.Enums(true).FirstOrDefault(x => x.NameToken.Value == customType.NameToken.Value);
if (enumDef != null)
{
return enumDef.Type != null ? ResolveType(enumDef.Type, currentModule) : new NubIntType(false, 64);
}
var structDef = module.Structs(true).FirstOrDefault(x => x.NameToken.Value == customType.NameToken.Value);
if (structDef != null)
{
var key = (customType.ModuleToken?.Value ?? currentModule, customType.NameToken.Value);
if (_typeCache.TryGetValue(key, out var cachedType))
{
return cachedType;
}
if (!_resolvingTypes.Add(key))
{
var placeholder = new NubStructType(customType.ModuleToken?.Value ?? currentModule, customType.NameToken.Value, []);
_typeCache[key] = placeholder;
return placeholder;
}
try
{
var result = new NubStructType(customType.ModuleToken?.Value ?? currentModule, structDef.NameToken.Value, []);
_typeCache[key] = result;
var fields = structDef.Fields
.Select(x => new NubStructFieldType(x.NameToken.Value, ResolveType(x.Type, currentModule), x.Value != null))
.ToList();
result.Fields.AddRange(fields);
return result;
}
finally
{
_resolvingTypes.Remove(key);
}
}
throw new TypeResolverException(Diagnostic
.Error($"Type {customType.NameToken.Value} not found in module {customType.ModuleToken?.Value ?? currentModule}")
.At(customType)
.Build());
}
}
public class TypeResolverException : Exception
{
public Diagnostic Diagnostic { get; }
public TypeResolverException(Diagnostic diagnostic) : base(diagnostic.Message)
{
Diagnostic = diagnostic;
}
}

View File

@@ -0,0 +1,11 @@
namespace NubLang.Diagnostics;
public class CompileException : Exception
{
public Diagnostic Diagnostic { get; }
public CompileException(Diagnostic diagnostic) : base(diagnostic.Message)
{
Diagnostic = diagnostic;
}
}

View File

@@ -10,15 +10,16 @@ public static class CType
{ {
NubVoidType => "void" + (variableName != null ? $" {variableName}" : ""), NubVoidType => "void" + (variableName != null ? $" {variableName}" : ""),
NubBoolType => "bool" + (variableName != null ? $" {variableName}" : ""), NubBoolType => "bool" + (variableName != null ? $" {variableName}" : ""),
NubIntType intType => CreateIntType(intType, variableName), NubIntType i => CreateIntType(i, variableName),
NubFloatType floatType => CreateFloatType(floatType, variableName), NubFloatType f => CreateFloatType(f, variableName),
NubPointerType ptr => CreatePointerType(ptr, variableName), NubPointerType p => CreatePointerType(p, variableName),
NubSliceType => "struct nub_slice" + (variableName != null ? $" {variableName}" : ""), NubRefType r => CreateRefType(r, variableName),
NubStringType => "struct nub_string" + (variableName != null ? $" {variableName}" : ""), NubSliceType => "nub_slice" + (variableName != null ? $" {variableName}" : ""),
NubConstArrayType arr => CreateConstArrayType(arr, variableName, constArraysAsPointers), NubStringType => "nub_string" + (variableName != null ? $" {variableName}" : ""),
NubArrayType arr => CreateArrayType(arr, variableName), NubConstArrayType a => CreateConstArrayType(a, variableName, constArraysAsPointers),
NubFuncType fn => CreateFuncType(fn, variableName), NubArrayType a => CreateArrayType(a, variableName),
NubStructType st => $"struct {st.Module}_{st.Name}_{NameMangler.Mangle(st)}" + (variableName != null ? $" {variableName}" : ""), NubFuncType f => CreateFuncType(f, variableName),
NubStructType s => $"{s.Module}_{s.Name}_{NameMangler.Mangle(s)}" + (variableName != null ? $" {variableName}" : ""),
_ => throw new NotSupportedException($"C type generation not supported for: {type}") _ => throw new NotSupportedException($"C type generation not supported for: {type}")
}; };
} }
@@ -47,6 +48,12 @@ public static class CType
return cType + (varName != null ? $" {varName}" : ""); return cType + (varName != null ? $" {varName}" : "");
} }
private static string CreateRefType(NubRefType ptr, string? varName)
{
var baseType = Create(ptr.BaseType);
return baseType + "*" + (varName != null ? $" {varName}" : "");
}
private static string CreatePointerType(NubPointerType ptr, string? varName) private static string CreatePointerType(NubPointerType ptr, string? varName)
{ {
var baseType = Create(ptr.BaseType); var baseType = Create(ptr.BaseType);

View File

@@ -7,12 +7,14 @@ namespace NubLang.Generation;
public class Generator public class Generator
{ {
private readonly CompilationUnit _compilationUnit; private readonly List<TopLevelNode> _compilationUnit;
private readonly IndentedTextWriter _writer; private readonly IndentedTextWriter _writer;
private readonly Stack<List<DeferNode>> _deferStack = []; private readonly Stack<Scope> _scopes = [];
private int _tmpIndex; private int _tmpIndex;
public Generator(CompilationUnit compilationUnit) private Scope Scope => _scopes.Peek();
public Generator(List<TopLevelNode> compilationUnit)
{ {
_compilationUnit = compilationUnit; _compilationUnit = compilationUnit;
_writer = new IndentedTextWriter(); _writer = new IndentedTextWriter();
@@ -29,68 +31,76 @@ public class Generator
return externSymbol ?? $"{module}_{name}"; return externSymbol ?? $"{module}_{name}";
} }
private string GetModuleName()
{
return _compilationUnit.OfType<ModuleNode>().First().NameToken.Value;
}
public string Emit() public string Emit()
{ {
_writer.WriteLine(""" foreach (var structType in _compilationUnit.OfType<StructNode>())
struct nub_string
{
unsigned long long length;
char *data;
};
struct nub_slice
{
unsigned long long length;
void *data;
};
""");
foreach (var structType in _compilationUnit.ImportedStructTypes)
{ {
_writer.WriteLine(CType.Create(structType)); _writer.WriteLine($"void {CType.Create(structType.StructType)}_create({CType.Create(structType.StructType)} *self)");
_writer.WriteLine("{"); _writer.WriteLine("{");
using (_writer.Indent()) using (_writer.Indent())
{ {
foreach (var field in structType.Fields) foreach (var field in structType.Fields)
{ {
_writer.WriteLine($"{CType.Create(field.Type, field.Name, constArraysAsPointers: false)};"); if (field.Value != null)
{
var value = EmitExpression(field.Value);
_writer.WriteLine($"self->{field.NameToken.Value} = {value}");
}
} }
} }
_writer.WriteLine("};"); _writer.WriteLine("}");
_writer.WriteLine(); _writer.WriteLine();
}
// note(nub31): Forward declarations _writer.WriteLine($"void {CType.Create(structType.StructType)}_destroy({CType.Create(structType.StructType)} *self)");
foreach (var prototype in _compilationUnit.ImportedFunctions) _writer.WriteLine("{");
{ using (_writer.Indent())
EmitLine(prototype.Tokens.FirstOrDefault()); {
var parameters = prototype.Parameters.Count != 0 foreach (var field in structType.Fields)
? string.Join(", ", prototype.Parameters.Select(x => CType.Create(x.Type, x.Name))) {
: "void"; if (field.Type is NubRefType)
{
_writer.WriteLine($"rc_release(self->{field.NameToken.Value});");
}
}
}
var name = FuncName(prototype.Module, prototype.Name, prototype.ExternSymbol); _writer.WriteLine("}");
_writer.WriteLine($"{CType.Create(prototype.ReturnType, name)}({parameters});");
_writer.WriteLine(); _writer.WriteLine();
} }
// note(nub31): Normal functions // note(nub31): Normal functions
foreach (var funcNode in _compilationUnit.Functions) foreach (var funcNode in _compilationUnit.OfType<FuncNode>())
{ {
if (funcNode.Body == null) continue; if (funcNode.Body == null) continue;
EmitLine(funcNode.Tokens.FirstOrDefault()); EmitLine(funcNode.Tokens.FirstOrDefault());
var parameters = funcNode.Prototype.Parameters.Count != 0 var parameters = funcNode.Prototype.Parameters.Count != 0
? string.Join(", ", funcNode.Prototype.Parameters.Select(x => CType.Create(x.Type, x.Name))) ? string.Join(", ", funcNode.Prototype.Parameters.Select(x => CType.Create(x.Type, x.NameToken.Value)))
: "void"; : "void";
var name = FuncName(funcNode.Module, funcNode.Name, funcNode.Prototype.ExternSymbol); var name = FuncName(GetModuleName(), funcNode.NameToken.Value, funcNode.Prototype.ExternSymbolToken?.Value);
_writer.WriteLine($"{CType.Create(funcNode.Prototype.ReturnType, name)}({parameters})"); _writer.WriteLine($"{CType.Create(funcNode.Prototype.ReturnType, name)}({parameters})");
_writer.WriteLine("{"); _writer.WriteLine("{");
using (_writer.Indent()) using (_writer.Indent())
{ {
EmitBlock(funcNode.Body); using (BeginScope())
{
foreach (var parameter in funcNode.Prototype.Parameters)
{
if (parameter.Type is NubRefType)
{
Scope.Defer(() => _writer.WriteLine($"rc_release({parameter.NameToken.Value});"));
}
}
EmitBlock(funcNode.Body);
}
} }
_writer.WriteLine("}"); _writer.WriteLine("}");
@@ -112,7 +122,10 @@ public class Generator
_writer.WriteLine("{"); _writer.WriteLine("{");
using (_writer.Indent()) using (_writer.Indent())
{ {
EmitBlock(blockNode); using (BeginScope())
{
EmitBlock(blockNode);
}
} }
_writer.WriteLine("}"); _writer.WriteLine("}");
@@ -124,7 +137,7 @@ public class Generator
EmitContinue(continueNode); EmitContinue(continueNode);
break; break;
case DeferNode deferNode: case DeferNode deferNode:
EmitDefer(deferNode); Scope.Defer(() => EmitStatement(deferNode.Statement));
break; break;
case ForConstArrayNode forConstArrayNode: case ForConstArrayNode forConstArrayNode:
EmitForConstArray(forConstArrayNode); EmitForConstArray(forConstArrayNode);
@@ -164,6 +177,14 @@ public class Generator
{ {
var target = EmitExpression(assignmentNode.Target); var target = EmitExpression(assignmentNode.Target);
var value = EmitExpression(assignmentNode.Value); var value = EmitExpression(assignmentNode.Value);
if (assignmentNode.Target.Type is NubRefType)
{
_writer.WriteLine($"rc_retain({value});");
Scope.Defer(() => _writer.WriteLine($"rc_release({value});"));
_writer.WriteLine($"rc_release({target});");
}
_writer.WriteLine($"{target} = {value};"); _writer.WriteLine($"{target} = {value};");
} }
@@ -179,23 +200,21 @@ public class Generator
_writer.WriteLine("continue;"); _writer.WriteLine("continue;");
} }
private void EmitDefer(DeferNode deferNode)
{
_deferStack.Peek().Add(deferNode);
}
private void EmitForSlice(ForSliceNode forSliceNode) private void EmitForSlice(ForSliceNode forSliceNode)
{ {
var targetType = (NubSliceType)forSliceNode.Target.Type; var targetType = (NubSliceType)forSliceNode.Target.Type;
var target = EmitExpression(forSliceNode.Target); var target = EmitExpression(forSliceNode.Target);
var indexName = forSliceNode.IndexName ?? NewTmp(); var indexName = forSliceNode.IndexNameToken?.Value ?? NewTmp();
_writer.WriteLine($"for (unsigned long long {indexName} = 0; {indexName} < {target}.length; ++{indexName})"); _writer.WriteLine($"for (unsigned long long {indexName} = 0; {indexName} < {target}.length; ++{indexName})");
_writer.WriteLine("{"); _writer.WriteLine("{");
using (_writer.Indent()) using (_writer.Indent())
{ {
_writer.WriteLine($"{CType.Create(targetType.ElementType, forSliceNode.ElementName)} = (({CType.Create(targetType.ElementType)}*){target}.data)[{indexName}];"); using (BeginScope())
EmitBlock(forSliceNode.Body); {
_writer.WriteLine($"{CType.Create(targetType.ElementType, forSliceNode.ElementNameToken.Value)} = (({CType.Create(targetType.ElementType)}*){target}.data)[{indexName}];");
EmitBlock(forSliceNode.Body);
}
} }
_writer.WriteLine("}"); _writer.WriteLine("}");
@@ -205,14 +224,17 @@ public class Generator
{ {
var targetType = (NubConstArrayType)forConstArrayNode.Target.Type; var targetType = (NubConstArrayType)forConstArrayNode.Target.Type;
var target = EmitExpression(forConstArrayNode.Target); var target = EmitExpression(forConstArrayNode.Target);
var indexName = forConstArrayNode.IndexName ?? NewTmp(); var indexName = forConstArrayNode.IndexNameToken?.Value ?? NewTmp();
_writer.WriteLine($"for (unsigned long long {indexName} = 0; {indexName} < {targetType.Size}; ++{indexName})"); _writer.WriteLine($"for (unsigned long long {indexName} = 0; {indexName} < {targetType.Size}; ++{indexName})");
_writer.WriteLine("{"); _writer.WriteLine("{");
using (_writer.Indent()) using (_writer.Indent())
{ {
_writer.WriteLine($"{CType.Create(targetType.ElementType, forConstArrayNode.ElementName)} = {target}[{indexName}];"); using (BeginScope())
EmitBlock(forConstArrayNode.Body); {
_writer.WriteLine($"{CType.Create(targetType.ElementType, forConstArrayNode.ElementNameToken.Value)} = {target}[{indexName}];");
EmitBlock(forConstArrayNode.Body);
}
} }
_writer.WriteLine("}"); _writer.WriteLine("}");
@@ -225,7 +247,10 @@ public class Generator
_writer.WriteLine("{"); _writer.WriteLine("{");
using (_writer.Indent()) using (_writer.Indent())
{ {
EmitBlock(ifNode.Body); using (BeginScope())
{
EmitBlock(ifNode.Body);
}
} }
_writer.WriteLine("}"); _writer.WriteLine("}");
@@ -238,7 +263,10 @@ public class Generator
_writer.WriteLine("{"); _writer.WriteLine("{");
using (_writer.Indent()) using (_writer.Indent())
{ {
EmitBlock(elseNode); using (BeginScope())
{
EmitBlock(elseNode);
}
} }
_writer.WriteLine("}"); _writer.WriteLine("}");
@@ -250,44 +278,28 @@ public class Generator
{ {
if (returnNode.Value == null) if (returnNode.Value == null)
{ {
var blockDefers = _deferStack.Peek(); EmitScopeCleanup();
for (var i = blockDefers.Count - 1; i >= 0; i--)
{
EmitStatement(blockDefers[i].Statement);
}
_writer.WriteLine("return;"); _writer.WriteLine("return;");
} }
else else
{ {
var returnValue = EmitExpression(returnNode.Value); var returnValue = EmitExpression(returnNode.Value);
var tmp = NewTmp();
if (_deferStack.Peek().Count != 0) _writer.WriteLine($"{CType.Create(returnNode.Value.Type, tmp)} = {returnValue};");
if (returnNode.Value.Type is NubRefType)
{ {
var tmp = NewTmp(); _writer.WriteLine($"rc_retain({tmp});");
_writer.WriteLine($"{CType.Create(returnNode.Value.Type, tmp)} = {returnValue};");
var blockDefers = _deferStack.Peek();
for (var i = blockDefers.Count - 1; i >= 0; i--)
{
EmitStatement(blockDefers[i].Statement);
}
EmitLine(returnNode.Tokens.FirstOrDefault());
_writer.WriteLine($"return {tmp};");
}
else
{
EmitLine(returnNode.Tokens.FirstOrDefault());
_writer.WriteLine($"return {returnValue};");
} }
EmitScopeCleanup();
EmitLine(returnNode.Tokens.FirstOrDefault());
_writer.WriteLine($"return {tmp};");
} }
} }
private void EmitStatementFuncCall(StatementFuncCallNode statementFuncCallNode) private void EmitStatementFuncCall(StatementFuncCallNode statementFuncCallNode)
{ {
var funcCall = EmitFuncCall(statementFuncCallNode.FuncCall); EmitFuncCall(statementFuncCallNode.FuncCall);
_writer.WriteLine($"{funcCall};");
} }
private void EmitVariableDeclaration(VariableDeclarationNode variableDeclarationNode) private void EmitVariableDeclaration(VariableDeclarationNode variableDeclarationNode)
@@ -295,11 +307,18 @@ public class Generator
if (variableDeclarationNode.Assignment != null) if (variableDeclarationNode.Assignment != null)
{ {
var value = EmitExpression(variableDeclarationNode.Assignment); var value = EmitExpression(variableDeclarationNode.Assignment);
_writer.WriteLine($"{CType.Create(variableDeclarationNode.Type, variableDeclarationNode.Name)} = {value};");
if (variableDeclarationNode.Type is NubRefType)
{
_writer.WriteLine($"rc_retain({value});");
Scope.Defer(() => _writer.WriteLine($"rc_release({value});"));
}
_writer.WriteLine($"{CType.Create(variableDeclarationNode.Type, variableDeclarationNode.NameToken.Value)} = {value};");
} }
else else
{ {
_writer.WriteLine($"{CType.Create(variableDeclarationNode.Type, variableDeclarationNode.Name)};"); _writer.WriteLine($"{CType.Create(variableDeclarationNode.Type, variableDeclarationNode.NameToken.Value)};");
} }
} }
@@ -310,7 +329,10 @@ public class Generator
_writer.WriteLine("{"); _writer.WriteLine("{");
using (_writer.Indent()) using (_writer.Indent())
{ {
EmitBlock(whileNode.Body); using (BeginScope())
{
EmitBlock(whileNode.Body);
}
} }
_writer.WriteLine("}"); _writer.WriteLine("}");
@@ -337,8 +359,10 @@ public class Generator
Float64LiteralNode float64LiteralNode => EmitFloat64Literal(float64LiteralNode), Float64LiteralNode float64LiteralNode => EmitFloat64Literal(float64LiteralNode),
CastNode castNode => EmitCast(castNode), CastNode castNode => EmitCast(castNode),
FuncCallNode funcCallNode => EmitFuncCall(funcCallNode), FuncCallNode funcCallNode => EmitFuncCall(funcCallNode),
FuncIdentifierNode funcIdentifierNode => FuncName(funcIdentifierNode.Module, funcIdentifierNode.Name, funcIdentifierNode.ExternSymbol), FuncIdentifierNode funcIdentifierNode => FuncName(funcIdentifierNode.ModuleToken.Value, funcIdentifierNode.NameToken.Value, funcIdentifierNode.ExternSymbolToken?.Value),
AddressOfNode addressOfNode => EmitAddressOf(addressOfNode), AddressOfNode addressOfNode => EmitAddressOf(addressOfNode),
RefDereferenceNode refDereferenceNode => EmitRefDereference(refDereferenceNode),
RefStructInitializerNode refStructInitializerNode => EmitRefStructInitializer(refStructInitializerNode),
SizeNode sizeBuiltinNode => $"sizeof({CType.Create(sizeBuiltinNode.TargetType)})", SizeNode sizeBuiltinNode => $"sizeof({CType.Create(sizeBuiltinNode.TargetType)})",
SliceIndexAccessNode sliceIndexAccessNode => EmitSliceArrayIndexAccess(sliceIndexAccessNode), SliceIndexAccessNode sliceIndexAccessNode => EmitSliceArrayIndexAccess(sliceIndexAccessNode),
StringLiteralNode stringLiteralNode => EmitStringLiteral(stringLiteralNode), StringLiteralNode stringLiteralNode => EmitStringLiteral(stringLiteralNode),
@@ -353,7 +377,7 @@ public class Generator
U32LiteralNode u32LiteralNode => EmitU32Literal(u32LiteralNode), U32LiteralNode u32LiteralNode => EmitU32Literal(u32LiteralNode),
U64LiteralNode u64LiteralNode => EmitU64Literal(u64LiteralNode), U64LiteralNode u64LiteralNode => EmitU64Literal(u64LiteralNode),
UnaryExpressionNode unaryExpressionNode => EmitUnaryExpression(unaryExpressionNode), UnaryExpressionNode unaryExpressionNode => EmitUnaryExpression(unaryExpressionNode),
VariableIdentifierNode variableIdentifierNode => variableIdentifierNode.Name, VariableIdentifierNode variableIdentifierNode => variableIdentifierNode.NameToken.Value,
_ => throw new ArgumentOutOfRangeException(nameof(expressionNode)) _ => throw new ArgumentOutOfRangeException(nameof(expressionNode))
}; };
@@ -473,8 +497,29 @@ public class Generator
private string EmitFuncCall(FuncCallNode funcCallNode) private string EmitFuncCall(FuncCallNode funcCallNode)
{ {
var name = EmitExpression(funcCallNode.Expression); var name = EmitExpression(funcCallNode.Expression);
var parameterNames = funcCallNode.Parameters.Select(EmitExpression).ToList();
return $"{name}({string.Join(", ", parameterNames)})"; var parameterNames = new List<string>();
foreach (var parameter in funcCallNode.Parameters)
{
var result = EmitExpression(parameter);
if (parameter.Type is NubRefType)
{
_writer.WriteLine($"rc_retain({result});");
}
parameterNames.Add(result);
}
var tmp = NewTmp();
_writer.WriteLine($"{CType.Create(funcCallNode.Type)} {tmp} = {name}({string.Join(", ", parameterNames)});");
if (funcCallNode.Type is NubRefType)
{
Scope.Defer(() => _writer.WriteLine($"rc_release({tmp});"));
}
return tmp;
} }
private string EmitAddressOf(AddressOfNode addressOfNode) private string EmitAddressOf(AddressOfNode addressOfNode)
@@ -483,6 +528,33 @@ public class Generator
return $"&{value}"; return $"&{value}";
} }
private string EmitRefDereference(RefDereferenceNode refDereferenceNode)
{
var pointer = EmitExpression(refDereferenceNode.Target);
return $"*{pointer}";
}
private string EmitRefStructInitializer(RefStructInitializerNode refStructInitializerNode)
{
var type = (NubRefType)refStructInitializerNode.Type;
var structType = (NubStructType)type.BaseType;
var tmp = NewTmp();
_writer.WriteLine($"{CType.Create(type)} {tmp} = ({CType.Create(type)})rc_alloc(sizeof({CType.Create(structType)}), (void (*)(void *)){CType.Create(structType)}_destroy);");
Scope.Defer(() => _writer.WriteLine($"rc_release({tmp});"));
_writer.WriteLine($"*{tmp} = ({CType.Create(structType)}){{{0}}};");
_writer.WriteLine($"{CType.Create(structType)}_create({tmp});");
foreach (var initializer in refStructInitializerNode.Initializers)
{
var value = EmitExpression(initializer.Value);
_writer.WriteLine($"{tmp}->{initializer.Key} = {value};");
}
return tmp;
}
private string EmitSliceArrayIndexAccess(SliceIndexAccessNode sliceIndexAccessNode) private string EmitSliceArrayIndexAccess(SliceIndexAccessNode sliceIndexAccessNode)
{ {
var targetType = (NubSliceType)sliceIndexAccessNode.Target.Type; var targetType = (NubSliceType)sliceIndexAccessNode.Target.Type;
@@ -495,29 +567,30 @@ public class Generator
private string EmitStringLiteral(StringLiteralNode stringLiteralNode) private string EmitStringLiteral(StringLiteralNode stringLiteralNode)
{ {
var length = Encoding.UTF8.GetByteCount(stringLiteralNode.Value); var length = Encoding.UTF8.GetByteCount(stringLiteralNode.Value);
return $"(nub_string){{.length = {length}, .data = \"{stringLiteralNode.Value}\"}}"; return $"({CType.Create(stringLiteralNode.Type)}){{.length = {length}, .data = \"{stringLiteralNode.Value}\"}}";
} }
private string EmitStructFieldAccess(StructFieldAccessNode structFieldAccessNode) private string EmitStructFieldAccess(StructFieldAccessNode structFieldAccessNode)
{ {
var structExpr = EmitExpression(structFieldAccessNode.Target); var structExpr = EmitExpression(structFieldAccessNode.Target);
return $"{structExpr}.{structFieldAccessNode.Field}"; return $"{structExpr}.{structFieldAccessNode.FieldToken.Value}";
} }
private string EmitStructInitializer(StructInitializerNode structInitializerNode) private string EmitStructInitializer(StructInitializerNode structInitializerNode)
{ {
var initValues = new List<string>(); var structType = (NubStructType)structInitializerNode.Type;
var tmp = NewTmp();
_writer.WriteLine($"{CType.Create(structType)} {tmp} = ({CType.Create(structType)}){{0}};");
_writer.WriteLine($"{CType.Create(structType)}_create(&{tmp});");
foreach (var initializer in structInitializerNode.Initializers) foreach (var initializer in structInitializerNode.Initializers)
{ {
var value = EmitExpression(initializer.Value); var value = EmitExpression(initializer.Value);
initValues.Add($".{initializer.Key} = {value}"); _writer.WriteLine($"{tmp}.{initializer.Key} = {value};");
} }
var initString = initValues.Count == 0 return tmp;
? "0"
: string.Join(", ", initValues);
return $"({CType.Create(structInitializerNode.Type)}){{{initString}}}";
} }
private string EmitI8Literal(I8LiteralNode i8LiteralNode) private string EmitI8Literal(I8LiteralNode i8LiteralNode)
@@ -574,17 +647,45 @@ public class Generator
private void EmitBlock(BlockNode blockNode) private void EmitBlock(BlockNode blockNode)
{ {
_deferStack.Push([]);
foreach (var statementNode in blockNode.Statements) foreach (var statementNode in blockNode.Statements)
{ {
EmitStatement(statementNode); EmitStatement(statementNode);
} }
}
var blockDefers = _deferStack.Pop(); private void EmitScopeCleanup()
for (var i = blockDefers.Count - 1; i >= 0; i--) {
var deferredStack = Scope.GetDeferred();
while (deferredStack.TryPop(out var deferred))
{ {
EmitStatement(blockDefers[i].Statement); deferred.Invoke();
} }
} }
private ScopeDisposer BeginScope()
{
_scopes.Push(new Scope());
return new ScopeDisposer(this);
}
private sealed class ScopeDisposer(Generator owner) : IDisposable
{
public void Dispose()
{
owner.EmitScopeCleanup();
owner._scopes.Pop();
}
}
}
public class Scope
{
private readonly List<Action> _deferred = [];
public void Defer(Action action)
{
_deferred.Add(action);
}
public Stack<Action> GetDeferred() => new(_deferred);
} }

View File

@@ -0,0 +1,49 @@
using NubLang.Ast;
using NubLang.Syntax;
namespace NubLang.Generation;
public static class HeaderGenerator
{
private static string FuncName(string module, string name, string? externSymbol)
{
return externSymbol ?? $"{module}_{name}";
}
public static string Generate(string name, TypedModule module)
{
var writer = new IndentedTextWriter();
writer.WriteLine();
foreach (var structType in module.StructTypes)
{
writer.WriteLine("typedef struct");
writer.WriteLine("{");
using (writer.Indent())
{
foreach (var field in structType.Fields)
{
writer.WriteLine($"{CType.Create(field.Type)} {field.Name};");
}
}
writer.WriteLine($"}} {CType.Create(structType)};");
writer.WriteLine($"void {CType.Create(structType)}_create({CType.Create(structType)} *self);");
writer.WriteLine($"void {CType.Create(structType)}_destroy({CType.Create(structType)} *self);");
writer.WriteLine();
}
foreach (var prototype in module.FunctionPrototypes)
{
var parameters = prototype.Parameters.Count != 0
? string.Join(", ", prototype.Parameters.Select(x => CType.Create(x.Type, x.NameToken.Value)))
: "void";
var funcName = FuncName(name, prototype.NameToken.Value, prototype.ExternSymbolToken?.Value);
writer.WriteLine($"{CType.Create(prototype.ReturnType, funcName)}({parameters});");
}
return writer.ToString();
}
}

View File

@@ -7,19 +7,23 @@ public sealed class Module
var modules = new Dictionary<string, Module>(); var modules = new Dictionary<string, Module>();
foreach (var syntaxTree in syntaxTrees) foreach (var syntaxTree in syntaxTrees)
{ {
if (!modules.TryGetValue(syntaxTree.ModuleName, out var module)) var moduleDeclaration = syntaxTree.TopLevelSyntaxNodes.OfType<ModuleSyntax>().FirstOrDefault();
if (moduleDeclaration != null)
{ {
module = new Module(); if (!modules.TryGetValue(moduleDeclaration.NameToken.Value, out var module))
modules.Add(syntaxTree.ModuleName, module); {
} module = new Module();
modules.Add(moduleDeclaration.NameToken.Value, module);
}
module._definitions.AddRange(syntaxTree.Definitions); module._definitions.AddRange(syntaxTree.TopLevelSyntaxNodes);
}
} }
return modules; return modules;
} }
private readonly List<DefinitionSyntax> _definitions = []; private readonly List<TopLevelSyntaxNode> _definitions = [];
public List<StructSyntax> Structs(bool includePrivate) public List<StructSyntax> Structs(bool includePrivate)
{ {

View File

@@ -19,9 +19,7 @@ public sealed class Parser
_tokens = tokens; _tokens = tokens;
_tokenIndex = 0; _tokenIndex = 0;
string? moduleName = null; var topLevelSyntaxNodes = new List<TopLevelSyntaxNode>();
var imports = new List<string>();
var definitions = new List<DefinitionSyntax>();
while (HasToken) while (HasToken)
{ {
@@ -29,66 +27,34 @@ public sealed class Parser
{ {
var startIndex = _tokenIndex; var startIndex = _tokenIndex;
if (TryExpectSymbol(Symbol.Import))
{
var name = ExpectStringLiteral();
if (imports.Contains(name.Value))
{
Diagnostics.Add(Diagnostic
.Warning($"Module {name.Value} is imported twice")
.At(name)
.WithHelp($"Remove duplicate import \"{name.Value}\"")
.Build());
}
else
{
imports.Add(name.Value);
}
continue;
}
if (TryExpectSymbol(Symbol.Module))
{
if (moduleName != null)
{
throw new ParseException(Diagnostic
.Error("Module is declared more than once")
.At(CurrentToken)
.WithHelp("Remove duplicate module declaration")
.Build());
}
moduleName = ExpectStringLiteral().Value;
continue;
}
var exported = TryExpectSymbol(Symbol.Export); var exported = TryExpectSymbol(Symbol.Export);
if (TryExpectSymbol(Symbol.Extern)) if (TryExpectSymbol(Symbol.Extern))
{ {
var externSymbol = ExpectStringLiteral(); var externSymbol = ExpectStringLiteral();
ExpectSymbol(Symbol.Func); ExpectSymbol(Symbol.Func);
definitions.Add(ParseFunc(startIndex, exported, externSymbol.Value)); topLevelSyntaxNodes.Add(ParseFunc(startIndex, exported, externSymbol));
continue; continue;
} }
var keyword = ExpectSymbol(); var keyword = ExpectSymbol();
DefinitionSyntax definition = keyword.Symbol switch TopLevelSyntaxNode definition = keyword.Symbol switch
{ {
Symbol.Module => ParseModule(startIndex),
Symbol.Import => ParseImport(startIndex),
Symbol.Func => ParseFunc(startIndex, exported, null), Symbol.Func => ParseFunc(startIndex, exported, null),
Symbol.Struct => ParseStruct(startIndex, exported), Symbol.Struct => ParseStruct(startIndex, exported),
Symbol.Enum => ParseEnum(startIndex, exported), Symbol.Enum => ParseEnum(startIndex, exported),
_ => throw new ParseException(Diagnostic _ => throw new CompileException(Diagnostic
.Error($"Expected 'func', 'struct', 'enum', 'import' or 'module' but found '{keyword.Symbol}'") .Error($"Expected 'func', 'struct', 'enum', 'import' or 'module' but found '{keyword.Symbol}'")
.WithHelp("Valid top level statements are 'func', 'struct', 'enum', 'import' and 'module'") .WithHelp("Valid top level statements are 'func', 'struct', 'enum', 'import' and 'module'")
.At(keyword) .At(keyword)
.Build()) .Build())
}; };
definitions.Add(definition); topLevelSyntaxNodes.Add(definition);
} }
catch (ParseException e) catch (CompileException e)
{ {
Diagnostics.Add(e.Diagnostic); Diagnostics.Add(e.Diagnostic);
while (HasToken) while (HasToken)
@@ -103,7 +69,19 @@ public sealed class Parser
} }
} }
return new SyntaxTree(definitions, moduleName ?? "default", imports); return new SyntaxTree(topLevelSyntaxNodes);
}
private ImportSyntax ParseImport(int startIndex)
{
var name = ExpectIdentifier();
return new ImportSyntax(GetTokens(startIndex), name);
}
private ModuleSyntax ParseModule(int startIndex)
{
var name = ExpectIdentifier();
return new ModuleSyntax(GetTokens(startIndex), name);
} }
private FuncParameterSyntax ParseFuncParameter() private FuncParameterSyntax ParseFuncParameter()
@@ -113,10 +91,10 @@ public sealed class Parser
ExpectSymbol(Symbol.Colon); ExpectSymbol(Symbol.Colon);
var type = ParseType(); var type = ParseType();
return new FuncParameterSyntax(GetTokens(startIndex), name.Value, type); return new FuncParameterSyntax(GetTokens(startIndex), name, type);
} }
private FuncSyntax ParseFunc(int startIndex, bool exported, string? externSymbol) private FuncSyntax ParseFunc(int startIndex, bool exported, StringLiteralToken? externSymbol)
{ {
var name = ExpectIdentifier(); var name = ExpectIdentifier();
List<FuncParameterSyntax> parameters = []; List<FuncParameterSyntax> parameters = [];
@@ -136,7 +114,7 @@ public sealed class Parser
var returnType = TryExpectSymbol(Symbol.Colon) ? ParseType() : new VoidTypeSyntax([]); var returnType = TryExpectSymbol(Symbol.Colon) ? ParseType() : new VoidTypeSyntax([]);
var prototype = new FuncPrototypeSyntax(GetTokens(startIndex), name.Value, exported, externSymbol, parameters, returnType); var prototype = new FuncPrototypeSyntax(GetTokens(startIndex), name, exported, externSymbol, parameters, returnType);
BlockSyntax? body = null; BlockSyntax? body = null;
var bodyStartIndex = _tokenIndex; var bodyStartIndex = _tokenIndex;
@@ -160,7 +138,7 @@ public sealed class Parser
{ {
var memberStartIndex = _tokenIndex; var memberStartIndex = _tokenIndex;
var fieldName = ExpectIdentifier().Value; var fieldName = ExpectIdentifier();
ExpectSymbol(Symbol.Colon); ExpectSymbol(Symbol.Colon);
var fieldType = ParseType(); var fieldType = ParseType();
@@ -174,7 +152,7 @@ public sealed class Parser
fields.Add(new StructFieldSyntax(GetTokens(memberStartIndex), fieldName, fieldType, fieldValue)); fields.Add(new StructFieldSyntax(GetTokens(memberStartIndex), fieldName, fieldType, fieldValue));
} }
return new StructSyntax(GetTokens(startIndex), name.Value, exported, fields); return new StructSyntax(GetTokens(startIndex), name, exported, fields);
} }
private EnumSyntax ParseEnum(int startIndex, bool exported) private EnumSyntax ParseEnum(int startIndex, bool exported)
@@ -192,37 +170,29 @@ public sealed class Parser
ExpectSymbol(Symbol.OpenBrace); ExpectSymbol(Symbol.OpenBrace);
long value = -1;
while (!TryExpectSymbol(Symbol.CloseBrace)) while (!TryExpectSymbol(Symbol.CloseBrace))
{ {
var memberStartIndex = _tokenIndex; var memberStartIndex = _tokenIndex;
var fieldName = ExpectIdentifier().Value; var fieldName = ExpectIdentifier();
long fieldValue; IntLiteralToken? value = null;
if (TryExpectSymbol(Symbol.Assign)) if (TryExpectSymbol(Symbol.Assign))
{ {
if (!TryExpectIntLiteral(out var intLiteralToken)) if (!TryExpectIntLiteral(out var intLiteralToken))
{ {
throw new ParseException(Diagnostic throw new CompileException(Diagnostic
.Error("Value of enum field must be an integer literal") .Error("Value of enum field must be an integer literal")
.At(CurrentToken) .At(CurrentToken)
.Build()); .Build());
} }
fieldValue = Convert.ToInt64(intLiteralToken.Value, intLiteralToken.Base); value = intLiteralToken;
value = fieldValue;
}
else
{
fieldValue = value + 1;
value = fieldValue;
} }
fields.Add(new EnumFieldSyntax(GetTokens(memberStartIndex), fieldName, fieldValue)); fields.Add(new EnumFieldSyntax(GetTokens(memberStartIndex), fieldName, value));
} }
return new EnumSyntax(GetTokens(startIndex), name.Value, exported, type, fields); return new EnumSyntax(GetTokens(startIndex), name, exported, type, fields);
} }
private StatementSyntax ParseStatement() private StatementSyntax ParseStatement()
@@ -267,7 +237,7 @@ public sealed class Parser
private VariableDeclarationSyntax ParseVariableDeclaration(int startIndex) private VariableDeclarationSyntax ParseVariableDeclaration(int startIndex)
{ {
var name = ExpectIdentifier().Value; var name = ExpectIdentifier();
TypeSyntax? explicitType = null; TypeSyntax? explicitType = null;
if (TryExpectSymbol(Symbol.Colon)) if (TryExpectSymbol(Symbol.Colon))
@@ -334,12 +304,12 @@ public sealed class Parser
private ForSyntax ParseFor(int startIndex) private ForSyntax ParseFor(int startIndex)
{ {
var itemName = ExpectIdentifier().Value; var itemName = ExpectIdentifier();
string? indexName = null; IdentifierToken? indexName = null;
if (TryExpectSymbol(Symbol.Comma)) if (TryExpectSymbol(Symbol.Comma))
{ {
indexName = ExpectIdentifier().Value; indexName = ExpectIdentifier();
} }
ExpectSymbol(Symbol.In); ExpectSymbol(Symbol.In);
@@ -467,10 +437,10 @@ public sealed class Parser
var token = ExpectToken(); var token = ExpectToken();
var expr = token switch var expr = token switch
{ {
BoolLiteralToken boolLiteral => new BoolLiteralSyntax(GetTokens(startIndex), boolLiteral.Value), BoolLiteralToken boolLiteral => new BoolLiteralSyntax(GetTokens(startIndex), boolLiteral),
StringLiteralToken stringLiteral => new StringLiteralSyntax(GetTokens(startIndex), stringLiteral.Value), StringLiteralToken stringLiteral => new StringLiteralSyntax(GetTokens(startIndex), stringLiteral),
FloatLiteralToken floatLiteral => new FloatLiteralSyntax(GetTokens(startIndex), floatLiteral.Value), FloatLiteralToken floatLiteral => new FloatLiteralSyntax(GetTokens(startIndex), floatLiteral),
IntLiteralToken intLiteral => new IntLiteralSyntax(GetTokens(startIndex), intLiteral.Value, intLiteral.Base), IntLiteralToken intLiteral => new IntLiteralSyntax(GetTokens(startIndex), intLiteral),
IdentifierToken identifier => ParseIdentifier(startIndex, identifier), IdentifierToken identifier => ParseIdentifier(startIndex, identifier),
SymbolToken symbolToken => symbolToken.Symbol switch SymbolToken symbolToken => symbolToken.Symbol switch
{ {
@@ -481,13 +451,13 @@ public sealed class Parser
Symbol.OpenBrace => new StructInitializerSyntax(GetTokens(startIndex), null, ParseStructInitializerBody()), Symbol.OpenBrace => new StructInitializerSyntax(GetTokens(startIndex), null, ParseStructInitializerBody()),
Symbol.Struct => ParseStructInitializer(startIndex), Symbol.Struct => ParseStructInitializer(startIndex),
Symbol.At => ParseBuiltinFunction(startIndex), Symbol.At => ParseBuiltinFunction(startIndex),
_ => throw new ParseException(Diagnostic _ => throw new CompileException(Diagnostic
.Error($"Unexpected symbol '{symbolToken.Symbol}' in expression") .Error($"Unexpected symbol '{symbolToken.Symbol}' in expression")
.WithHelp("Expected '(', '-', '!', '[' or '{'") .WithHelp("Expected '(', '-', '!', '[' or '{'")
.At(symbolToken) .At(symbolToken)
.Build()) .Build())
}, },
_ => throw new ParseException(Diagnostic _ => throw new CompileException(Diagnostic
.Error($"Unexpected token '{token.GetType().Name}' in expression") .Error($"Unexpected token '{token.GetType().Name}' in expression")
.WithHelp("Expected literal, identifier, or parenthesized expression") .WithHelp("Expected literal, identifier, or parenthesized expression")
.At(token) .At(token)
@@ -518,7 +488,7 @@ public sealed class Parser
} }
default: default:
{ {
throw new ParseException(Diagnostic.Error($"Unknown builtin {name.Value}").At(name).Build()); throw new CompileException(Diagnostic.Error($"Unknown builtin {name.Value}").At(name).Build());
} }
} }
} }
@@ -528,10 +498,10 @@ public sealed class Parser
if (TryExpectSymbol(Symbol.DoubleColon)) if (TryExpectSymbol(Symbol.DoubleColon))
{ {
var name = ExpectIdentifier(); var name = ExpectIdentifier();
return new ModuleIdentifierSyntax(GetTokens(startIndex), identifier.Value, name.Value); return new ModuleIdentifierSyntax(GetTokens(startIndex), identifier, name);
} }
return new LocalIdentifierSyntax(GetTokens(startIndex), identifier.Value); return new LocalIdentifierSyntax(GetTokens(startIndex), identifier);
} }
private ExpressionSyntax ParseParenthesizedExpression() private ExpressionSyntax ParseParenthesizedExpression()
@@ -560,7 +530,7 @@ public sealed class Parser
if (TryExpectSymbol(Symbol.Period)) if (TryExpectSymbol(Symbol.Period))
{ {
var member = ExpectIdentifier().Value; var member = ExpectIdentifier();
expr = new MemberAccessSyntax(GetTokens(startIndex), expr, member); expr = new MemberAccessSyntax(GetTokens(startIndex), expr, member);
continue; continue;
} }
@@ -627,12 +597,12 @@ public sealed class Parser
return new StructInitializerSyntax(GetTokens(startIndex), type, initializers); return new StructInitializerSyntax(GetTokens(startIndex), type, initializers);
} }
private Dictionary<string, ExpressionSyntax> ParseStructInitializerBody() private Dictionary<IdentifierToken, ExpressionSyntax> ParseStructInitializerBody()
{ {
Dictionary<string, ExpressionSyntax> initializers = []; Dictionary<IdentifierToken, ExpressionSyntax> initializers = [];
while (!TryExpectSymbol(Symbol.CloseBrace)) while (!TryExpectSymbol(Symbol.CloseBrace))
{ {
var name = ExpectIdentifier().Value; var name = ExpectIdentifier();
ExpectSymbol(Symbol.Assign); ExpectSymbol(Symbol.Assign);
var value = ParseExpression(); var value = ParseExpression();
initializers.Add(name, value); initializers.Add(name, value);
@@ -658,7 +628,7 @@ public sealed class Parser
{ {
statements.Add(ParseStatement()); statements.Add(ParseStatement());
} }
catch (ParseException ex) catch (CompileException ex)
{ {
Diagnostics.Add(ex.Diagnostic); Diagnostics.Add(ex.Diagnostic);
if (HasToken) if (HasToken)
@@ -684,7 +654,7 @@ public sealed class Parser
{ {
if (size is not 8 and not 16 and not 32 and not 64) if (size is not 8 and not 16 and not 32 and not 64)
{ {
throw new ParseException(Diagnostic throw new CompileException(Diagnostic
.Error("Arbitrary uint size is not supported") .Error("Arbitrary uint size is not supported")
.WithHelp("Use u8, u16, u32 or u64") .WithHelp("Use u8, u16, u32 or u64")
.At(name) .At(name)
@@ -698,7 +668,7 @@ public sealed class Parser
{ {
if (size is not 8 and not 16 and not 32 and not 64) if (size is not 8 and not 16 and not 32 and not 64)
{ {
throw new ParseException(Diagnostic throw new CompileException(Diagnostic
.Error("Arbitrary int size is not supported") .Error("Arbitrary int size is not supported")
.WithHelp("Use i8, i16, i32 or i64") .WithHelp("Use i8, i16, i32 or i64")
.At(name) .At(name)
@@ -712,7 +682,7 @@ public sealed class Parser
{ {
if (size is not 32 and not 64) if (size is not 32 and not 64)
{ {
throw new ParseException(Diagnostic throw new CompileException(Diagnostic
.Error("Arbitrary float size is not supported") .Error("Arbitrary float size is not supported")
.WithHelp("Use f32 or f64") .WithHelp("Use f32 or f64")
.At(name) .At(name)
@@ -732,20 +702,26 @@ public sealed class Parser
return new BoolTypeSyntax(GetTokens(startIndex)); return new BoolTypeSyntax(GetTokens(startIndex));
default: default:
{ {
string? module = null; IdentifierToken? module = null;
if (TryExpectSymbol(Symbol.DoubleColon)) if (TryExpectSymbol(Symbol.DoubleColon))
{ {
var customTypeName = ExpectIdentifier(); var customTypeName = ExpectIdentifier();
module = name.Value; module = name;
name = customTypeName; name = customTypeName;
} }
return new CustomTypeSyntax(GetTokens(startIndex), module, name.Value); return new CustomTypeSyntax(GetTokens(startIndex), module, name);
} }
} }
} }
if (TryExpectSymbol(Symbol.Ampersand))
{
var baseType = ParseType();
return new RefTypeSyntax(GetTokens(startIndex), baseType);
}
if (TryExpectSymbol(Symbol.Caret)) if (TryExpectSymbol(Symbol.Caret))
{ {
var baseType = ParseType(); var baseType = ParseType();
@@ -780,7 +756,7 @@ public sealed class Parser
{ {
ExpectSymbol(Symbol.CloseBracket); ExpectSymbol(Symbol.CloseBracket);
var baseType = ParseType(); var baseType = ParseType();
return new ConstArrayTypeSyntax(GetTokens(startIndex), baseType, Convert.ToInt64(intLiteral.Value, intLiteral.Base)); return new ConstArrayTypeSyntax(GetTokens(startIndex), baseType, intLiteral.AsU64);
} }
else if (TryExpectSymbol(Symbol.QuestionMark)) else if (TryExpectSymbol(Symbol.QuestionMark))
{ {
@@ -796,7 +772,7 @@ public sealed class Parser
} }
} }
throw new ParseException(Diagnostic throw new CompileException(Diagnostic
.Error("Invalid type syntax") .Error("Invalid type syntax")
.WithHelp("Expected type name, '^' for pointer, or '[]' for array") .WithHelp("Expected type name, '^' for pointer, or '[]' for array")
.At(CurrentToken) .At(CurrentToken)
@@ -807,7 +783,7 @@ public sealed class Parser
{ {
if (!HasToken) if (!HasToken)
{ {
throw new ParseException(Diagnostic throw new CompileException(Diagnostic
.Error("Unexpected end of file") .Error("Unexpected end of file")
.WithHelp("Expected more tokens to complete the syntax") .WithHelp("Expected more tokens to complete the syntax")
.At(_tokens[^1]) .At(_tokens[^1])
@@ -824,7 +800,7 @@ public sealed class Parser
var token = ExpectToken(); var token = ExpectToken();
if (token is not SymbolToken symbol) if (token is not SymbolToken symbol)
{ {
throw new ParseException(Diagnostic throw new CompileException(Diagnostic
.Error($"Expected symbol, but found {token.GetType().Name}") .Error($"Expected symbol, but found {token.GetType().Name}")
.WithHelp("This position requires a symbol like '(', ')', '{', '}', etc.") .WithHelp("This position requires a symbol like '(', ')', '{', '}', etc.")
.At(token) .At(token)
@@ -839,7 +815,7 @@ public sealed class Parser
var token = ExpectSymbol(); var token = ExpectSymbol();
if (token.Symbol != expectedSymbol) if (token.Symbol != expectedSymbol)
{ {
throw new ParseException(Diagnostic throw new CompileException(Diagnostic
.Error($"Expected '{expectedSymbol}', but found '{token.Symbol}'") .Error($"Expected '{expectedSymbol}', but found '{token.Symbol}'")
.WithHelp($"Insert '{expectedSymbol}' here") .WithHelp($"Insert '{expectedSymbol}' here")
.At(token) .At(token)
@@ -889,7 +865,7 @@ public sealed class Parser
var token = ExpectToken(); var token = ExpectToken();
if (token is not IdentifierToken identifier) if (token is not IdentifierToken identifier)
{ {
throw new ParseException(Diagnostic throw new CompileException(Diagnostic
.Error($"Expected identifier, but found {token.GetType().Name}") .Error($"Expected identifier, but found {token.GetType().Name}")
.WithHelp("Provide a valid identifier name here") .WithHelp("Provide a valid identifier name here")
.At(token) .At(token)
@@ -917,7 +893,7 @@ public sealed class Parser
var token = ExpectToken(); var token = ExpectToken();
if (token is not StringLiteralToken identifier) if (token is not StringLiteralToken identifier)
{ {
throw new ParseException(Diagnostic throw new CompileException(Diagnostic
.Error($"Expected string literal, but found {token.GetType().Name}") .Error($"Expected string literal, but found {token.GetType().Name}")
.WithHelp("Provide a valid string literal") .WithHelp("Provide a valid string literal")
.At(token) .At(token)
@@ -938,14 +914,4 @@ public sealed class Parser
} }
} }
public record SyntaxTree(List<DefinitionSyntax> Definitions, string ModuleName, List<string> Imports); public record SyntaxTree(List<TopLevelSyntaxNode> TopLevelSyntaxNodes);
public class ParseException : Exception
{
public Diagnostic Diagnostic { get; }
public ParseException(Diagnostic diagnostic) : base(diagnostic.Message)
{
Diagnostic = diagnostic;
}
}

View File

@@ -4,21 +4,27 @@ public abstract record SyntaxNode(List<Token> Tokens);
#region Definitions #region Definitions
public abstract record DefinitionSyntax(List<Token> Tokens, string Name, bool Exported) : SyntaxNode(Tokens); public record TopLevelSyntaxNode(List<Token> Tokens) : SyntaxNode(Tokens);
public record FuncParameterSyntax(List<Token> Tokens, string Name, TypeSyntax Type) : SyntaxNode(Tokens); public record ModuleSyntax(List<Token> Tokens, IdentifierToken NameToken) : TopLevelSyntaxNode(Tokens);
public record FuncPrototypeSyntax(List<Token> Tokens, string Name, bool Exported, string? ExternSymbol, List<FuncParameterSyntax> Parameters, TypeSyntax ReturnType) : SyntaxNode(Tokens); public record ImportSyntax(List<Token> Tokens, IdentifierToken NameToken) : TopLevelSyntaxNode(Tokens);
public record FuncSyntax(List<Token> Tokens, FuncPrototypeSyntax Prototype, BlockSyntax? Body) : DefinitionSyntax(Tokens, Prototype.Name, Prototype.Exported); public abstract record DefinitionSyntax(List<Token> Tokens, IdentifierToken NameToken, bool Exported) : TopLevelSyntaxNode(Tokens);
public record StructFieldSyntax(List<Token> Tokens, string Name, TypeSyntax Type, ExpressionSyntax? Value) : SyntaxNode(Tokens); public record FuncParameterSyntax(List<Token> Tokens, IdentifierToken NameToken, TypeSyntax Type) : SyntaxNode(Tokens);
public record StructSyntax(List<Token> Tokens, string Name, bool Exported, List<StructFieldSyntax> Fields) : DefinitionSyntax(Tokens, Name, Exported); public record FuncPrototypeSyntax(List<Token> Tokens, IdentifierToken NameToken, bool Exported, StringLiteralToken? ExternSymbolToken, List<FuncParameterSyntax> Parameters, TypeSyntax ReturnType) : SyntaxNode(Tokens);
public record EnumFieldSyntax(List<Token> Tokens, string Name, long Value) : SyntaxNode(Tokens); public record FuncSyntax(List<Token> Tokens, FuncPrototypeSyntax Prototype, BlockSyntax? Body) : DefinitionSyntax(Tokens, Prototype.NameToken, Prototype.Exported);
public record EnumSyntax(List<Token> Tokens, string Name, bool Exported, TypeSyntax? Type, List<EnumFieldSyntax> Fields) : DefinitionSyntax(Tokens, Name, Exported); public record StructFieldSyntax(List<Token> Tokens, IdentifierToken NameToken, TypeSyntax Type, ExpressionSyntax? Value) : SyntaxNode(Tokens);
public record StructSyntax(List<Token> Tokens, IdentifierToken NameToken, bool Exported, List<StructFieldSyntax> Fields) : DefinitionSyntax(Tokens, NameToken, Exported);
public record EnumFieldSyntax(List<Token> Tokens, IdentifierToken NameToken, IntLiteralToken? ValueToken) : SyntaxNode(Tokens);
public record EnumSyntax(List<Token> Tokens, IdentifierToken NameToken, bool Exported, TypeSyntax? Type, List<EnumFieldSyntax> Fields) : DefinitionSyntax(Tokens, NameToken, Exported);
public enum UnaryOperatorSyntax public enum UnaryOperatorSyntax
{ {
@@ -64,7 +70,7 @@ public record AssignmentSyntax(List<Token> Tokens, ExpressionSyntax Target, Expr
public record IfSyntax(List<Token> Tokens, ExpressionSyntax Condition, BlockSyntax Body, Variant<IfSyntax, BlockSyntax>? Else) : StatementSyntax(Tokens); public record IfSyntax(List<Token> Tokens, ExpressionSyntax Condition, BlockSyntax Body, Variant<IfSyntax, BlockSyntax>? Else) : StatementSyntax(Tokens);
public record VariableDeclarationSyntax(List<Token> Tokens, string Name, TypeSyntax? ExplicitType, ExpressionSyntax? Assignment) : StatementSyntax(Tokens); public record VariableDeclarationSyntax(List<Token> Tokens, IdentifierToken NameToken, TypeSyntax? ExplicitType, ExpressionSyntax? Assignment) : StatementSyntax(Tokens);
public record ContinueSyntax(List<Token> Tokens) : StatementSyntax(Tokens); public record ContinueSyntax(List<Token> Tokens) : StatementSyntax(Tokens);
@@ -74,7 +80,7 @@ public record DeferSyntax(List<Token> Tokens, StatementSyntax Statement) : State
public record WhileSyntax(List<Token> Tokens, ExpressionSyntax Condition, BlockSyntax Body) : StatementSyntax(Tokens); public record WhileSyntax(List<Token> Tokens, ExpressionSyntax Condition, BlockSyntax Body) : StatementSyntax(Tokens);
public record ForSyntax(List<Token> Tokens, string ElementName, string? IndexName, ExpressionSyntax Target, BlockSyntax Body) : StatementSyntax(Tokens); public record ForSyntax(List<Token> Tokens, IdentifierToken ElementNameToken, IdentifierToken? IndexNameToken, ExpressionSyntax Target, BlockSyntax Body) : StatementSyntax(Tokens);
#endregion #endregion
@@ -88,9 +94,9 @@ public record UnaryExpressionSyntax(List<Token> Tokens, UnaryOperatorSyntax Oper
public record FuncCallSyntax(List<Token> Tokens, ExpressionSyntax Expression, List<ExpressionSyntax> Parameters) : ExpressionSyntax(Tokens); public record FuncCallSyntax(List<Token> Tokens, ExpressionSyntax Expression, List<ExpressionSyntax> Parameters) : ExpressionSyntax(Tokens);
public record LocalIdentifierSyntax(List<Token> Tokens, string Name) : ExpressionSyntax(Tokens); public record LocalIdentifierSyntax(List<Token> Tokens, IdentifierToken NameToken) : ExpressionSyntax(Tokens);
public record ModuleIdentifierSyntax(List<Token> Tokens, string Module, string Name) : ExpressionSyntax(Tokens); public record ModuleIdentifierSyntax(List<Token> Tokens, IdentifierToken ModuleToken, IdentifierToken NameToken) : ExpressionSyntax(Tokens);
public record ArrayInitializerSyntax(List<Token> Tokens, List<ExpressionSyntax> Values) : ExpressionSyntax(Tokens); public record ArrayInitializerSyntax(List<Token> Tokens, List<ExpressionSyntax> Values) : ExpressionSyntax(Tokens);
@@ -98,17 +104,17 @@ public record ArrayIndexAccessSyntax(List<Token> Tokens, ExpressionSyntax Target
public record AddressOfSyntax(List<Token> Tokens, ExpressionSyntax Target) : ExpressionSyntax(Tokens); public record AddressOfSyntax(List<Token> Tokens, ExpressionSyntax Target) : ExpressionSyntax(Tokens);
public record IntLiteralSyntax(List<Token> Tokens, string Value, int Base) : ExpressionSyntax(Tokens); public record IntLiteralSyntax(List<Token> Tokens, IntLiteralToken Token) : ExpressionSyntax(Tokens);
public record StringLiteralSyntax(List<Token> Tokens, string Value) : ExpressionSyntax(Tokens); public record StringLiteralSyntax(List<Token> Tokens, StringLiteralToken Token) : ExpressionSyntax(Tokens);
public record BoolLiteralSyntax(List<Token> Tokens, bool Value) : ExpressionSyntax(Tokens); public record BoolLiteralSyntax(List<Token> Tokens, BoolLiteralToken Token) : ExpressionSyntax(Tokens);
public record FloatLiteralSyntax(List<Token> Tokens, string Value) : ExpressionSyntax(Tokens); public record FloatLiteralSyntax(List<Token> Tokens, FloatLiteralToken Token) : ExpressionSyntax(Tokens);
public record MemberAccessSyntax(List<Token> Tokens, ExpressionSyntax Target, string Member) : ExpressionSyntax(Tokens); public record MemberAccessSyntax(List<Token> Tokens, ExpressionSyntax Target, IdentifierToken MemberToken) : ExpressionSyntax(Tokens);
public record StructInitializerSyntax(List<Token> Tokens, TypeSyntax? StructType, Dictionary<string, ExpressionSyntax> Initializers) : ExpressionSyntax(Tokens); public record StructInitializerSyntax(List<Token> Tokens, TypeSyntax? StructType, Dictionary<IdentifierToken, ExpressionSyntax> Initializers) : ExpressionSyntax(Tokens);
public record DereferenceSyntax(List<Token> Tokens, ExpressionSyntax Target) : ExpressionSyntax(Tokens); public record DereferenceSyntax(List<Token> Tokens, ExpressionSyntax Target) : ExpressionSyntax(Tokens);
@@ -140,8 +146,10 @@ public record SliceTypeSyntax(List<Token> Tokens, TypeSyntax BaseType) : TypeSyn
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, long Size) : TypeSyntax(Tokens); public record ConstArrayTypeSyntax(List<Token> Tokens, TypeSyntax BaseType, ulong Size) : TypeSyntax(Tokens);
public record CustomTypeSyntax(List<Token> Tokens, string? Module, string Name) : TypeSyntax(Tokens); public record CustomTypeSyntax(List<Token> Tokens, IdentifierToken? ModuleToken, IdentifierToken NameToken) : TypeSyntax(Tokens);
public record RefTypeSyntax(List<Token> Tokens, TypeSyntax BaseType) : TypeSyntax(Tokens);
#endregion #endregion

View File

@@ -2,8 +2,68 @@
namespace NubLang.Syntax; namespace NubLang.Syntax;
public abstract record Token(SourceSpan Span);
public record IdentifierToken(SourceSpan Span, string Value) : Token(Span)
{
public override string ToString()
{
return Value;
}
}
public record IntLiteralToken(SourceSpan Span, string Value, int Base) : Token(Span)
{
public ulong AsU64 => Convert.ToUInt64(Value, Base);
public long AsI64 => Convert.ToInt64(Value, Base);
public uint AsU32 => Convert.ToUInt32(Value, Base);
public int AsI32 => Convert.ToInt32(Value, Base);
public ushort AsU16 => Convert.ToUInt16(Value, Base);
public short AsI16 => Convert.ToInt16(Value, Base);
public byte AsU8 => Convert.ToByte(Value, Base);
public sbyte AsI8 => Convert.ToSByte(Value, Base);
public float AsF32 => Convert.ToSingle(AsI32);
public double AsF64 => Convert.ToDouble(AsI64);
public override string ToString()
{
return Value;
}
}
public record StringLiteralToken(SourceSpan Span, string Value) : Token(Span)
{
public override string ToString()
{
return $"\"{Value}\"";
}
}
public record BoolLiteralToken(SourceSpan Span, bool Value) : Token(Span)
{
public override string ToString()
{
return Value ? "true" : "false";
}
}
public record FloatLiteralToken(SourceSpan Span, string Value) : Token(Span)
{
public float AsF32 => Convert.ToSingle(Value);
public double AsF64 => Convert.ToDouble(Value);
public override string ToString()
{
return Value;
}
}
public enum Symbol public enum Symbol
{ {
// Default
None,
// Control // Control
If, If,
Else, Else,
@@ -62,16 +122,63 @@ public enum Symbol
QuestionMark, QuestionMark,
} }
public abstract record Token(SourceSpan Span); public record SymbolToken(SourceSpan Span, Symbol Symbol) : Token(Span)
{
public record IdentifierToken(SourceSpan Span, string Value) : Token(Span); public override string ToString()
{
public record IntLiteralToken(SourceSpan Span, string Value, int Base) : Token(Span); return Symbol switch
{
public record StringLiteralToken(SourceSpan Span, string Value) : Token(Span); Symbol.Func => "func",
Symbol.If => "if",
public record BoolLiteralToken(SourceSpan Span, bool Value) : Token(Span); Symbol.Else => "else",
Symbol.While => "while",
public record FloatLiteralToken(SourceSpan Span, string Value) : Token(Span); Symbol.For => "for",
Symbol.In => "in",
public record SymbolToken(SourceSpan Span, Symbol Symbol) : Token(Span); Symbol.Break => "break",
Symbol.Continue => "continue",
Symbol.Return => "return",
Symbol.Struct => "struct",
Symbol.Let => "let",
Symbol.Extern => "extern",
Symbol.Module => "module",
Symbol.Export => "export",
Symbol.Import => "import",
Symbol.Defer => "defer",
Symbol.Enum => "enum",
Symbol.Equal => "==",
Symbol.NotEqual => "!=",
Symbol.LessThanOrEqual => "<=",
Symbol.GreaterThanOrEqual => ">=",
Symbol.LeftShift => "<<",
Symbol.RightShift => ">>",
Symbol.And => "&&",
Symbol.Or => "||",
Symbol.DoubleColon => "::",
Symbol.Colon => ":",
Symbol.OpenParen => "(",
Symbol.CloseParen => ")",
Symbol.OpenBrace => "{",
Symbol.CloseBrace => "}",
Symbol.OpenBracket => "[",
Symbol.CloseBracket => "]",
Symbol.Comma => ",",
Symbol.Period => ".",
Symbol.Assign => "=",
Symbol.LessThan => "<",
Symbol.GreaterThan => ">",
Symbol.Plus => "+",
Symbol.Minus => "-",
Symbol.Star => "*",
Symbol.ForwardSlash => "/",
Symbol.Bang => "!",
Symbol.Caret => "^",
Symbol.Ampersand => "&",
Symbol.Semi => ";",
Symbol.Percent => "%",
Symbol.Pipe => "|",
Symbol.At => "@",
Symbol.QuestionMark => "?",
_ => "none",
};
}
}

View File

@@ -4,72 +4,9 @@ namespace NubLang.Syntax;
public sealed class Tokenizer public sealed class Tokenizer
{ {
private static readonly Dictionary<string, Symbol> Keywords = new()
{
["func"] = Symbol.Func,
["if"] = Symbol.If,
["else"] = Symbol.Else,
["while"] = Symbol.While,
["for"] = Symbol.For,
["in"] = Symbol.In,
["break"] = Symbol.Break,
["continue"] = Symbol.Continue,
["return"] = Symbol.Return,
["struct"] = Symbol.Struct,
["let"] = Symbol.Let,
["extern"] = Symbol.Extern,
["module"] = Symbol.Module,
["export"] = Symbol.Export,
["import"] = Symbol.Import,
["defer"] = Symbol.Defer,
["enum"] = Symbol.Enum,
};
private static readonly Dictionary<char[], Symbol> Symbols = new()
{
[['=', '=']] = Symbol.Equal,
[['!', '=']] = Symbol.NotEqual,
[['<', '=']] = Symbol.LessThanOrEqual,
[['>', '=']] = Symbol.GreaterThanOrEqual,
[['<', '<']] = Symbol.LeftShift,
[['>', '>']] = Symbol.RightShift,
[['&', '&']] = Symbol.And,
[['|', '|']] = Symbol.Or,
[[':', ':']] = Symbol.DoubleColon,
[[':']] = Symbol.Colon,
[['(']] = Symbol.OpenParen,
[[')']] = Symbol.CloseParen,
[['{']] = Symbol.OpenBrace,
[['}']] = Symbol.CloseBrace,
[['[']] = Symbol.OpenBracket,
[[']']] = Symbol.CloseBracket,
[[',']] = Symbol.Comma,
[['.']] = Symbol.Period,
[['=']] = Symbol.Assign,
[['<']] = Symbol.LessThan,
[['>']] = Symbol.GreaterThan,
[['+']] = Symbol.Plus,
[['-']] = Symbol.Minus,
[['*']] = Symbol.Star,
[['/']] = Symbol.ForwardSlash,
[['!']] = Symbol.Bang,
[['^']] = Symbol.Caret,
[['&']] = Symbol.Ampersand,
[[';']] = Symbol.Semi,
[['%']] = Symbol.Percent,
[['|']] = Symbol.Pipe,
[['@']] = Symbol.At,
[['?']] = Symbol.QuestionMark,
};
private static readonly (char[] Pattern, Symbol Symbol)[] OrderedSymbols = Symbols
.OrderByDescending(kvp => kvp.Key.Length)
.Select(kvp => (kvp.Key, kvp.Value))
.ToArray();
private readonly string _fileName; private readonly string _fileName;
private readonly string _content; private readonly string _content;
private int _index = 0; private int _index;
private int _line = 1; private int _line = 1;
private int _column = 1; private int _column = 1;
@@ -79,8 +16,8 @@ public sealed class Tokenizer
_content = content; _content = content;
} }
public List<Diagnostic> Diagnostics { get; } = []; public List<Diagnostic> Diagnostics { get; } = new(16);
public List<Token> Tokens { get; } = []; public List<Token> Tokens { get; } = new(256);
public void Tokenize() public void Tokenize()
{ {
@@ -90,17 +27,17 @@ public sealed class Tokenizer
_line = 1; _line = 1;
_column = 1; _column = 1;
while (Peek().HasValue) while (_index < _content.Length)
{ {
try try
{ {
var current = Peek()!.Value; var current = _content[_index];
if (char.IsWhiteSpace(current)) if (char.IsWhiteSpace(current))
{ {
if (current is '\n') if (current == '\n')
{ {
_line += 1; _line += 1;
// note(nub31): Next increments the column, so 0 is correct here
_column = 0; _column = 0;
} }
@@ -108,10 +45,10 @@ public sealed class Tokenizer
continue; continue;
} }
if (current == '/' && Peek(1) == '/') if (current == '/' && _index + 1 < _content.Length && _content[_index + 1] == '/')
{ {
// note(nub31): Keep newline so next iteration increments the line counter Next(2);
while (Peek() is not '\n') while (_index < _content.Length && _content[_index] != '\n')
{ {
Next(); Next();
} }
@@ -121,7 +58,7 @@ public sealed class Tokenizer
Tokens.Add(ParseToken(current, _line, _column)); Tokens.Add(ParseToken(current, _line, _column));
} }
catch (TokenizerException e) catch (CompileException e)
{ {
Diagnostics.Add(e.Diagnostic); Diagnostics.Add(e.Diagnostic);
Next(); Next();
@@ -131,171 +68,301 @@ public sealed class Tokenizer
private Token ParseToken(char current, int lineStart, int columnStart) private Token ParseToken(char current, int lineStart, int columnStart)
{ {
if (char.IsLetter(current) || current == '_') // Numbers
{
var buffer = string.Empty;
while (Peek() != null && (char.IsLetterOrDigit(Peek()!.Value) || Peek() == '_'))
{
buffer += Peek();
Next();
}
if (Keywords.TryGetValue(buffer, out var keywordSymbol))
{
return new SymbolToken(CreateSpan(lineStart, columnStart), keywordSymbol);
}
if (buffer is "true" or "false")
{
return new BoolLiteralToken(CreateSpan(lineStart, columnStart), Convert.ToBoolean(buffer));
}
return new IdentifierToken(CreateSpan(lineStart, columnStart), buffer);
}
if (char.IsDigit(current)) if (char.IsDigit(current))
{ {
var buffer = string.Empty; return ParseNumber(lineStart, columnStart);
}
if (current == '0' && Peek(1) is 'x') // String literals
if (current == '"')
{
return ParseString(lineStart, columnStart);
}
// Try keywords and symbols by length (longest first)
for (var i = 8; i >= 1; i--)
{
if (TryMatchSymbol(i, lineStart, columnStart, out var token))
{ {
buffer += "0x"; return token;
Next(); }
Next(); }
while (Peek() != null && Uri.IsHexDigit(Peek()!.Value))
{
buffer += Peek()!.Value;
Next();
}
if (buffer.Length <= 2) // Identifiers
if (char.IsLetter(current) || current == '_')
{
return ParseIdentifier(lineStart, columnStart);
}
throw new CompileException(Diagnostic.Error($"Unknown token '{current}'").Build());
}
private Token ParseNumber(int lineStart, int columnStart)
{
var start = _index;
var current = _content[_index];
// Hex literal
if (current == '0' && _index + 1 < _content.Length && _content[_index + 1] == 'x')
{
Next(2);
var digitStart = _index;
while (_index < _content.Length && Uri.IsHexDigit(_content[_index]))
{
Next();
}
if (_index == digitStart)
{
throw new CompileException(Diagnostic
.Error("Invalid hex literal, no digits found")
.At(_fileName, _line, _column)
.Build());
}
return new IntLiteralToken(
CreateSpan(lineStart, columnStart),
_content.Substring(start, _index - start),
16);
}
// Binary literal
if (current == '0' && _index + 1 < _content.Length && _content[_index + 1] == 'b')
{
Next(2);
var digitStart = _index;
while (_index < _content.Length && (_content[_index] == '0' || _content[_index] == '1'))
{
Next();
}
if (_index == digitStart)
{
throw new CompileException(Diagnostic
.Error("Invalid binary literal, no digits found")
.At(_fileName, _line, _column)
.Build());
}
return new IntLiteralToken(
CreateSpan(lineStart, columnStart),
_content.Substring(start, _index - start),
2);
}
// Decimal or float
var isFloat = false;
while (_index < _content.Length)
{
var next = _content[_index];
if (next == '.')
{
if (isFloat)
{ {
throw new TokenizerException(Diagnostic throw new CompileException(Diagnostic
.Error("Invalid hex literal, no digits found") .Error("More than one period found in float literal")
.At(_fileName, _line, _column) .At(_fileName, _line, _column)
.Build()); .Build());
} }
return new IntLiteralToken(CreateSpan(lineStart, columnStart), buffer, 16); isFloat = true;
}
if (current == '0' && Peek(1) is 'b')
{
buffer += "0b";
Next(); Next();
}
else if (char.IsDigit(next))
{
Next(); Next();
while (Peek() != null && (Peek() == '0' || Peek() == '1'))
{
buffer += Peek()!.Value;
Next();
}
if (buffer.Length <= 2)
{
throw new TokenizerException(Diagnostic
.Error("Invalid binary literal, no digits found")
.At(_fileName, _line, _column)
.Build());
}
return new IntLiteralToken(CreateSpan(lineStart, columnStart), buffer, 2);
}
var isFloat = false;
while (Peek() != null)
{
var next = Peek()!.Value;
if (next == '.')
{
if (isFloat)
{
throw new TokenizerException(Diagnostic
.Error("More than one period found in float literal")
.At(_fileName, _line, _column)
.Build());
}
isFloat = true;
buffer += next;
Next();
}
else if (char.IsDigit(next))
{
buffer += next;
Next();
}
else
{
break;
}
}
if (isFloat)
{
return new FloatLiteralToken(CreateSpan(lineStart, columnStart), buffer);
} }
else else
{ {
return new IntLiteralToken(CreateSpan(lineStart, columnStart), buffer, 10); break;
} }
} }
if (current == '"') var buffer = _content.Substring(start, _index - start);
return isFloat
? new FloatLiteralToken(CreateSpan(lineStart, columnStart), buffer)
: new IntLiteralToken(CreateSpan(lineStart, columnStart), buffer, 10);
}
private StringLiteralToken ParseString(int lineStart, int columnStart)
{
Next(); // Skip opening quote
var start = _index;
while (true)
{ {
Next(); if (_index >= _content.Length)
var buffer = string.Empty;
while (true)
{ {
var next = Peek(); throw new CompileException(Diagnostic
if (!next.HasValue) .Error("Unclosed string literal")
{ .At(_fileName, _line, _column)
throw new TokenizerException(Diagnostic .Build());
.Error("Unclosed string literal") }
.At(_fileName, _line, _column)
.Build());
}
if (next is '\n') var next = _content[_index];
{
_line += 1;
break;
}
if (next is '"') if (next == '\n')
{ {
Next(); throw new CompileException(Diagnostic
break; .Error("Unclosed string literal (newline found)")
} .At(_fileName, _line, _column)
.Build());
}
buffer += next; if (next == '"')
{
var buffer = _content.Substring(start, _index - start);
Next();
return new StringLiteralToken(CreateSpan(lineStart, columnStart), buffer);
}
Next();
}
}
private bool TryMatchSymbol(int length, int lineStart, int columnStart, out Token token)
{
token = null!;
if (_index + length > _content.Length)
{
return false;
}
var span = _content.AsSpan(_index, length);
var symbol = length switch
{
8 => span switch
{
"continue" => Symbol.Continue,
_ => Symbol.None
},
6 => span switch
{
"return" => Symbol.Return,
"struct" => Symbol.Struct,
"extern" => Symbol.Extern,
"module" => Symbol.Module,
"export" => Symbol.Export,
"import" => Symbol.Import,
_ => Symbol.None
},
5 => span switch
{
"break" => Symbol.Break,
"while" => Symbol.While,
"defer" => Symbol.Defer,
_ => Symbol.None
},
4 => span switch
{
"func" => Symbol.Func,
"else" => Symbol.Else,
"enum" => Symbol.Enum,
_ => Symbol.None
},
3 => span switch
{
"for" => Symbol.For,
"let" => Symbol.Let,
_ => Symbol.None
},
2 => span switch
{
"if" => Symbol.If,
"in" => Symbol.In,
"==" => Symbol.Equal,
"!=" => Symbol.NotEqual,
"<=" => Symbol.LessThanOrEqual,
">=" => Symbol.GreaterThanOrEqual,
"<<" => Symbol.LeftShift,
">>" => Symbol.RightShift,
"&&" => Symbol.And,
"||" => Symbol.Or,
"::" => Symbol.DoubleColon,
_ => Symbol.None
},
1 => span[0] switch
{
':' => Symbol.Colon,
'(' => Symbol.OpenParen,
')' => Symbol.CloseParen,
'{' => Symbol.OpenBrace,
'}' => Symbol.CloseBrace,
'[' => Symbol.OpenBracket,
']' => Symbol.CloseBracket,
',' => Symbol.Comma,
'.' => Symbol.Period,
'=' => Symbol.Assign,
'<' => Symbol.LessThan,
'>' => Symbol.GreaterThan,
'+' => Symbol.Plus,
'-' => Symbol.Minus,
'*' => Symbol.Star,
'/' => Symbol.ForwardSlash,
'!' => Symbol.Bang,
'^' => Symbol.Caret,
'&' => Symbol.Ampersand,
';' => Symbol.Semi,
'%' => Symbol.Percent,
'|' => Symbol.Pipe,
'@' => Symbol.At,
'?' => Symbol.QuestionMark,
_ => Symbol.None
},
_ => Symbol.None
};
if (symbol != Symbol.None)
{
var isAlphaKeyword = char.IsLetter(span[0]);
if (isAlphaKeyword)
{
var nextIdx = _index + length;
if (nextIdx < _content.Length)
{
var nextChar = _content[nextIdx];
if (char.IsLetterOrDigit(nextChar) || nextChar == '_')
{
return false;
}
}
}
Next(length);
token = new SymbolToken(CreateSpan(lineStart, columnStart), symbol);
return true;
}
return false;
}
private IdentifierToken ParseIdentifier(int lineStart, int columnStart)
{
var start = _index;
while (_index < _content.Length)
{
var ch = _content[_index];
if (char.IsLetterOrDigit(ch) || ch == '_')
{
Next(); Next();
} }
else
return new StringLiteralToken(CreateSpan(lineStart, columnStart), buffer);
}
foreach (var (pattern, symbol) in OrderedSymbols)
{
for (var i = 0; i < pattern.Length; i++)
{ {
var c = Peek(i); break;
if (!c.HasValue || c.Value != pattern[i]) break;
if (i == pattern.Length - 1)
{
for (var j = 0; j <= i; j++)
{
Next();
}
return new SymbolToken(CreateSpan(lineStart, columnStart), symbol);
}
} }
} }
throw new TokenizerException(Diagnostic.Error($"Unknown token '{current}'").Build()); return new IdentifierToken(
CreateSpan(lineStart, columnStart),
_content.Substring(start, _index - start));
} }
private SourceSpan CreateSpan(int lineStart, int columnStart) private SourceSpan CreateSpan(int lineStart, int columnStart)
@@ -303,29 +370,9 @@ public sealed class Tokenizer
return new SourceSpan(_fileName, new SourceLocation(lineStart, columnStart), new SourceLocation(_line, _column)); return new SourceSpan(_fileName, new SourceLocation(lineStart, columnStart), new SourceLocation(_line, _column));
} }
private char? Peek(int offset = 0) private void Next(int count = 1)
{ {
if (_index + offset < _content.Length) _index += count;
{ _column += count;
return _content[_index + offset];
}
return null;
}
private void Next()
{
_index += 1;
_column += 1;
}
}
public class TokenizerException : Exception
{
public Diagnostic Diagnostic { get; }
public TokenizerException(Diagnostic diagnostic) : base(diagnostic.Message)
{
Diagnostic = diagnostic;
} }
} }

View File

@@ -0,0 +1,50 @@
using NubLang.Ast;
namespace NubLang.Syntax;
public sealed class TypedModule
{
public static TypedModule FromModule(string name, Module module, Dictionary<string, Module> modules)
{
var typeResolver = new TypeResolver(modules);
var functionPrototypes = new List<FuncPrototypeNode>();
foreach (var funcSyntax in module.Functions(true))
{
var parameters = new List<FuncParameterNode>();
foreach (var parameter in funcSyntax.Prototype.Parameters)
{
parameters.Add(new FuncParameterNode(parameter.Tokens, parameter.NameToken, typeResolver.ResolveType(parameter.Type, name)));
}
var returnType = typeResolver.ResolveType(funcSyntax.Prototype.ReturnType, name);
functionPrototypes.Add(new FuncPrototypeNode(funcSyntax.Tokens, funcSyntax.Prototype.NameToken, funcSyntax.Prototype.ExternSymbolToken, parameters, returnType));
}
var structTypes = new List<NubStructType>();
foreach (var structSyntax in module.Structs(true))
{
var fields = new List<NubStructFieldType>();
foreach (var field in structSyntax.Fields)
{
fields.Add(new NubStructFieldType(field.NameToken.Value, typeResolver.ResolveType(field.Type, name), field.Value != null));
}
structTypes.Add(new NubStructType(name, structSyntax.NameToken.Value, fields));
}
return new TypedModule(functionPrototypes, structTypes);
}
public TypedModule(List<FuncPrototypeNode> functionPrototypes, List<NubStructType> structTypes)
{
FunctionPrototypes = functionPrototypes;
StructTypes = structTypes;
}
public List<FuncPrototypeNode> FunctionPrototypes { get; set; }
public List<NubStructType> StructTypes { get; set; }
}

31
compiler/NubLang/Utils.cs Normal file
View File

@@ -0,0 +1,31 @@
namespace NubLang;
public static class Utils
{
public static int LevenshteinDistance(string a, string b)
{
if (a == b) return 0;
if (a.Length == 0) return b.Length;
if (b.Length == 0) return a.Length;
var costs = new int[b.Length + 1];
for (int j = 0; j <= b.Length; j++) costs[j] = j;
for (int i = 1; i <= a.Length; i++)
{
costs[0] = i;
int prevCost = i - 1;
for (int j = 1; j <= b.Length; j++)
{
int currentCost = costs[j];
costs[j] = Math.Min(
Math.Min(costs[j - 1] + 1, costs[j] + 1),
prevCost + (a[i - 1] == b[j - 1] ? 0 : 1)
);
prevCost = currentCost;
}
}
return costs[b.Length];
}
}

View File

@@ -1,24 +1,9 @@
module "main" module main
extern "puts" func puts(text: cstring) extern "puts" func puts(text: ^i8)
struct X extern "main" func main(argc: i64, argv: [?]^i8): i64
{ {
points: []i32 puts("Hello, World!")
}
extern "main" func main(argc: i64, argv: [?]cstring): i64
{
let f: []cstring = ["1", "2", "3"]
puts(f[0])
puts(f[1])
puts(f[2])
for num in f
{
puts(num)
}
return 0 return 0
} }

6
examples/playgroud/build.sh Executable file
View File

@@ -0,0 +1,6 @@
#!/bin/bash
set -euo pipefail
obj=$(nubc main.nub)
clang $obj ../../runtime/.build/runtime.o -o .build/out

View File

@@ -0,0 +1,45 @@
module main
extern "puts" func puts(text: ^i8)
struct Name
{
first: ^i8
last: ^i8
}
struct Human
{
age: u64
name: &Name
}
extern "main" func main(argc: i64, argv: [?]^i8): i64
{
let x: &Human = {
age = 23
name = {
first = "oliver"
last = "stene"
}
}
let z: Human = {
age = 23
name = {
first = "oliver"
last = "stene"
}
}
test(x)
let y = x
return 0
}
func test(x: &Human): &Human
{
return x
}

View File

@@ -1,4 +1,4 @@
module "raylib" module raylib
export struct Vector2 export struct Vector2
{ {

View File

@@ -1,190 +0,0 @@
module "raymath"
export struct Vector2
{
x: f32
y: f32
}
export struct Vector3
{
x: f32
y: f32
z: f32
}
export struct Vector4
{
x: f32
y: f32
z: f32
w: f32
}
export struct Matrix
{
m0: f32
m4: f32
m8: f32
m12: f32
m1: f32
m5: f32
m9: f32
m13: f32
m2: f32
m6: f32
m10: f32
m14: f32
m3: f32
m7: f32
m11: f32
m15: f32
}
export struct float3
{
v: [3]f32
}
export struct float16
{
v: [16]f32
}
export extern "Clamp" func Clamp(value: f32, min: f32, max: f32): f32
export extern "Lerp" func Lerp(start: f32, end: f32, amount: f32): f32
export extern "Normalize" func Normalize(value: f32, start: f32, end: f32): f32
export extern "Remap" func Remap(value: f32, inputStart: f32, inputEnd: f32, outputStart: f32, outputEnd: f32): f32
export extern "Wrap" func Wrap(value: f32, min: f32, max: f32): f32
export extern "FloatEquals" func FloatEquals(x: f32, y: f32): i32
export extern "Vector2Zero" func Vector2Zero(): Vector2
export extern "Vector2One" func Vector2One(): Vector2
export extern "Vector2Add" func Vector2Add(v1: Vector2, v2: Vector2): Vector2
export extern "Vector2AddValue" func Vector2AddValue(v: Vector2, add: f32): Vector2
export extern "Vector2Subtract" func Vector2Subtract(v1: Vector2, v2: Vector2): Vector2
export extern "Vector2SubtractValue" func Vector2SubtractValue(v: Vector2, sub: f32): Vector2
export extern "Vector2Length" func Vector2Length(v: Vector2): f32
export extern "Vector2LengthSqr" func Vector2LengthSqr(v: Vector2): f32
export extern "Vector2DotProduct" func Vector2DotProduct(v1: Vector2, v2: Vector2): f32
export extern "Vector2Distance" func Vector2Distance(v1: Vector2, v2: Vector2): f32
export extern "Vector2DistanceSqr" func Vector2DistanceSqr(v1: Vector2, v2: Vector2): f32
export extern "Vector2Angle" func Vector2Angle(v1: Vector2, v2: Vector2): f32
export extern "Vector2LineAngle" func Vector2LineAngle(start: Vector2, end: Vector2): f32
export extern "Vector2Scale" func Vector2Scale(v: Vector2, scale: f32): Vector2
export extern "Vector2Multiply" func Vector2Multiply(v1: Vector2, v2: Vector2): Vector2
export extern "Vector2Negate" func Vector2Negate(v: Vector2): Vector2
export extern "Vector2Divide" func Vector2Divide(v1: Vector2, v2: Vector2): Vector2
export extern "Vector2Normalize" func Vector2Normalize(v: Vector2): Vector2
export extern "Vector2Transform" func Vector2Transform(v: Vector2, mat: Matrix): Vector2
export extern "Vector2Lerp" func Vector2Lerp(v1: Vector2, v2: Vector2, amount: f32): Vector2
export extern "Vector2Reflect" func Vector2Reflect(v: Vector2, normal: Vector2): Vector2
export extern "Vector2Min" func Vector2Min(v1: Vector2, v2: Vector2): Vector2
export extern "Vector2Max" func Vector2Max(v1: Vector2, v2: Vector2): Vector2
export extern "Vector2Rotate" func Vector2Rotate(v: Vector2, angle: f32): Vector2
export extern "Vector2MoveTowards" func Vector2MoveTowards(v: Vector2, target: Vector2, maxDistance: f32): Vector2
export extern "Vector2Invert" func Vector2Invert(v: Vector2): Vector2
export extern "Vector2Clamp" func Vector2Clamp(v: Vector2, min: Vector2, max: Vector2): Vector2
export extern "Vector2ClampValue" func Vector2ClampValue(v: Vector2, min: f32, max: f32): Vector2
export extern "Vector2Equals" func Vector2Equals(p: Vector2, q: Vector2): i32
export extern "Vector2Refract" func Vector2Refract(v: Vector2, n: Vector2, r: f32): Vector2
export extern "Vector3Zero" func Vector3Zero(): Vector3
export extern "Vector3One" func Vector3One(): Vector3
export extern "Vector3Add" func Vector3Add(v1: Vector3, v2: Vector3): Vector3
export extern "Vector3AddValue" func Vector3AddValue(v: Vector3, add: f32): Vector3
export extern "Vector3Subtract" func Vector3Subtract(v1: Vector3, v2: Vector3): Vector3
export extern "Vector3SubtractValue" func Vector3SubtractValue(v: Vector3, sub: f32): Vector3
export extern "Vector3Scale" func Vector3Scale(v: Vector3, scalar: f32): Vector3
export extern "Vector3Multiply" func Vector3Multiply(v1: Vector3, v2: Vector3): Vector3
export extern "Vector3CrossProduct" func Vector3CrossProduct(v1: Vector3, v2: Vector3): Vector3
export extern "Vector3Perpendicular" func Vector3Perpendicular(v: Vector3): Vector3
export extern "Vector3Length" func Vector3Length(v: Vector3): f32
export extern "Vector3LengthSqr" func Vector3LengthSqr(v: Vector3): f32
export extern "Vector3DotProduct" func Vector3DotProduct(v1: Vector3, v2: Vector3): f32
export extern "Vector3Distance" func Vector3Distance(v1: Vector3, v2: Vector3): f32
export extern "Vector3DistanceSqr" func Vector3DistanceSqr(v1: Vector3, v2: Vector3): f32
export extern "Vector3Angle" func Vector3Angle(v1: Vector3, v2: Vector3): f32
export extern "Vector3Negate" func Vector3Negate(v: Vector3): Vector3
export extern "Vector3Divide" func Vector3Divide(v1: Vector3, v2: Vector3): Vector3
export extern "Vector3Normalize" func Vector3Normalize(v: Vector3): Vector3
export extern "Vector3Project" func Vector3Project(v1: Vector3, v2: Vector3): Vector3
export extern "Vector3Reject" func Vector3Reject(v1: Vector3, v2: Vector3): Vector3
export extern "Vector3OrthoNormalize" func Vector3OrthoNormalize(v1: ^Vector3, v2: ^Vector3): void
export extern "Vector3Transform" func Vector3Transform(v: Vector3, mat: Matrix): Vector3
export extern "Vector3RotateByQuaternion" func Vector3RotateByQuaternion(v: Vector3, q: Vector4): Vector3
export extern "Vector3RotateByAxisAngle" func Vector3RotateByAxisAngle(v: Vector3, axis: Vector3, angle: f32): Vector3
export extern "Vector3MoveTowards" func Vector3MoveTowards(v: Vector3, target: Vector3, maxDistance: f32): Vector3
export extern "Vector3Lerp" func Vector3Lerp(v1: Vector3, v2: Vector3, amount: f32): Vector3
export extern "Vector3CubicHermite" func Vector3CubicHermite(v1: Vector3, tangent1: Vector3, v2: Vector3, tangent2: Vector3, amount: f32): Vector3
export extern "Vector3Reflect" func Vector3Reflect(v: Vector3, normal: Vector3): Vector3
export extern "Vector3Min" func Vector3Min(v1: Vector3, v2: Vector3): Vector3
export extern "Vector3Max" func Vector3Max(v1: Vector3, v2: Vector3): Vector3
export extern "Vector3Barycenter" func Vector3Barycenter(p: Vector3, a: Vector3, b: Vector3, c: Vector3): Vector3
export extern "Vector3Unproject" func Vector3Unproject(source: Vector3, projection: Matrix, view: Matrix): Vector3
export extern "Vector3ToFloatV" func Vector3ToFloatV(v: Vector3): float3
export extern "Vector3Invert" func Vector3Invert(v: Vector3): Vector3
export extern "Vector3Clamp" func Vector3Clamp(v: Vector3, min: Vector3, max: Vector3): Vector3
export extern "Vector3ClampValue" func Vector3ClampValue(v: Vector3, min: f32, max: f32): Vector3
export extern "Vector3Equals" func Vector3Equals(p: Vector3, q: Vector3): i32
export extern "Vector3Refract" func Vector3Refract(v: Vector3, n: Vector3, r: f32): Vector3
export extern "Vector4Zero" func Vector4Zero(): Vector4
export extern "Vector4One" func Vector4One(): Vector4
export extern "Vector4Add" func Vector4Add(v1: Vector4, v2: Vector4): Vector4
export extern "Vector4AddValue" func Vector4AddValue(v: Vector4, add: f32): Vector4
export extern "Vector4Subtract" func Vector4Subtract(v1: Vector4, v2: Vector4): Vector4
export extern "Vector4SubtractValue" func Vector4SubtractValue(v: Vector4, add: f32): Vector4
export extern "Vector4Length" func Vector4Length(v: Vector4): f32
export extern "Vector4LengthSqr" func Vector4LengthSqr(v: Vector4): f32
export extern "Vector4DotProduct" func Vector4DotProduct(v1: Vector4, v2: Vector4): f32
export extern "Vector4Distance" func Vector4Distance(v1: Vector4, v2: Vector4): f32
export extern "Vector4DistanceSqr" func Vector4DistanceSqr(v1: Vector4, v2: Vector4): f32
export extern "Vector4Scale" func Vector4Scale(v: Vector4, scale: f32): Vector4
export extern "Vector4Multiply" func Vector4Multiply(v1: Vector4, v2: Vector4): Vector4
export extern "Vector4Negate" func Vector4Negate(v: Vector4): Vector4
export extern "Vector4Divide" func Vector4Divide(v1: Vector4, v2: Vector4): Vector4
export extern "Vector4Normalize" func Vector4Normalize(v: Vector4): Vector4
export extern "Vector4Min" func Vector4Min(v1: Vector4, v2: Vector4): Vector4
export extern "Vector4Max" func Vector4Max(v1: Vector4, v2: Vector4): Vector4
export extern "Vector4Lerp" func Vector4Lerp(v1: Vector4, v2: Vector4, amount: f32): Vector4
export extern "Vector4MoveTowards" func Vector4MoveTowards(v: Vector4, target: Vector4, maxDistance: f32): Vector4
export extern "Vector4Invert" func Vector4Invert(v: Vector4): Vector4
export extern "Vector4Equals" func Vector4Equals(p: Vector4, q: Vector4): i32
export extern "MatrixDeterminant" func MatrixDeterminant(mat: Matrix): f32
export extern "MatrixTrace" func MatrixTrace(mat: Matrix): f32
export extern "MatrixTranspose" func MatrixTranspose(mat: Matrix): Matrix
export extern "MatrixInvert" func MatrixInvert(mat: Matrix): Matrix
export extern "MatrixIdentity" func MatrixIdentity(): Matrix
export extern "MatrixAdd" func MatrixAdd(left: Matrix, right: Matrix): Matrix
export extern "MatrixSubtract" func MatrixSubtract(left: Matrix, right: Matrix): Matrix
export extern "MatrixMultiply" func MatrixMultiply(left: Matrix, right: Matrix): Matrix
export extern "MatrixTranslate" func MatrixTranslate(x: f32, y: f32, z: f32): Matrix
export extern "MatrixRotate" func MatrixRotate(axis: Vector3, angle: f32): Matrix
export extern "MatrixRotateX" func MatrixRotateX(angle: f32): Matrix
export extern "MatrixRotateY" func MatrixRotateY(angle: f32): Matrix
export extern "MatrixRotateZ" func MatrixRotateZ(angle: f32): Matrix
export extern "MatrixRotateXYZ" func MatrixRotateXYZ(angle: Vector3): Matrix
export extern "MatrixRotateZYX" func MatrixRotateZYX(angle: Vector3): Matrix
export extern "MatrixScale" func MatrixScale(x: f32, y: f32, z: f32): Matrix
export extern "MatrixFrustum" func MatrixFrustum(left: f64, right: f64, bottom: f64, top: f64, nearPlane: f64, farPlane: f64): Matrix
export extern "MatrixPerspective" func MatrixPerspective(fovY: f64, aspect: f64, nearPlane: f64, farPlane: f64): Matrix
export extern "MatrixOrtho" func MatrixOrtho(left: f64, right: f64, bottom: f64, top: f64, nearPlane: f64, farPlane: f64): Matrix
export extern "MatrixLookAt" func MatrixLookAt(eye: Vector3, target: Vector3, up: Vector3): Matrix
export extern "MatrixToFloatV" func MatrixToFloatV(mat: Matrix): float16
export extern "QuaternionAdd" func QuaternionAdd(q1: Vector4, q2: Vector4): Vector4
export extern "QuaternionAddValue" func QuaternionAddValue(q: Vector4, add: f32): Vector4
export extern "QuaternionSubtract" func QuaternionSubtract(q1: Vector4, q2: Vector4): Vector4
export extern "QuaternionSubtractValue" func QuaternionSubtractValue(q: Vector4, sub: f32): Vector4
export extern "QuaternionIdentity" func QuaternionIdentity(): Vector4
export extern "QuaternionLength" func QuaternionLength(q: Vector4): f32
export extern "QuaternionNormalize" func QuaternionNormalize(q: Vector4): Vector4
export extern "QuaternionInvert" func QuaternionInvert(q: Vector4): Vector4
export extern "QuaternionMultiply" func QuaternionMultiply(q1: Vector4, q2: Vector4): Vector4
export extern "QuaternionScale" func QuaternionScale(q: Vector4, mul: f32): Vector4
export extern "QuaternionDivide" func QuaternionDivide(q1: Vector4, q2: Vector4): Vector4
export extern "QuaternionLerp" func QuaternionLerp(q1: Vector4, q2: Vector4, amount: f32): Vector4
export extern "QuaternionNlerp" func QuaternionNlerp(q1: Vector4, q2: Vector4, amount: f32): Vector4
export extern "QuaternionSlerp" func QuaternionSlerp(q1: Vector4, q2: Vector4, amount: f32): Vector4
export extern "QuaternionCubicHermiteSpline" func QuaternionCubicHermiteSpline(q1: Vector4, outTangent1: Vector4, q2: Vector4, inTangent2: Vector4, t: f32): Vector4
export extern "QuaternionFromVector3ToVector3" func QuaternionFromVector3ToVector3(from: Vector3, to: Vector3): Vector4
export extern "QuaternionFromMatrix" func QuaternionFromMatrix(mat: Matrix): Vector4
export extern "QuaternionToMatrix" func QuaternionToMatrix(q: Vector4): Matrix
export extern "QuaternionFromAxisAngle" func QuaternionFromAxisAngle(axis: Vector3, angle: f32): Vector4
export extern "QuaternionToAxisAngle" func QuaternionToAxisAngle(q: Vector4, outAxis: ^Vector3, outAngle: ^f32): void
export extern "QuaternionFromEuler" func QuaternionFromEuler(pitch: f32, yaw: f32, roll: f32): Vector4
export extern "QuaternionToEuler" func QuaternionToEuler(q: Vector4): Vector3
export extern "QuaternionTransform" func QuaternionTransform(q: Vector4, mat: Matrix): Vector4
export extern "QuaternionEquals" func QuaternionEquals(p: Vector4, q: Vector4): i32
export extern "MatrixDecompose" func MatrixDecompose(mat: Matrix, translation: ^Vector3, rotation: ^Vector4, scale: ^Vector3): void

View File

@@ -1,202 +0,0 @@
module "rlgl"
export struct Matrix
{
m0: f32
m4: f32
m8: f32
m12: f32
m1: f32
m5: f32
m9: f32
m13: f32
m2: f32
m6: f32
m10: f32
m14: f32
m3: f32
m7: f32
m11: f32
m15: f32
}
export struct rlVertexBuffer
{
elementCount: i32
vertices: ^f32
texcoords: ^f32
normals: ^f32
colors: ^u8
indices: ^u32
vaoId: u32
vboId: [5]u32
}
export struct rlDrawCall
{
mode: i32
vertexCount: i32
vertexAlignment: i32
textureId: u32
}
export struct rlRenderBatch
{
bufferCount: i32
currentBuffer: i32
vertexBuffer: ^rlVertexBuffer
draws: ^rlDrawCall
drawCounter: i32
currentDepth: f32
}
export extern "rlMatrixMode" func rlMatrixMode(mode: i32): void
export extern "rlPushMatrix" func rlPushMatrix(): void
export extern "rlPopMatrix" func rlPopMatrix(): void
export extern "rlLoadIdentity" func rlLoadIdentity(): void
export extern "rlTranslatef" func rlTranslatef(x: f32, y: f32, z: f32): void
export extern "rlRotatef" func rlRotatef(angle: f32, x: f32, y: f32, z: f32): void
export extern "rlScalef" func rlScalef(x: f32, y: f32, z: f32): void
export extern "rlMultMatrixf" func rlMultMatrixf(matf: ^f32): void
export extern "rlFrustum" func rlFrustum(left: f64, right: f64, bottom: f64, top: f64, znear: f64, zfar: f64): void
export extern "rlOrtho" func rlOrtho(left: f64, right: f64, bottom: f64, top: f64, znear: f64, zfar: f64): void
export extern "rlViewport" func rlViewport(x: i32, y: i32, width: i32, height: i32): void
export extern "rlSetClipPlanes" func rlSetClipPlanes(nearPlane: f64, farPlane: f64): void
export extern "rlGetCullDistanceNear" func rlGetCullDistanceNear(): f64
export extern "rlGetCullDistanceFar" func rlGetCullDistanceFar(): f64
export extern "rlBegin" func rlBegin(mode: i32): void
export extern "rlEnd" func rlEnd(): void
export extern "rlVertex2i" func rlVertex2i(x: i32, y: i32): void
export extern "rlVertex2f" func rlVertex2f(x: f32, y: f32): void
export extern "rlVertex3f" func rlVertex3f(x: f32, y: f32, z: f32): void
export extern "rlTexCoord2f" func rlTexCoord2f(x: f32, y: f32): void
export extern "rlNormal3f" func rlNormal3f(x: f32, y: f32, z: f32): void
export extern "rlColor4ub" func rlColor4ub(r: u8, g: u8, b: u8, a: u8): void
export extern "rlColor3f" func rlColor3f(x: f32, y: f32, z: f32): void
export extern "rlColor4f" func rlColor4f(x: f32, y: f32, z: f32, w: f32): void
export extern "rlEnableVertexArray" func rlEnableVertexArray(vaoId: u32): bool
export extern "rlDisableVertexArray" func rlDisableVertexArray(): void
export extern "rlEnableVertexBuffer" func rlEnableVertexBuffer(id: u32): void
export extern "rlDisableVertexBuffer" func rlDisableVertexBuffer(): void
export extern "rlEnableVertexBufferElement" func rlEnableVertexBufferElement(id: u32): void
export extern "rlDisableVertexBufferElement" func rlDisableVertexBufferElement(): void
export extern "rlEnableVertexAttribute" func rlEnableVertexAttribute(index: u32): void
export extern "rlDisableVertexAttribute" func rlDisableVertexAttribute(index: u32): void
export extern "rlActiveTextureSlot" func rlActiveTextureSlot(slot: i32): void
export extern "rlEnableTexture" func rlEnableTexture(id: u32): void
export extern "rlDisableTexture" func rlDisableTexture(): void
export extern "rlEnableTextureCubemap" func rlEnableTextureCubemap(id: u32): void
export extern "rlDisableTextureCubemap" func rlDisableTextureCubemap(): void
export extern "rlTextureParameters" func rlTextureParameters(id: u32, param: i32, value: i32): void
export extern "rlCubemapParameters" func rlCubemapParameters(id: u32, param: i32, value: i32): void
export extern "rlEnableShader" func rlEnableShader(id: u32): void
export extern "rlDisableShader" func rlDisableShader(): void
export extern "rlEnableFramebuffer" func rlEnableFramebuffer(id: u32): void
export extern "rlDisableFramebuffer" func rlDisableFramebuffer(): void
export extern "rlGetActiveFramebuffer" func rlGetActiveFramebuffer(): u32
export extern "rlActiveDrawBuffers" func rlActiveDrawBuffers(count: i32): void
export extern "rlBlitFramebuffer" func rlBlitFramebuffer(srcX: i32, srcY: i32, srcWidth: i32, srcHeight: i32, dstX: i32, dstY: i32, dstWidth: i32, dstHeight: i32, bufferMask: i32): void
export extern "rlBindFramebuffer" func rlBindFramebuffer(target: u32, framebuffer: u32): void
export extern "rlEnableColorBlend" func rlEnableColorBlend(): void
export extern "rlDisableColorBlend" func rlDisableColorBlend(): void
export extern "rlEnableDepthTest" func rlEnableDepthTest(): void
export extern "rlDisableDepthTest" func rlDisableDepthTest(): void
export extern "rlEnableDepthMask" func rlEnableDepthMask(): void
export extern "rlDisableDepthMask" func rlDisableDepthMask(): void
export extern "rlEnableBackfaceCulling" func rlEnableBackfaceCulling(): void
export extern "rlDisableBackfaceCulling" func rlDisableBackfaceCulling(): void
export extern "rlColorMask" func rlColorMask(r: bool, g: bool, b: bool, a: bool): void
export extern "rlSetCullFace" func rlSetCullFace(mode: i32): void
export extern "rlEnableScissorTest" func rlEnableScissorTest(): void
export extern "rlDisableScissorTest" func rlDisableScissorTest(): void
export extern "rlScissor" func rlScissor(x: i32, y: i32, width: i32, height: i32): void
export extern "rlEnableWireMode" func rlEnableWireMode(): void
export extern "rlEnablePointMode" func rlEnablePointMode(): void
export extern "rlDisableWireMode" func rlDisableWireMode(): void
export extern "rlSetLineWidth" func rlSetLineWidth(width: f32): void
export extern "rlGetLineWidth" func rlGetLineWidth(): f32
export extern "rlEnableSmoothLines" func rlEnableSmoothLines(): void
export extern "rlDisableSmoothLines" func rlDisableSmoothLines(): void
export extern "rlEnableStereoRender" func rlEnableStereoRender(): void
export extern "rlDisableStereoRender" func rlDisableStereoRender(): void
export extern "rlIsStereoRenderEnabled" func rlIsStereoRenderEnabled(): bool
export extern "rlClearColor" func rlClearColor(r: u8, g: u8, b: u8, a: u8): void
export extern "rlClearScreenBuffers" func rlClearScreenBuffers(): void
export extern "rlCheckErrors" func rlCheckErrors(): void
export extern "rlSetBlendMode" func rlSetBlendMode(mode: i32): void
export extern "rlSetBlendFactors" func rlSetBlendFactors(glSrcFactor: i32, glDstFactor: i32, glEquation: i32): void
export extern "rlSetBlendFactorsSeparate" func rlSetBlendFactorsSeparate(glSrcRGB: i32, glDstRGB: i32, glSrcAlpha: i32, glDstAlpha: i32, glEqRGB: i32, glEqAlpha: i32): void
export extern "rlglInit" func rlglInit(width: i32, height: i32): void
export extern "rlglClose" func rlglClose(): void
export extern "rlLoadExtensions" func rlLoadExtensions(loader: ^void): void
export extern "rlGetVersion" func rlGetVersion(): i32
export extern "rlSetFramebufferWidth" func rlSetFramebufferWidth(width: i32): void
export extern "rlGetFramebufferWidth" func rlGetFramebufferWidth(): i32
export extern "rlSetFramebufferHeight" func rlSetFramebufferHeight(height: i32): void
export extern "rlGetFramebufferHeight" func rlGetFramebufferHeight(): i32
export extern "rlGetTextureIdDefault" func rlGetTextureIdDefault(): u32
export extern "rlGetShaderIdDefault" func rlGetShaderIdDefault(): u32
export extern "rlGetShaderLocsDefault" func rlGetShaderLocsDefault(): ^i32
export extern "rlLoadRenderBatch" func rlLoadRenderBatch(numBuffers: i32, bufferElements: i32): rlRenderBatch
export extern "rlUnloadRenderBatch" func rlUnloadRenderBatch(batch: rlRenderBatch): void
export extern "rlDrawRenderBatch" func rlDrawRenderBatch(batch: ^rlRenderBatch): void
export extern "rlSetRenderBatchActive" func rlSetRenderBatchActive(batch: ^rlRenderBatch): void
export extern "rlDrawRenderBatchActive" func rlDrawRenderBatchActive(): void
export extern "rlCheckRenderBatchLimit" func rlCheckRenderBatchLimit(vCount: i32): bool
export extern "rlSetTexture" func rlSetTexture(id: u32): void
export extern "rlLoadVertexArray" func rlLoadVertexArray(): u32
export extern "rlLoadVertexBuffer" func rlLoadVertexBuffer(buffer: ^void, size: i32, dynamic: bool): u32
export extern "rlLoadVertexBufferElement" func rlLoadVertexBufferElement(buffer: ^void, size: i32, dynamic: bool): u32
export extern "rlUpdateVertexBuffer" func rlUpdateVertexBuffer(bufferId: u32, data: ^void, dataSize: i32, offset: i32): void
export extern "rlUpdateVertexBufferElements" func rlUpdateVertexBufferElements(id: u32, data: ^void, dataSize: i32, offset: i32): void
export extern "rlUnloadVertexArray" func rlUnloadVertexArray(vaoId: u32): void
export extern "rlUnloadVertexBuffer" func rlUnloadVertexBuffer(vboId: u32): void
export extern "rlSetVertexAttribute" func rlSetVertexAttribute(index: u32, compSize: i32, type: i32, normalized: bool, stride: i32, offset: i32): void
export extern "rlSetVertexAttributeDivisor" func rlSetVertexAttributeDivisor(index: u32, divisor: i32): void
export extern "rlSetVertexAttributeDefault" func rlSetVertexAttributeDefault(locIndex: i32, value: ^void, attribType: i32, count: i32): void
export extern "rlDrawVertexArray" func rlDrawVertexArray(offset: i32, count: i32): void
export extern "rlDrawVertexArrayElements" func rlDrawVertexArrayElements(offset: i32, count: i32, buffer: ^void): void
export extern "rlDrawVertexArrayInstanced" func rlDrawVertexArrayInstanced(offset: i32, count: i32, instances: i32): void
export extern "rlDrawVertexArrayElementsInstanced" func rlDrawVertexArrayElementsInstanced(offset: i32, count: i32, buffer: ^void, instances: i32): void
export extern "rlLoadTexture" func rlLoadTexture(data: ^void, width: i32, height: i32, format: i32, mipmapCount: i32): u32
export extern "rlLoadTextureDepth" func rlLoadTextureDepth(width: i32, height: i32, useRenderBuffer: bool): u32
export extern "rlLoadTextureCubemap" func rlLoadTextureCubemap(data: ^void, size: i32, format: i32, mipmapCount: i32): u32
export extern "rlUpdateTexture" func rlUpdateTexture(id: u32, offsetX: i32, offsetY: i32, width: i32, height: i32, format: i32, data: ^void): void
export extern "rlGetGlTextureFormats" func rlGetGlTextureFormats(format: i32, glInternalFormat: ^u32, glFormat: ^u32, glType: ^u32): void
export extern "rlGetPixelFormatName" func rlGetPixelFormatName(format: u32): cstring
export extern "rlUnloadTexture" func rlUnloadTexture(id: u32): void
export extern "rlGenTextureMipmaps" func rlGenTextureMipmaps(id: u32, width: i32, height: i32, format: i32, mipmaps: ^i32): void
export extern "rlReadTexturePixels" func rlReadTexturePixels(id: u32, width: i32, height: i32, format: i32): ^void
export extern "rlReadScreenPixels" func rlReadScreenPixels(width: i32, height: i32): ^u8
export extern "rlLoadFramebuffer" func rlLoadFramebuffer(): u32
export extern "rlFramebufferAttach" func rlFramebufferAttach(fboId: u32, texId: u32, attachType: i32, texType: i32, mipLevel: i32): void
export extern "rlFramebufferComplete" func rlFramebufferComplete(id: u32): bool
export extern "rlUnloadFramebuffer" func rlUnloadFramebuffer(id: u32): void
export extern "rlLoadShaderCode" func rlLoadShaderCode(vsCode: cstring, fsCode: cstring): u32
export extern "rlCompileShader" func rlCompileShader(shaderCode: cstring, type: i32): u32
export extern "rlLoadShaderProgram" func rlLoadShaderProgram(vShaderId: u32, fShaderId: u32): u32
export extern "rlUnloadShaderProgram" func rlUnloadShaderProgram(id: u32): void
export extern "rlGetLocationUniform" func rlGetLocationUniform(shaderId: u32, uniformName: cstring): i32
export extern "rlGetLocationAttrib" func rlGetLocationAttrib(shaderId: u32, attribName: cstring): i32
export extern "rlSetUniform" func rlSetUniform(locIndex: i32, value: ^void, uniformType: i32, count: i32): void
export extern "rlSetUniformMatrix" func rlSetUniformMatrix(locIndex: i32, mat: Matrix): void
export extern "rlSetUniformMatrices" func rlSetUniformMatrices(locIndex: i32, mat: ^Matrix, count: i32): void
export extern "rlSetUniformSampler" func rlSetUniformSampler(locIndex: i32, textureId: u32): void
export extern "rlSetShader" func rlSetShader(id: u32, locs: ^i32): void
export extern "rlLoadComputeShaderProgram" func rlLoadComputeShaderProgram(shaderId: u32): u32
export extern "rlComputeShaderDispatch" func rlComputeShaderDispatch(groupX: u32, groupY: u32, groupZ: u32): void
export extern "rlLoadShaderBuffer" func rlLoadShaderBuffer(size: u32, data: ^void, usageHint: i32): u32
export extern "rlUnloadShaderBuffer" func rlUnloadShaderBuffer(ssboId: u32): void
export extern "rlUpdateShaderBuffer" func rlUpdateShaderBuffer(id: u32, data: ^void, dataSize: u32, offset: u32): void
export extern "rlBindShaderBuffer" func rlBindShaderBuffer(id: u32, index: u32): void
export extern "rlReadShaderBuffer" func rlReadShaderBuffer(id: u32, dest: ^void, count: u32, offset: u32): void
export extern "rlCopyShaderBuffer" func rlCopyShaderBuffer(destId: u32, srcId: u32, destOffset: u32, srcOffset: u32, count: u32): void
export extern "rlGetShaderBufferSize" func rlGetShaderBufferSize(id: u32): u32
export extern "rlBindImageTexture" func rlBindImageTexture(id: u32, index: u32, format: i32, readonly: bool): void
export extern "rlGetMatrixModelview" func rlGetMatrixModelview(): Matrix
export extern "rlGetMatrixProjection" func rlGetMatrixProjection(): Matrix
export extern "rlGetMatrixTransform" func rlGetMatrixTransform(): Matrix
export extern "rlGetMatrixProjectionStereo" func rlGetMatrixProjectionStereo(eye: i32): Matrix
export extern "rlGetMatrixViewOffsetStereo" func rlGetMatrixViewOffsetStereo(eye: i32): Matrix
export extern "rlSetMatrixProjection" func rlSetMatrixProjection(proj: Matrix): void
export extern "rlSetMatrixModelview" func rlSetMatrixModelview(view: Matrix): void
export extern "rlSetMatrixProjectionStereo" func rlSetMatrixProjectionStereo(right: Matrix, left: Matrix): void
export extern "rlSetMatrixViewOffsetStereo" func rlSetMatrixViewOffsetStereo(right: Matrix, left: Matrix): void
export extern "rlLoadDrawCube" func rlLoadDrawCube(): void
export extern "rlLoadDrawQuad" func rlLoadDrawQuad(): void

View File

@@ -1,11 +1,9 @@
import "raylib" import raylib
module "main" module main
extern "main" func main(argc: i64, argv: ^^i8): i64 extern "main" func main(argc: i64, argv: [?]^i8): i64
{ {
let uwu: []i32 = [1, 2]
raylib::SetConfigFlags(raylib::ConfigFlags.FLAG_VSYNC_HINT | raylib::ConfigFlags.FLAG_WINDOW_RESIZABLE) raylib::SetConfigFlags(raylib::ConfigFlags.FLAG_VSYNC_HINT | raylib::ConfigFlags.FLAG_WINDOW_RESIZABLE)
raylib::InitWindow(1600, 900, "Hi from nub-lang") raylib::InitWindow(1600, 900, "Hi from nub-lang")

1
runtime/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
.build

6
runtime/build.sh Executable file
View File

@@ -0,0 +1,6 @@
#!/bin/bash
set -euo pipefail
mkdir -p .build
clang -c runtime.c -o .build/runtime.o

42
runtime/ref.c Normal file
View File

@@ -0,0 +1,42 @@
#include "ref.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
void *rc_alloc(size_t size, void (*destructor)(void *self))
{
printf("rc_alloc %zu bytes\n", size);
ref_header *header = malloc(sizeof(ref_header) + size);
if (!header)
{
exit(69);
}
header->ref_count = 1;
header->destructor = destructor;
return (void *)(header + 1);
}
void rc_retain(void *obj)
{
printf("rc_retain\n");
ref_header *header = ((ref_header *)obj) - 1;
header->ref_count++;
}
void rc_release(void *obj)
{
ref_header *header = ((ref_header *)obj) - 1;
printf("rc_release\n");
if (--header->ref_count == 0)
{
if (header->destructor)
{
header->destructor(obj);
}
free(header);
printf("rc_free\n");
}
}

13
runtime/ref.h Normal file
View File

@@ -0,0 +1,13 @@
#pragma once
#include <stddef.h>
typedef struct
{
int ref_count;
void (*destructor)(void *self);
} ref_header;
void *rc_alloc(size_t size, void (*destructor)(void *self));
void rc_retain(void *obj);
void rc_release(void *obj);

1
runtime/runtime.c Normal file
View File

@@ -0,0 +1 @@
#include "ref.c"