...
This commit is contained in:
@@ -28,8 +28,6 @@ var moduleRepository = new ModuleRepository(syntaxTrees);
|
||||
|
||||
var definitions = new List<DefinitionNode>();
|
||||
|
||||
var referencedStructTypes = new HashSet<NubStructType>();
|
||||
|
||||
foreach (var syntaxTree in syntaxTrees)
|
||||
{
|
||||
var typeChecker = new TypeChecker(syntaxTree, moduleRepository);
|
||||
@@ -37,11 +35,6 @@ foreach (var syntaxTree in syntaxTrees)
|
||||
|
||||
definitions.AddRange(typeChecker.Definitions);
|
||||
diagnostics.AddRange(typeChecker.Diagnostics);
|
||||
|
||||
foreach (var structType in typeChecker.ReferencedStructTypes)
|
||||
{
|
||||
referencedStructTypes.Add(structType);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var diagnostic in diagnostics)
|
||||
@@ -56,7 +49,7 @@ if (diagnostics.Any(diagnostic => diagnostic.Severity == DiagnosticSeverity.Erro
|
||||
|
||||
Directory.CreateDirectory(".build");
|
||||
|
||||
var generator = new Generator(definitions, referencedStructTypes);
|
||||
var generator = new Generator(definitions);
|
||||
var c = generator.Emit();
|
||||
var cFilePath = Path.Combine(".build", "out.c");
|
||||
|
||||
@@ -91,7 +84,7 @@ if (moduleRepository.Modules().TryGetValue("main", out var mainModule))
|
||||
.text
|
||||
.globl _start
|
||||
_start:
|
||||
mov rdi, [rsp + 8] # Pass stack pointer to main (argv-like)
|
||||
mov rdi, rsp # Pass stack pointer to main (length + cstring pointers)
|
||||
call {mainFunction.ExternSymbol}
|
||||
mov rdi, rax # Move return value into rdi
|
||||
mov rax, 60 # syscall: exit
|
||||
|
||||
@@ -20,8 +20,6 @@ public record StructFuncNode(List<Token> Tokens, string Name, FuncSignatureNode
|
||||
|
||||
public record StructNode(List<Token> Tokens, string Module, string Name, List<StructFieldNode> Fields, List<StructFuncNode> Functions) : DefinitionNode(Tokens, Module, Name);
|
||||
|
||||
public record GlobalVariableNode(List<Token> Tokens, string Module, string Name, ExpressionNode Value) : DefinitionNode(Tokens, Module, Name);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Statements
|
||||
|
||||
@@ -29,7 +29,6 @@ public sealed class TypeChecker
|
||||
|
||||
public List<DefinitionNode> Definitions { get; } = [];
|
||||
public List<Diagnostic> Diagnostics { get; } = [];
|
||||
public List<NubStructType> ReferencedStructTypes { get; } = [];
|
||||
|
||||
public void Check()
|
||||
{
|
||||
@@ -41,7 +40,6 @@ public sealed class TypeChecker
|
||||
|
||||
Diagnostics.Clear();
|
||||
Definitions.Clear();
|
||||
ReferencedStructTypes.Clear();
|
||||
|
||||
using (BeginRootScope(_syntaxTree.Metadata.ModuleName))
|
||||
{
|
||||
@@ -57,9 +55,6 @@ public sealed class TypeChecker
|
||||
case StructSyntax structSyntax:
|
||||
Definitions.Add(CheckStructDefinition(structSyntax));
|
||||
break;
|
||||
case GlobalVariableSyntax globalVariableSyntax:
|
||||
Definitions.Add(CheckGlobalVariable(globalVariableSyntax));
|
||||
break;
|
||||
case StructTemplateSyntax:
|
||||
break;
|
||||
default:
|
||||
@@ -90,39 +85,7 @@ public sealed class TypeChecker
|
||||
|
||||
private ScopeDisposer BeginRootScope(string moduleName)
|
||||
{
|
||||
if (!_visibleModules.TryGetValue(moduleName, out var moduleScope))
|
||||
{
|
||||
throw new TypeCheckerException(Diagnostic.Error($"Module with name {moduleName} not found").Build());
|
||||
}
|
||||
|
||||
var scope = new Scope(moduleName);
|
||||
_scopes.Push(scope);
|
||||
|
||||
foreach (var globalVariable in moduleScope.GlobalVariables(true))
|
||||
{
|
||||
NubType? type;
|
||||
|
||||
if (globalVariable.ExplicitType != null)
|
||||
{
|
||||
type = ResolveType(globalVariable.ExplicitType);
|
||||
var valueExpression = CheckExpression(globalVariable.Value, type);
|
||||
|
||||
if (valueExpression.Type != ResolveType(globalVariable.ExplicitType))
|
||||
{
|
||||
throw new TypeCheckerException(Diagnostic
|
||||
.Error("Value does not match explicit type of global variable")
|
||||
.At(globalVariable.Value)
|
||||
.Build());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
type = CheckExpression(globalVariable.Value).Type;
|
||||
}
|
||||
|
||||
scope.DeclareVariable(new Variable(globalVariable.Name, type, VariableKind.LValue));
|
||||
}
|
||||
|
||||
_scopes.Push(new Scope(moduleName));
|
||||
return new ScopeDisposer(this);
|
||||
}
|
||||
|
||||
@@ -224,11 +187,6 @@ public sealed class TypeChecker
|
||||
return new FuncNode(node.Tokens, CurrentScope.Module, node.Name, node.ExternSymbol, signature, body);
|
||||
}
|
||||
|
||||
private GlobalVariableNode CheckGlobalVariable(GlobalVariableSyntax node)
|
||||
{
|
||||
return new GlobalVariableNode(node.Tokens, CurrentScope.Module, node.Name, CheckExpression(node.Value));
|
||||
}
|
||||
|
||||
private AssignmentNode CheckAssignment(AssignmentSyntax statement)
|
||||
{
|
||||
var target = CheckExpression(statement.Target);
|
||||
@@ -702,7 +660,6 @@ public sealed class TypeChecker
|
||||
|
||||
private ExpressionNode CheckLocalIdentifier(LocalIdentifierSyntax expression)
|
||||
{
|
||||
// First, look in the current scope for a matching identifier
|
||||
var scopeIdent = CurrentScope.LookupVariable(expression.Name);
|
||||
if (scopeIdent != null)
|
||||
{
|
||||
@@ -714,7 +671,6 @@ public sealed class TypeChecker
|
||||
};
|
||||
}
|
||||
|
||||
// Second, look in the current module for a function matching the identifier
|
||||
var module = _visibleModules[CurrentScope.Module];
|
||||
var function = module.Functions(true).FirstOrDefault(x => x.Name == expression.Name);
|
||||
|
||||
@@ -741,20 +697,6 @@ public sealed class TypeChecker
|
||||
|
||||
var includePrivate = expression.Module == CurrentScope.Module;
|
||||
|
||||
var globalVariable = module.GlobalVariables(includePrivate).FirstOrDefault(x => x.Name == expression.Name);
|
||||
if (globalVariable != null)
|
||||
{
|
||||
// todo(nub31): This should be done in the global scope
|
||||
NubType? type = null;
|
||||
if (globalVariable.ExplicitType != null)
|
||||
{
|
||||
type = ResolveType(globalVariable.ExplicitType);
|
||||
}
|
||||
|
||||
return CheckExpression(globalVariable.Value, type);
|
||||
}
|
||||
|
||||
// First, look for the exported function in the specified module
|
||||
var function = module.Functions(includePrivate).FirstOrDefault(x => x.Name == expression.Name);
|
||||
if (function != null)
|
||||
{
|
||||
@@ -1069,8 +1011,6 @@ public sealed class TypeChecker
|
||||
.ToList();
|
||||
|
||||
result.Functions.AddRange(functions);
|
||||
|
||||
ReferencedStructTypes.Add(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1146,8 +1086,6 @@ public sealed class TypeChecker
|
||||
_checkedTemplateStructs.Add($"{structTemplate.Module}.{mangledName}");
|
||||
}
|
||||
|
||||
ReferencedStructTypes.Add(structType);
|
||||
|
||||
return structType;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Text;
|
||||
using NubLang.Ast;
|
||||
using NubLang.Syntax;
|
||||
|
||||
@@ -6,17 +7,16 @@ namespace NubLang.Generation;
|
||||
public class Generator
|
||||
{
|
||||
private readonly List<DefinitionNode> _definitions;
|
||||
private readonly HashSet<NubStructType> _structTypes;
|
||||
private readonly IndentedTextWriter _writer;
|
||||
private readonly Stack<List<DeferNode>> _deferStack = [];
|
||||
private readonly Stack<(string Name, NubFuncType FuncType)> _funcDefs = [];
|
||||
private readonly List<NubStructType> _structTypes = [];
|
||||
private int _tmpIndex;
|
||||
private int _funcDefIndex;
|
||||
|
||||
public Generator(List<DefinitionNode> definitions, HashSet<NubStructType> structTypes)
|
||||
public Generator(List<DefinitionNode> definitions)
|
||||
{
|
||||
_definitions = definitions;
|
||||
_structTypes = structTypes;
|
||||
_writer = new IndentedTextWriter();
|
||||
}
|
||||
|
||||
@@ -55,12 +55,18 @@ public class Generator
|
||||
},
|
||||
NubPointerType pointerType => MapType(pointerType.BaseType),
|
||||
NubStringType => throw new NotImplementedException(),
|
||||
NubStructType structType => StructName(structType.Module, structType.Name),
|
||||
NubStructType structType => MapStructType(structType),
|
||||
NubVoidType => "void",
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(nubType))
|
||||
};
|
||||
}
|
||||
|
||||
private string MapStructType(NubStructType structType)
|
||||
{
|
||||
_structTypes.Add(structType);
|
||||
return StructName(structType.Module, structType.Name);
|
||||
}
|
||||
|
||||
private string MapFuncType(NubFuncType funcType)
|
||||
{
|
||||
var name = $"_func_type_def{++_funcDefIndex}";
|
||||
@@ -146,21 +152,7 @@ public class Generator
|
||||
#define U64_C(x) x##ULL
|
||||
""";
|
||||
|
||||
foreach (var structType in _structTypes)
|
||||
{
|
||||
_writer.WriteLine("typedef struct");
|
||||
_writer.WriteLine("{");
|
||||
using (_writer.Indent())
|
||||
{
|
||||
foreach (var field in structType.Fields)
|
||||
{
|
||||
_writer.WriteLine($"{MapNameWithType(field.Type, field.Name)};");
|
||||
}
|
||||
}
|
||||
|
||||
_writer.WriteLine($"}} {StructName(structType.Module, structType.Name)};");
|
||||
_writer.WriteLine();
|
||||
}
|
||||
|
||||
var appendNewLine = false;
|
||||
|
||||
@@ -231,7 +223,21 @@ public class Generator
|
||||
typedefs.Add($"typedef {returnType} (*{funcTypeDef.Name})({paramList});");
|
||||
}
|
||||
|
||||
return header + "\n\n" + string.Join('\n', typedefs) + "\n\n" + _writer;
|
||||
var structDefSb = new StringBuilder();
|
||||
foreach (var structType in _structTypes)
|
||||
{
|
||||
structDefSb.AppendLine("typedef struct");
|
||||
structDefSb.AppendLine("{");
|
||||
foreach (var field in structType.Fields)
|
||||
{
|
||||
structDefSb.AppendLine($" {MapNameWithType(field.Type, field.Name)};");
|
||||
}
|
||||
|
||||
structDefSb.AppendLine($"}} {StructName(structType.Module, structType.Name)};");
|
||||
structDefSb.AppendLine();
|
||||
}
|
||||
|
||||
return header + structDefSb + "\n\n" + string.Join('\n', typedefs) + "\n\n" + _writer;
|
||||
}
|
||||
|
||||
private void EmitStatement(StatementNode statementNode)
|
||||
|
||||
@@ -34,12 +34,4 @@ public class Module
|
||||
.Where(x => x.Exported || includePrivate)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public List<GlobalVariableSyntax> GlobalVariables(bool includePrivate)
|
||||
{
|
||||
return _definitions
|
||||
.OfType<GlobalVariableSyntax>()
|
||||
.Where(x => x.Exported || includePrivate)
|
||||
.ToList();
|
||||
}
|
||||
}
|
||||
@@ -84,7 +84,6 @@ public sealed class Parser
|
||||
{
|
||||
Symbol.Func => ParseFunc(startIndex, exported, null),
|
||||
Symbol.Struct => ParseStruct(startIndex, exported),
|
||||
Symbol.Let => ParseGlobalVariable(startIndex, exported),
|
||||
_ => throw new ParseException(Diagnostic
|
||||
.Error($"Expected 'func' or 'struct' but found '{keyword.Symbol}'")
|
||||
.WithHelp("Valid definition keywords are 'func' and 'struct'")
|
||||
@@ -112,22 +111,6 @@ public sealed class Parser
|
||||
return definitions;
|
||||
}
|
||||
|
||||
private GlobalVariableSyntax ParseGlobalVariable(int startIndex, bool exported)
|
||||
{
|
||||
var name = ExpectIdentifier();
|
||||
|
||||
TypeSyntax? type = null;
|
||||
if (TryExpectSymbol(Symbol.Colon))
|
||||
{
|
||||
type = ParseType();
|
||||
}
|
||||
|
||||
ExpectSymbol(Symbol.Assign);
|
||||
var value = ParseExpression();
|
||||
|
||||
return new GlobalVariableSyntax(GetTokens(startIndex), name.Value, exported, type, value);
|
||||
}
|
||||
|
||||
private FuncSignatureSyntax ParseFuncSignature()
|
||||
{
|
||||
var startIndex = _tokenIndex;
|
||||
@@ -924,21 +907,6 @@ public sealed class Parser
|
||||
return identifier;
|
||||
}
|
||||
|
||||
private IntLiteralToken ExpectIntLiteral()
|
||||
{
|
||||
var token = ExpectToken();
|
||||
if (token is not IntLiteralToken identifier)
|
||||
{
|
||||
throw new ParseException(Diagnostic
|
||||
.Error($"Expected int literal, but found {token.GetType().Name}")
|
||||
.WithHelp("Provide a valid int literal")
|
||||
.At(token)
|
||||
.Build());
|
||||
}
|
||||
|
||||
return identifier;
|
||||
}
|
||||
|
||||
private bool TryExpectIntLiteral([NotNullWhen(true)] out IntLiteralToken? stringLiteral)
|
||||
{
|
||||
if (CurrentToken is IntLiteralToken token)
|
||||
@@ -952,36 +920,6 @@ public sealed class Parser
|
||||
return false;
|
||||
}
|
||||
|
||||
private FloatLiteralToken ExpectFloatLiteral()
|
||||
{
|
||||
var token = ExpectToken();
|
||||
if (token is not FloatLiteralToken identifier)
|
||||
{
|
||||
throw new ParseException(Diagnostic
|
||||
.Error($"Expected float literal, but found {token.GetType().Name}")
|
||||
.WithHelp("Provide a valid float literal")
|
||||
.At(token)
|
||||
.Build());
|
||||
}
|
||||
|
||||
return identifier;
|
||||
}
|
||||
|
||||
private BoolLiteralToken ExpectBoolLiteral()
|
||||
{
|
||||
var token = ExpectToken();
|
||||
if (token is not BoolLiteralToken identifier)
|
||||
{
|
||||
throw new ParseException(Diagnostic
|
||||
.Error($"Expected bool literal, but found {token.GetType().Name}")
|
||||
.WithHelp("Provide a valid bool literal")
|
||||
.At(token)
|
||||
.Build());
|
||||
}
|
||||
|
||||
return identifier;
|
||||
}
|
||||
|
||||
private StringLiteralToken ExpectStringLiteral()
|
||||
{
|
||||
var token = ExpectToken();
|
||||
|
||||
@@ -20,8 +20,6 @@ public record StructSyntax(List<Token> Tokens, string Name, bool Exported, List<
|
||||
|
||||
public record StructTemplateSyntax(List<Token> Tokens, List<string> TemplateArguments, string Name, bool Exported, List<StructFieldSyntax> Fields, List<StructFuncSyntax> Functions) : DefinitionSyntax(Tokens, Name, Exported);
|
||||
|
||||
public record GlobalVariableSyntax(List<Token> Tokens, string Name, bool Exported, TypeSyntax? ExplicitType, ExpressionSyntax Value) : DefinitionSyntax(Tokens, Name, Exported);
|
||||
|
||||
public enum UnaryOperatorSyntax
|
||||
{
|
||||
Negate,
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
out: .build/out.o
|
||||
gcc -nostartfiles -lm -o out x86_64.s .build/out.o
|
||||
|
||||
.build/out.o: main.nub
|
||||
.build/out: main.nub
|
||||
nubc main.nub
|
||||
|
||||
clean:
|
||||
@rm -r .build 2>/dev/null || true
|
||||
@rm out 2>/dev/null || true
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
.intel_syntax noprefix
|
||||
|
||||
.text
|
||||
.globl _start
|
||||
_start:
|
||||
mov rdi, rsp
|
||||
call main
|
||||
mov rdi, rax
|
||||
mov rax, 60
|
||||
syscall
|
||||
3
examples/raylib/.gitignore
vendored
3
examples/raylib/.gitignore
vendored
@@ -1,3 +0,0 @@
|
||||
.build
|
||||
out.a
|
||||
out
|
||||
Reference in New Issue
Block a user