...
This commit is contained in:
@@ -14,6 +14,9 @@ public sealed class Generator(List<TypedNodeDefinitionFunc> functions, ModuleGra
|
|||||||
|
|
||||||
private string Emit()
|
private string Emit()
|
||||||
{
|
{
|
||||||
|
foreach (var (i, structType) in moduleGraph.GetModules().SelectMany(x => x.GetCustomTypes().OfType<NubTypeStruct>().Index()))
|
||||||
|
structTypeNames[structType] = $"s{i}";
|
||||||
|
|
||||||
writer.WriteLine("""
|
writer.WriteLine("""
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
@@ -28,9 +31,6 @@ public sealed class Generator(List<TypedNodeDefinitionFunc> functions, ModuleGra
|
|||||||
|
|
||||||
""");
|
""");
|
||||||
|
|
||||||
foreach (var (i, structType) in moduleGraph.GetModules().SelectMany(x => x.GetCustomTypes().OfType<NubTypeStruct>().Index()))
|
|
||||||
structTypeNames[structType] = $"s{i}";
|
|
||||||
|
|
||||||
foreach (var typeName in structTypeNames)
|
foreach (var typeName in structTypeNames)
|
||||||
writer.WriteLine($"struct {typeName.Value};");
|
writer.WriteLine($"struct {typeName.Value};");
|
||||||
|
|
||||||
@@ -45,30 +45,55 @@ public sealed class Generator(List<TypedNodeDefinitionFunc> functions, ModuleGra
|
|||||||
foreach (var field in typeName.Key.Fields)
|
foreach (var field in typeName.Key.Fields)
|
||||||
writer.WriteLine($"{CType(field.Type, field.Name)};");
|
writer.WriteLine($"{CType(field.Type, field.Name)};");
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.WriteLine("};");
|
writer.WriteLine("};");
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.WriteLine();
|
writer.WriteLine();
|
||||||
|
|
||||||
foreach (var node in functions)
|
foreach (var module in moduleGraph.GetModules())
|
||||||
{
|
{
|
||||||
var parameters = node.Parameters.Select(x => CType(x.Type, x.Name.Ident));
|
foreach (var (name, type) in module.GetIdentifierTypes())
|
||||||
writer.WriteLine($"{CType(node.ReturnType, node.Name.Ident)}({string.Join(", ", parameters)});");
|
{
|
||||||
|
if (type is NubTypeFunc fn)
|
||||||
|
{
|
||||||
|
if (!functions.Any(x => x.GetMangledName() == SymbolNameGen.Exported(module.Name, name, type)))
|
||||||
|
writer.Write("extern ");
|
||||||
|
|
||||||
|
writer.WriteLine($"{CType(fn.ReturnType)} {SymbolNameGen.Exported(module.Name, name, type)}({string.Join(", ", fn.Parameters.Select(p => CType(p)))});");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
writer.WriteLine($"{CType(type)} {SymbolNameGen.Exported(module.Name, name, type)};");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.WriteLine();
|
writer.WriteLine();
|
||||||
|
|
||||||
foreach (var node in functions)
|
var main = functions.FirstOrDefault(x => x.Module == "main" && x.Name.Ident == "main");
|
||||||
|
|
||||||
|
if (main != null)
|
||||||
{
|
{
|
||||||
var parameters = node.Parameters.Select(x => CType(x.Type, x.Name.Ident));
|
writer.WriteLine("int main(int argc, char *argv[])");
|
||||||
writer.WriteLine($"{CType(node.ReturnType, node.Name.Ident)}({string.Join(", ", parameters)})");
|
|
||||||
writer.WriteLine("{");
|
writer.WriteLine("{");
|
||||||
using (writer.Indent())
|
using (writer.Indent())
|
||||||
{
|
{
|
||||||
EmitStatement(node.Body);
|
writer.WriteLine($"return {main.GetMangledName()}();");
|
||||||
}
|
}
|
||||||
|
writer.WriteLine("}");
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.WriteLine();
|
||||||
|
|
||||||
|
foreach (var function in functions)
|
||||||
|
{
|
||||||
|
var parameters = function.Parameters.Select(x => CType(x.Type, x.Name.Ident));
|
||||||
|
writer.WriteLine($"{CType(function.ReturnType, function.GetMangledName())}({string.Join(", ", parameters)})");
|
||||||
|
writer.WriteLine("{");
|
||||||
|
using (writer.Indent())
|
||||||
|
{
|
||||||
|
EmitStatement(function.Body);
|
||||||
|
}
|
||||||
writer.WriteLine("}");
|
writer.WriteLine("}");
|
||||||
writer.WriteLine();
|
writer.WriteLine();
|
||||||
}
|
}
|
||||||
@@ -114,7 +139,6 @@ public sealed class Generator(List<TypedNodeDefinitionFunc> functions, ModuleGra
|
|||||||
foreach (var statement in node.Statements)
|
foreach (var statement in node.Statements)
|
||||||
EmitStatement(statement);
|
EmitStatement(statement);
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.WriteLine("}");
|
writer.WriteLine("}");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,7 +177,6 @@ public sealed class Generator(List<TypedNodeDefinitionFunc> functions, ModuleGra
|
|||||||
{
|
{
|
||||||
EmitStatement(statement.ThenBlock);
|
EmitStatement(statement.ThenBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.WriteLine("}");
|
writer.WriteLine("}");
|
||||||
|
|
||||||
if (statement.ElseBlock != null)
|
if (statement.ElseBlock != null)
|
||||||
@@ -169,7 +192,6 @@ public sealed class Generator(List<TypedNodeDefinitionFunc> functions, ModuleGra
|
|||||||
{
|
{
|
||||||
EmitStatement(statement.ElseBlock);
|
EmitStatement(statement.ElseBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.WriteLine("}");
|
writer.WriteLine("}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -183,7 +205,6 @@ public sealed class Generator(List<TypedNodeDefinitionFunc> functions, ModuleGra
|
|||||||
{
|
{
|
||||||
EmitStatement(statement.Block);
|
EmitStatement(statement.Block);
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.WriteLine("}");
|
writer.WriteLine("}");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,7 +220,7 @@ public sealed class Generator(List<TypedNodeDefinitionFunc> functions, ModuleGra
|
|||||||
TypedNodeExpressionStructLiteral expression => EmitExpressionStructLiteral(expression),
|
TypedNodeExpressionStructLiteral expression => EmitExpressionStructLiteral(expression),
|
||||||
TypedNodeExpressionMemberAccess expression => EmitExpressionMemberAccess(expression),
|
TypedNodeExpressionMemberAccess expression => EmitExpressionMemberAccess(expression),
|
||||||
TypedNodeExpressionLocalIdent expression => expression.Value.Ident,
|
TypedNodeExpressionLocalIdent expression => expression.Value.Ident,
|
||||||
TypedNodeExpressionModuleIdent expression => expression.Value.Ident,
|
TypedNodeExpressionModuleIdent expression => SymbolNameGen.Exported(expression.Module.Ident, expression.Value.Ident, expression.Type),
|
||||||
TypedNodeExpressionFuncCall expression => EmitExpressionFuncCall(expression),
|
TypedNodeExpressionFuncCall expression => EmitExpressionFuncCall(expression),
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(node), node, null)
|
_ => throw new ArgumentOutOfRangeException(nameof(node), node, null)
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -24,11 +24,16 @@ public class ModuleGraph(Dictionary<string, ModuleGraph.Module> modules)
|
|||||||
private readonly Dictionary<string, NubType> customTypes = new();
|
private readonly Dictionary<string, NubType> customTypes = new();
|
||||||
private readonly Dictionary<string, NubType> identifierTypes = new();
|
private readonly Dictionary<string, NubType> identifierTypes = new();
|
||||||
|
|
||||||
public List<NubType> GetCustomTypes()
|
public IReadOnlyList<NubType> GetCustomTypes()
|
||||||
{
|
{
|
||||||
return customTypes.Values.ToList();
|
return customTypes.Values.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IReadOnlyDictionary<string, NubType> GetIdentifierTypes()
|
||||||
|
{
|
||||||
|
return identifierTypes;
|
||||||
|
}
|
||||||
|
|
||||||
public bool TryResolveCustomType(string name, [NotNullWhen(true)] out NubType? customType)
|
public bool TryResolveCustomType(string name, [NotNullWhen(true)] out NubType? customType)
|
||||||
{
|
{
|
||||||
customType = customTypes.GetValueOrDefault(name);
|
customType = customTypes.GetValueOrDefault(name);
|
||||||
@@ -61,7 +66,7 @@ public class ModuleGraph(Dictionary<string, ModuleGraph.Module> modules)
|
|||||||
asts.Add(ast);
|
asts.Add(ast);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModuleGraph Build(out List<Diagnostic> diagnostics)
|
public ModuleGraph? Build(out List<Diagnostic> diagnostics)
|
||||||
{
|
{
|
||||||
diagnostics = [];
|
diagnostics = [];
|
||||||
|
|
||||||
@@ -71,24 +76,11 @@ public class ModuleGraph(Dictionary<string, ModuleGraph.Module> modules)
|
|||||||
// First pass: Register modules
|
// First pass: Register modules
|
||||||
foreach (var ast in asts)
|
foreach (var ast in asts)
|
||||||
{
|
{
|
||||||
var moduleDefinitions = ast.Definitions.OfType<NodeDefinitionModule>().ToList();
|
if (!modules.ContainsKey(ast.ModuleName.Ident))
|
||||||
|
|
||||||
if (moduleDefinitions.Count == 0)
|
|
||||||
diagnostics.Add(Diagnostic.Error("Missing module declaration").At(ast.FileName, 1, 1, 1).Build());
|
|
||||||
|
|
||||||
foreach (var extraModuleDefinition in moduleDefinitions.Skip(1))
|
|
||||||
diagnostics.Add(Diagnostic.Warning("Duplicate module declaration will be ignored").At(ast.FileName, extraModuleDefinition).Build());
|
|
||||||
|
|
||||||
if (moduleDefinitions.Count >= 1)
|
|
||||||
{
|
{
|
||||||
var currentModule = moduleDefinitions[0].Name.Ident;
|
var module = new Module(ast.ModuleName.Ident);
|
||||||
|
modules.Add(ast.ModuleName.Ident, module);
|
||||||
if (!modules.ContainsKey(currentModule))
|
astModuleCache[ast] = module;
|
||||||
{
|
|
||||||
var module = new Module(currentModule);
|
|
||||||
modules.Add(currentModule, module);
|
|
||||||
astModuleCache[ast] = module;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,6 +125,9 @@ public class ModuleGraph(Dictionary<string, ModuleGraph.Module> modules)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (diagnostics.Any(x => x.Severity == DiagnosticSeverity.Error))
|
||||||
|
return null;
|
||||||
|
|
||||||
return new ModuleGraph(modules);
|
return new ModuleGraph(modules);
|
||||||
|
|
||||||
NubType ResolveType(NodeType node)
|
NubType ResolveType(NodeType node)
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace Compiler;
|
namespace Compiler;
|
||||||
|
|
||||||
public abstract class NubType
|
public abstract class NubType
|
||||||
@@ -153,6 +155,8 @@ public sealed class NubTypeFunc : NubType
|
|||||||
public IReadOnlyList<NubType> Parameters { get; }
|
public IReadOnlyList<NubType> Parameters { get; }
|
||||||
public NubType ReturnType { get; }
|
public NubType ReturnType { get; }
|
||||||
|
|
||||||
|
public string MangledName(string name, string module) => SymbolNameGen.Exported(name, module, this);
|
||||||
|
|
||||||
private NubTypeFunc(List<NubType> parameters, NubType returnType)
|
private NubTypeFunc(List<NubType> parameters, NubType returnType)
|
||||||
{
|
{
|
||||||
Parameters = parameters;
|
Parameters = parameters;
|
||||||
@@ -162,4 +166,110 @@ public sealed class NubTypeFunc : NubType
|
|||||||
public override string ToString() => $"func({string.Join(' ', Parameters)}): {ReturnType}";
|
public override string ToString() => $"func({string.Join(' ', Parameters)}): {ReturnType}";
|
||||||
|
|
||||||
private readonly record struct Signature(IReadOnlyList<NubType> Parameters, NubType ReturnType);
|
private readonly record struct Signature(IReadOnlyList<NubType> Parameters, NubType ReturnType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static class TypeMangler
|
||||||
|
{
|
||||||
|
public static string Encode(NubType type)
|
||||||
|
{
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
Encode(type, sb);
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void Encode(NubType type, StringBuilder sb)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case NubTypeVoid:
|
||||||
|
sb.Append('V');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NubTypeBool:
|
||||||
|
sb.Append('B');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NubTypeUInt u:
|
||||||
|
sb.Append("U(");
|
||||||
|
sb.Append(u.Width);
|
||||||
|
sb.Append(')');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NubTypeSInt s:
|
||||||
|
sb.Append("U(");
|
||||||
|
sb.Append(s.Width);
|
||||||
|
sb.Append(')');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NubTypeString:
|
||||||
|
sb.Append('S');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NubTypePointer p:
|
||||||
|
sb.Append("P(");
|
||||||
|
Encode(p.To, sb);
|
||||||
|
sb.Append(')');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NubTypeStruct st:
|
||||||
|
sb.Append($"T({st.Module}::{st.Name})").Append(st.Module).Append("::").Append(st.Name).Append(')');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NubTypeFunc fn:
|
||||||
|
sb.Append("F(");
|
||||||
|
for (int i = 0; i < fn.Parameters.Count; i++)
|
||||||
|
{
|
||||||
|
Encode(fn.Parameters[i], sb);
|
||||||
|
sb.Append(',');
|
||||||
|
}
|
||||||
|
Encode(fn.ReturnType, sb);
|
||||||
|
sb.Append(')');
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new NotSupportedException(type.GetType().Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Hashing
|
||||||
|
{
|
||||||
|
public static ulong Fnv1a64(string text)
|
||||||
|
{
|
||||||
|
const ulong offset = 14695981039346656037UL;
|
||||||
|
const ulong prime = 1099511628211UL;
|
||||||
|
|
||||||
|
ulong hash = offset;
|
||||||
|
foreach (var c in Encoding.UTF8.GetBytes(text))
|
||||||
|
{
|
||||||
|
hash ^= c;
|
||||||
|
hash *= prime;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class SymbolNameGen
|
||||||
|
{
|
||||||
|
public static string Exported(string module, string function, NubType type)
|
||||||
|
{
|
||||||
|
var canonical = TypeMangler.Encode(type);
|
||||||
|
var hash = Hashing.Fnv1a64(canonical);
|
||||||
|
|
||||||
|
return $"nub_{Sanitize(module)}_{Sanitize(function)}_{hash:x16}";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string Sanitize(string s)
|
||||||
|
{
|
||||||
|
var sb = new StringBuilder(s.Length);
|
||||||
|
foreach (var c in s)
|
||||||
|
{
|
||||||
|
if (char.IsLetterOrDigit(c))
|
||||||
|
sb.Append(c);
|
||||||
|
else
|
||||||
|
sb.Append('_');
|
||||||
|
}
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,20 +4,25 @@ namespace Compiler;
|
|||||||
|
|
||||||
public sealed class Parser(string fileName, List<Token> tokens)
|
public sealed class Parser(string fileName, List<Token> tokens)
|
||||||
{
|
{
|
||||||
public static Ast Parse(string fileName, List<Token> tokens, out List<Diagnostic> diagnostics)
|
public static Ast? Parse(string fileName, List<Token> tokens, out List<Diagnostic> diagnostics)
|
||||||
{
|
{
|
||||||
return new Parser(fileName, tokens).Parse(out diagnostics);
|
return new Parser(fileName, tokens).Parse(out diagnostics);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int index;
|
private int index;
|
||||||
|
|
||||||
private Ast Parse(out List<Diagnostic> diagnostics)
|
private Ast? Parse(out List<Diagnostic> diagnostics)
|
||||||
{
|
{
|
||||||
var definitions = new List<NodeDefinition>();
|
var definitions = new List<NodeDefinition>();
|
||||||
diagnostics = [];
|
diagnostics = [];
|
||||||
|
|
||||||
|
TokenIdent? moduleName = null;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
ExpectKeyword(Keyword.Module);
|
||||||
|
moduleName = ExpectIdent();
|
||||||
|
|
||||||
while (Peek() != null)
|
while (Peek() != null)
|
||||||
{
|
{
|
||||||
definitions.Add(ParseDefinition());
|
definitions.Add(ParseDefinition());
|
||||||
@@ -28,7 +33,10 @@ public sealed class Parser(string fileName, List<Token> tokens)
|
|||||||
diagnostics.Add(e.Diagnostic);
|
diagnostics.Add(e.Diagnostic);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Ast(definitions, fileName);
|
if (moduleName == null || diagnostics.Any(x => x.Severity == DiagnosticSeverity.Error))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return new Ast(fileName, moduleName, definitions);
|
||||||
}
|
}
|
||||||
|
|
||||||
private NodeDefinition ParseDefinition()
|
private NodeDefinition ParseDefinition()
|
||||||
@@ -76,12 +84,6 @@ public sealed class Parser(string fileName, List<Token> tokens)
|
|||||||
return new NodeDefinitionStruct(TokensFrom(startIndex), name, fields);
|
return new NodeDefinitionStruct(TokensFrom(startIndex), name, fields);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TryExpectKeyword(Keyword.Module))
|
|
||||||
{
|
|
||||||
var name = ExpectIdent();
|
|
||||||
return new NodeDefinitionModule(TokensFrom(startIndex), name);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new CompileException(Diagnostic.Error("Not a valid definition").At(fileName, Peek()).Build());
|
throw new CompileException(Diagnostic.Error("Not a valid definition").At(fileName, Peek()).Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,6 +357,17 @@ public sealed class Parser(string fileName, List<Token> tokens)
|
|||||||
return tokens.GetRange(startIndex, index - startIndex);
|
return tokens.GetRange(startIndex, index - startIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ExpectKeyword(Keyword keyword)
|
||||||
|
{
|
||||||
|
if (Peek() is TokenKeyword token && token.Keyword == keyword)
|
||||||
|
{
|
||||||
|
Next();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new CompileException(Diagnostic.Error($"Expected '{keyword.AsString()}'").At(fileName, Peek()).Build());
|
||||||
|
}
|
||||||
|
|
||||||
private bool TryExpectKeyword(Keyword keyword)
|
private bool TryExpectKeyword(Keyword keyword)
|
||||||
{
|
{
|
||||||
if (Peek() is TokenKeyword token && token.Keyword == keyword)
|
if (Peek() is TokenKeyword token && token.Keyword == keyword)
|
||||||
@@ -529,9 +542,10 @@ public sealed class Parser(string fileName, List<Token> tokens)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class Ast(List<NodeDefinition> definitions, string fileName)
|
public sealed class Ast(string fileName, TokenIdent moduleName, List<NodeDefinition> definitions)
|
||||||
{
|
{
|
||||||
public string FileName { get; } = fileName;
|
public string FileName { get; } = fileName;
|
||||||
|
public TokenIdent ModuleName { get; } = moduleName;
|
||||||
public List<NodeDefinition> Definitions { get; } = definitions;
|
public List<NodeDefinition> Definitions { get; } = definitions;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -542,11 +556,6 @@ public abstract class Node(List<Token> tokens)
|
|||||||
|
|
||||||
public abstract class NodeDefinition(List<Token> tokens) : Node(tokens);
|
public abstract class NodeDefinition(List<Token> tokens) : Node(tokens);
|
||||||
|
|
||||||
public sealed class NodeDefinitionModule(List<Token> tokens, TokenIdent name) : NodeDefinition(tokens)
|
|
||||||
{
|
|
||||||
public TokenIdent Name { get; } = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed class NodeDefinitionFunc(List<Token> tokens, TokenIdent name, List<NodeDefinitionFunc.Param> parameters, NodeStatement body, NodeType returnType) : NodeDefinition(tokens)
|
public sealed class NodeDefinitionFunc(List<Token> tokens, TokenIdent name, List<NodeDefinitionFunc.Param> parameters, NodeStatement body, NodeType returnType) : NodeDefinition(tokens)
|
||||||
{
|
{
|
||||||
public TokenIdent Name { get; } = name;
|
public TokenIdent Name { get; } = name;
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ foreach (var fileName in args)
|
|||||||
foreach (var diagnostic in tokenizerDiagnostics)
|
foreach (var diagnostic in tokenizerDiagnostics)
|
||||||
DiagnosticFormatter.Print(diagnostic, Console.Error);
|
DiagnosticFormatter.Print(diagnostic, Console.Error);
|
||||||
|
|
||||||
if (tokenizerDiagnostics.Any(x => x.Severity == DiagnosticSeverity.Error))
|
if (tokens == null)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
var ast = Parser.Parse(fileName, tokens, out var parserDiagnostics);
|
var ast = Parser.Parse(fileName, tokens, out var parserDiagnostics);
|
||||||
@@ -21,7 +21,7 @@ foreach (var fileName in args)
|
|||||||
foreach (var diagnostic in parserDiagnostics)
|
foreach (var diagnostic in parserDiagnostics)
|
||||||
DiagnosticFormatter.Print(diagnostic, Console.Error);
|
DiagnosticFormatter.Print(diagnostic, Console.Error);
|
||||||
|
|
||||||
if (parserDiagnostics.Any(x => x.Severity == DiagnosticSeverity.Error))
|
if (ast == null)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
moduleGraphBuilder.AddAst(ast);
|
moduleGraphBuilder.AddAst(ast);
|
||||||
@@ -33,7 +33,7 @@ var moduleGraph = moduleGraphBuilder.Build(out var moduleGraphDiagnostics);
|
|||||||
foreach (var diagnostic in moduleGraphDiagnostics)
|
foreach (var diagnostic in moduleGraphDiagnostics)
|
||||||
DiagnosticFormatter.Print(diagnostic, Console.Error);
|
DiagnosticFormatter.Print(diagnostic, Console.Error);
|
||||||
|
|
||||||
if (moduleGraphDiagnostics.Any(x => x.Severity == DiagnosticSeverity.Error))
|
if (moduleGraph == null)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
var functions = new List<TypedNodeDefinitionFunc>();
|
var functions = new List<TypedNodeDefinitionFunc>();
|
||||||
@@ -42,7 +42,7 @@ foreach (var ast in asts)
|
|||||||
{
|
{
|
||||||
foreach (var func in ast.Definitions.OfType<NodeDefinitionFunc>())
|
foreach (var func in ast.Definitions.OfType<NodeDefinitionFunc>())
|
||||||
{
|
{
|
||||||
var typedFunction = TypeChecker.CheckFunction(ast.FileName, func, moduleGraph, out var typeCheckerDiagnostics);
|
var typedFunction = TypeChecker.CheckFunction(ast.FileName, ast.ModuleName.Ident, func, moduleGraph, out var typeCheckerDiagnostics);
|
||||||
|
|
||||||
foreach (var diagnostic in typeCheckerDiagnostics)
|
foreach (var diagnostic in typeCheckerDiagnostics)
|
||||||
DiagnosticFormatter.Print(diagnostic, Console.Error);
|
DiagnosticFormatter.Print(diagnostic, Console.Error);
|
||||||
@@ -61,6 +61,6 @@ Directory.CreateDirectory(".build");
|
|||||||
|
|
||||||
File.WriteAllText(".build/out.c", output);
|
File.WriteAllText(".build/out.c", output);
|
||||||
|
|
||||||
Process.Start("gcc", ["-Og", "-g", "-o", ".build/out", ".build/out.c"]);
|
Process.Start("gcc", ["-Og", "-g", "-o", ".build/out", ".build/out.c", "-fvisibility=hidden","-fno-builtin"]);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -5,7 +5,7 @@ namespace Compiler;
|
|||||||
|
|
||||||
public sealed class Tokenizer(string fileName, string contents)
|
public sealed class Tokenizer(string fileName, string contents)
|
||||||
{
|
{
|
||||||
public static List<Token> Tokenize(string fileName, string contents, out List<Diagnostic> diagnostics)
|
public static List<Token>? Tokenize(string fileName, string contents, out List<Diagnostic> diagnostics)
|
||||||
{
|
{
|
||||||
return new Tokenizer(fileName, contents).Tokenize(out diagnostics);
|
return new Tokenizer(fileName, contents).Tokenize(out diagnostics);
|
||||||
}
|
}
|
||||||
@@ -14,7 +14,7 @@ public sealed class Tokenizer(string fileName, string contents)
|
|||||||
private int line = 1;
|
private int line = 1;
|
||||||
private int column = 1;
|
private int column = 1;
|
||||||
|
|
||||||
private List<Token> Tokenize(out List<Diagnostic> diagnostics)
|
private List<Token>? Tokenize(out List<Diagnostic> diagnostics)
|
||||||
{
|
{
|
||||||
var tokens = new List<Token>();
|
var tokens = new List<Token>();
|
||||||
diagnostics = [];
|
diagnostics = [];
|
||||||
@@ -53,6 +53,9 @@ public sealed class Tokenizer(string fileName, string contents)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (diagnostics.Any(x => x.Severity == DiagnosticSeverity.Error))
|
||||||
|
return null;
|
||||||
|
|
||||||
return tokens;
|
return tokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
namespace Compiler;
|
namespace Compiler;
|
||||||
|
|
||||||
public sealed class TypeChecker(string fileName, NodeDefinitionFunc function, ModuleGraph moduleGraph)
|
public sealed class TypeChecker(string fileName, string moduleName, NodeDefinitionFunc function, ModuleGraph moduleGraph)
|
||||||
{
|
{
|
||||||
public static TypedNodeDefinitionFunc? CheckFunction(string fileName, NodeDefinitionFunc function, ModuleGraph moduleGraph, out List<Diagnostic> diagnostics)
|
public static TypedNodeDefinitionFunc? CheckFunction(string fileName, string moduleName, NodeDefinitionFunc function, ModuleGraph moduleGraph, out List<Diagnostic> diagnostics)
|
||||||
{
|
{
|
||||||
return new TypeChecker(fileName, function, moduleGraph).CheckFunction(out diagnostics);
|
return new TypeChecker(fileName, moduleName, function, moduleGraph).CheckFunction(out diagnostics);
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly Scope scope = new(null);
|
private readonly Scope scope = new(null);
|
||||||
@@ -52,7 +52,7 @@ public sealed class TypeChecker(string fileName, NodeDefinitionFunc function, Mo
|
|||||||
if (body == null || returnType == null || invalidParameter)
|
if (body == null || returnType == null || invalidParameter)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return new TypedNodeDefinitionFunc(function.Tokens, function.Name, parameters, body, returnType);
|
return new TypedNodeDefinitionFunc(function.Tokens, moduleName, function.Name, parameters, body, returnType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private TypedNodeDefinitionFunc.Param CheckDefinitionFuncParameter(NodeDefinitionFunc.Param node)
|
private TypedNodeDefinitionFunc.Param CheckDefinitionFuncParameter(NodeDefinitionFunc.Param node)
|
||||||
@@ -409,15 +409,28 @@ public abstract class TypedNode(List<Token> tokens)
|
|||||||
public List<Token> Tokens { get; } = tokens;
|
public List<Token> Tokens { get; } = tokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class TypedNodeDefinition(List<Token> tokens) : TypedNode(tokens);
|
public abstract class TypedNodeDefinition(List<Token> tokens, string module) : TypedNode(tokens)
|
||||||
|
{
|
||||||
|
public string Module { get; } = module;
|
||||||
|
}
|
||||||
|
|
||||||
public sealed class TypedNodeDefinitionFunc(List<Token> tokens, TokenIdent name, List<TypedNodeDefinitionFunc.Param> parameters, TypedNodeStatement body, NubType returnType) : TypedNodeDefinition(tokens)
|
public sealed class TypedNodeDefinitionFunc(List<Token> tokens, string module, TokenIdent name, List<TypedNodeDefinitionFunc.Param> parameters, TypedNodeStatement body, NubType returnType) : TypedNodeDefinition(tokens, module)
|
||||||
{
|
{
|
||||||
public TokenIdent Name { get; } = name;
|
public TokenIdent Name { get; } = name;
|
||||||
public List<Param> Parameters { get; } = parameters;
|
public List<Param> Parameters { get; } = parameters;
|
||||||
public TypedNodeStatement Body { get; } = body;
|
public TypedNodeStatement Body { get; } = body;
|
||||||
public NubType ReturnType { get; } = returnType;
|
public NubType ReturnType { get; } = returnType;
|
||||||
|
|
||||||
|
public NubTypeFunc GetNubType()
|
||||||
|
{
|
||||||
|
return NubTypeFunc.Get(Parameters.Select(x => x.Type).ToList(), ReturnType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetMangledName()
|
||||||
|
{
|
||||||
|
return SymbolNameGen.Exported(Module, Name.Ident, GetNubType());
|
||||||
|
}
|
||||||
|
|
||||||
public sealed class Param(List<Token> tokens, TokenIdent name, NubType type) : TypedNode(tokens)
|
public sealed class Param(List<Token> tokens, TokenIdent name, NubType type) : TypedNode(tokens)
|
||||||
{
|
{
|
||||||
public TokenIdent Name { get; } = name;
|
public TokenIdent Name { get; } = name;
|
||||||
|
|||||||
Reference in New Issue
Block a user