...
This commit is contained in:
@@ -379,7 +379,7 @@ public class QBEGenerator
|
|||||||
_labelIndex = 0;
|
_labelIndex = 0;
|
||||||
_tmpIndex = 0;
|
_tmpIndex = 0;
|
||||||
|
|
||||||
_writer.Write("export function ");
|
_writer.Write(funcDef.ExternSymbol != null ? "export function " : "function ");
|
||||||
|
|
||||||
if (funcDef.Signature.ReturnType is not VoidTypeNode)
|
if (funcDef.Signature.ReturnType is not VoidTypeNode)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ public record FuncParameterNode(string Name, TypeNode Type) : Node;
|
|||||||
|
|
||||||
public record FuncSignatureNode(IReadOnlyList<FuncParameterNode> Parameters, TypeNode ReturnType) : Node;
|
public record FuncSignatureNode(IReadOnlyList<FuncParameterNode> Parameters, TypeNode ReturnType) : Node;
|
||||||
|
|
||||||
public record FuncNode(string Module, string Name, FuncSignatureNode Signature, BlockNode? Body) : DefinitionNode(Module, Name);
|
public record FuncNode(string Module, string Name, string? ExternSymbol, FuncSignatureNode Signature, BlockNode? Body) : DefinitionNode(Module, Name);
|
||||||
|
|
||||||
public record StructFieldNode(int Index, string Name, TypeNode Type, Optional<ExpressionNode> Value) : Node;
|
public record StructFieldNode(int Index, string Name, TypeNode Type, Optional<ExpressionNode> Value) : Node;
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
using NubLang.Diagnostics;
|
using NubLang.Diagnostics;
|
||||||
using NubLang.Parsing.Syntax;
|
using NubLang.Parsing.Syntax;
|
||||||
using NubLang.Tokenization;
|
using NubLang.Tokenization;
|
||||||
@@ -59,7 +60,11 @@ public sealed class TypeChecker
|
|||||||
|
|
||||||
private InterfaceNode CheckInterfaceDefinition(InterfaceSyntax node)
|
private InterfaceNode CheckInterfaceDefinition(InterfaceSyntax node)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
var functions = node.Functions
|
||||||
|
.Select(function => new InterfaceFuncNode(function.Name, CheckFuncSignature(function.Signature)))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
return new InterfaceNode(_syntaxTree.Metadata.ModuleName, node.Name, functions);
|
||||||
}
|
}
|
||||||
|
|
||||||
private StructNode CheckStructDefinition(StructSyntax node)
|
private StructNode CheckStructDefinition(StructSyntax node)
|
||||||
@@ -124,7 +129,7 @@ public sealed class TypeChecker
|
|||||||
_funcReturnTypes.Pop();
|
_funcReturnTypes.Pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new FuncNode(_syntaxTree.Metadata.ModuleName, node.Name, CheckFuncSignature(node.Signature), body);
|
return new FuncNode(_syntaxTree.Metadata.ModuleName, node.Name, node.ExternSymbol, CheckFuncSignature(node.Signature), body);
|
||||||
}
|
}
|
||||||
|
|
||||||
private StatementNode CheckStatement(StatementSyntax node)
|
private StatementNode CheckStatement(StatementSyntax node)
|
||||||
@@ -308,7 +313,7 @@ public sealed class TypeChecker
|
|||||||
var parameterExpression = CheckExpression(parameter, expectedType);
|
var parameterExpression = CheckExpression(parameter, expectedType);
|
||||||
if (parameterExpression.Type != expectedType)
|
if (parameterExpression.Type != expectedType)
|
||||||
{
|
{
|
||||||
throw new Exception($"Parameter {i + 1} does not match the type {expectedType} for function {funcType}");
|
throw new TypeCheckerException(Diagnostic.Error($"Parameter {i + 1} does not match the type {expectedType} for function {funcType}").At(parameter).Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
parameters.Add(parameterExpression);
|
parameters.Add(parameterExpression);
|
||||||
@@ -402,12 +407,77 @@ public sealed class TypeChecker
|
|||||||
|
|
||||||
private StructFieldAccessNode CheckStructFieldAccess(StructFieldAccessSyntax expression)
|
private StructFieldAccessNode CheckStructFieldAccess(StructFieldAccessSyntax expression)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
var target = CheckExpression(expression.Target);
|
||||||
|
|
||||||
|
if (target.Type is not StructTypeNode structType)
|
||||||
|
{
|
||||||
|
throw new TypeCheckerException(Diagnostic
|
||||||
|
.Error($"Cannot access struct member on non-struct type {target.Type}")
|
||||||
|
.At(expression)
|
||||||
|
.Build());
|
||||||
|
}
|
||||||
|
|
||||||
|
var field = structType.Fields.FirstOrDefault(x => x.Name == expression.Member);
|
||||||
|
if (field == null)
|
||||||
|
{
|
||||||
|
throw new TypeCheckerException(Diagnostic
|
||||||
|
.Error($"Struct {target.Type} does not have a field with the name {expression.Member}")
|
||||||
|
.At(expression)
|
||||||
|
.Build());
|
||||||
|
}
|
||||||
|
|
||||||
|
return new StructFieldAccessNode(field.Type, structType, target, expression.Member);
|
||||||
}
|
}
|
||||||
|
|
||||||
private StructInitializerNode CheckStructInitializer(StructInitializerSyntax expression, TypeNode? expectedType)
|
private StructInitializerNode CheckStructInitializer(StructInitializerSyntax expression, TypeNode? expectedType)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
StructTypeNode? structType = null;
|
||||||
|
|
||||||
|
if (expression.StructType.TryGetValue(out var customType))
|
||||||
|
{
|
||||||
|
var checkedType = ResolveType(customType);
|
||||||
|
if (checkedType is not StructTypeNode checkedStructType)
|
||||||
|
{
|
||||||
|
throw new UnreachableException("Parser fucked up");
|
||||||
|
}
|
||||||
|
|
||||||
|
structType = checkedStructType;
|
||||||
|
}
|
||||||
|
else if (expectedType is StructTypeNode expectedStructType)
|
||||||
|
{
|
||||||
|
structType = expectedStructType;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (structType == null)
|
||||||
|
{
|
||||||
|
throw new TypeCheckerException(Diagnostic
|
||||||
|
.Error("Cannot get implicit type of struct")
|
||||||
|
.WithHelp("Specify struct type with struct {type_name} syntax")
|
||||||
|
.At(expression)
|
||||||
|
.Build());
|
||||||
|
}
|
||||||
|
|
||||||
|
var initializers = new Dictionary<string, ExpressionNode>();
|
||||||
|
|
||||||
|
foreach (var initializer in expression.Initializers)
|
||||||
|
{
|
||||||
|
initializers.Add(initializer.Key, CheckExpression(initializer.Value));
|
||||||
|
}
|
||||||
|
|
||||||
|
var missingFields = structType.Fields
|
||||||
|
.Where(x => !x.HasDefaultValue && !initializers.ContainsKey(x.Name))
|
||||||
|
.Select(x => x.Name)
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
if (missingFields.Length != 0)
|
||||||
|
{
|
||||||
|
throw new TypeCheckerException(Diagnostic
|
||||||
|
.Error($"Fields {string.Join(", ", missingFields)} are not initialized")
|
||||||
|
.At(expression)
|
||||||
|
.Build());
|
||||||
|
}
|
||||||
|
|
||||||
|
return new StructInitializerNode(structType, initializers);
|
||||||
}
|
}
|
||||||
|
|
||||||
private UnaryExpressionNode CheckUnaryExpression(UnaryExpressionSyntax expression)
|
private UnaryExpressionNode CheckUnaryExpression(UnaryExpressionSyntax expression)
|
||||||
@@ -453,7 +523,7 @@ public sealed class TypeChecker
|
|||||||
{
|
{
|
||||||
if (!_importedModules.TryGetValue(customType.Module, out var module))
|
if (!_importedModules.TryGetValue(customType.Module, out var module))
|
||||||
{
|
{
|
||||||
throw new Exception("Module not found: " + customType.Module);
|
throw new TypeCheckerException(Diagnostic.Error($"Module {customType.Module} not found").WithHelp($"import \"{customType.Module}\"").At(customType).Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (customType.Module == _syntaxTree.Metadata.ModuleName)
|
if (customType.Module == _syntaxTree.Metadata.ModuleName)
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
module "main"
|
|
||||||
import "test"
|
|
||||||
|
|
||||||
export extern "puts" func puts(text: cstring)
|
|
||||||
|
|
||||||
struct Human
|
|
||||||
{
|
|
||||||
name: cstring
|
|
||||||
age: u64
|
|
||||||
}
|
|
||||||
|
|
||||||
func main(args: []cstring): i64
|
|
||||||
{
|
|
||||||
let me: main::Human = {
|
|
||||||
name = "Oliver"
|
|
||||||
age = 21
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
@@ -3,8 +3,8 @@ NUBC = ../compiler/NubLang.CLI/bin/Debug/net9.0/nubc
|
|||||||
out: .build/out.o
|
out: .build/out.o
|
||||||
gcc -nostartfiles -o out x86_64.s .build/out.o
|
gcc -nostartfiles -o out x86_64.s .build/out.o
|
||||||
|
|
||||||
.build/out.o: $(NUBC) main.nub
|
.build/out.o: $(NUBC) src/main.nub src/test.nub
|
||||||
$(NUBC) main.nub
|
$(NUBC) src/main.nub src/test.nub
|
||||||
|
|
||||||
.PHONY: $(NUBC)
|
.PHONY: $(NUBC)
|
||||||
$(NUBC):
|
$(NUBC):
|
||||||
|
|||||||
14
example/src/main.nub
Normal file
14
example/src/main.nub
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
module "main"
|
||||||
|
import "test"
|
||||||
|
|
||||||
|
export extern "puts" func puts(text: cstring)
|
||||||
|
|
||||||
|
export struct Test1
|
||||||
|
{
|
||||||
|
test2: ^test::Test2
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "main" func main(args: []cstring): i64
|
||||||
|
{
|
||||||
|
return 0
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
.globl _start
|
.globl _start
|
||||||
_start:
|
_start:
|
||||||
mov rdi, rsp
|
mov rdi, rsp
|
||||||
call main.main
|
call main
|
||||||
mov rdi, rax
|
mov rdi, rax
|
||||||
mov rax, 60
|
mov rax, 60
|
||||||
syscall
|
syscall
|
||||||
|
|||||||
Reference in New Issue
Block a user