WIP: dev #1

Draft
nub31 wants to merge 103 commits from dev into master
9 changed files with 300 additions and 176 deletions
Showing only changes of commit ab9bd6fd05 - Show all commits

View File

@@ -2,11 +2,11 @@
namespace Compiler;
public sealed class Generator(List<TypedNodeDefinitionFunc> functions)
public sealed class Generator(List<TypedNodeDefinitionFunc> functions, ModuleGraph moduleGraph)
{
public static string Emit(List<TypedNodeDefinitionFunc> functions)
public static string Emit(List<TypedNodeDefinitionFunc> functions, ModuleGraph moduleGraph)
{
return new Generator(functions).Emit();
return new Generator(functions, moduleGraph).Emit();
}
private readonly IndentedTextWriter writer = new();
@@ -28,27 +28,26 @@ public sealed class Generator(List<TypedNodeDefinitionFunc> functions)
""");
// for (var i = 0; i < ast.StructTypes.Count; i++)
// {
// var structType = ast.StructTypes[i];
// structTypeNames[structType] = $"s{i}";
// }
//
// foreach (var structType in ast.StructTypes)
// {
// var name = structTypeNames[structType];
// writer.WriteLine($"struct {name}");
// writer.WriteLine("{");
// using (writer.Indent())
// {
// foreach (var field in structType.Fields)
// {
// writer.WriteLine($"{CType(field.Type, field.Name)};");
// }
// }
//
// writer.WriteLine("};");
// }
foreach (var (i, structType) in moduleGraph.GetStructTypes().Index())
structTypeNames[structType] = $"s{i}";
foreach (var typeName in structTypeNames)
writer.WriteLine($"struct {typeName.Value};");
writer.WriteLine();
foreach (var typeName in structTypeNames)
{
writer.WriteLine($"struct {typeName.Value}");
writer.WriteLine("{");
using (writer.Indent())
{
foreach (var field in typeName.Key.Fields)
writer.WriteLine($"{CType(field.Type, field.Name)};");
}
writer.WriteLine("};");
}
writer.WriteLine();
@@ -199,7 +198,8 @@ public sealed class Generator(List<TypedNodeDefinitionFunc> functions)
TypedNodeExpressionStringLiteral expression => $"(struct string){{ \"{expression.Value.Value}\", {expression.Value.Value.Length} }}",
TypedNodeExpressionStructLiteral expression => EmitExpressionStructLiteral(expression),
TypedNodeExpressionMemberAccess expression => EmitExpressionMemberAccess(expression),
TypedNodeExpressionIdent expression => expression.Value.Ident,
TypedNodeExpressionLocalIdent expression => expression.Value.Ident,
TypedNodeExpressionModuleIdent expression => expression.Value.Ident,
_ => throw new ArgumentOutOfRangeException(nameof(node), node, null)
};
}

178
compiler/ModuleGraph.cs Normal file
View File

@@ -0,0 +1,178 @@
namespace Compiler;
public class ModuleGraph(Dictionary<string, ModuleGraph.Module> modules)
{
public static Builder Create() => new();
public NubTypeStruct ResolveStruct(string moduleName, string name)
{
var module = modules.GetValueOrDefault(moduleName);
if (module == null)
throw new CompileException(Diagnostic.Error($"Module '{moduleName}' not found").Build());
var structType = module.ResolveStruct(name);
if (structType == null)
throw new CompileException(Diagnostic.Error($"Struct '{moduleName}::{name}' not found").Build());
return structType;
}
public NubType ResolveIdentifier(string moduleName, string name)
{
var module = modules.GetValueOrDefault(moduleName);
if (module == null)
throw new CompileException(Diagnostic.Error($"Module '{moduleName}' not found").Build());
var identType = module.ResolveIdentifier(name);
if (identType == null)
throw new CompileException(Diagnostic.Error($"Function '{moduleName}::{name}' not found").Build());
return identType;
}
public List<NubTypeStruct> GetStructTypes()
{
return modules.SelectMany(x => x.Value.GetStructTypes()).ToList();
}
public sealed class Module
{
private readonly Dictionary<string, NubTypeStruct> structTypes = new();
private readonly Dictionary<string, NubType> identifierTypes = new();
public List<NubTypeStruct> GetStructTypes()
{
return structTypes.Values.ToList();
}
public List<NubType> GetIdentifiers()
{
return identifierTypes.Values.ToList();
}
public NubTypeStruct? ResolveStruct(string name)
{
return structTypes.GetValueOrDefault(name);
}
public NubType? ResolveIdentifier(string name)
{
return identifierTypes.GetValueOrDefault(name);
}
public void AddStruct(string name, NubTypeStruct structType)
{
structTypes.Add(name, structType);
}
public void AddIdentifier(string name, NubType identifier)
{
identifierTypes.Add(name, identifier);
}
}
public class Builder
{
private readonly List<Ast> asts = [];
public void AddAst(Ast ast)
{
asts.Add(ast);
}
public ModuleGraph Build(out List<Diagnostic> diagnostics)
{
diagnostics = [];
var modules = new Dictionary<string, Module>();
// First pass: Register modules
foreach (var ast in asts)
{
var moduleDefinitions = ast.Definitions.OfType<NodeDefinitionModule>().ToList();
var currentModule = moduleDefinitions[0].Name.Ident;
if (!modules.ContainsKey(currentModule))
modules.Add(currentModule, new Module());
}
// Second pass: Register struct types without fields
foreach (var ast in asts)
{
var moduleDefinitions = ast.Definitions.OfType<NodeDefinitionModule>().ToList();
var currentModule = moduleDefinitions[0].Name.Ident;
if (!modules.TryGetValue(currentModule, out var module))
{
module = new Module();
modules[currentModule] = module;
}
foreach (var structDef in ast.Definitions.OfType<NodeDefinitionStruct>())
{
module.AddStruct(structDef.Name.Ident, new NubTypeStruct());
}
}
// Third pass: Resolve struct fields
foreach (var ast in asts)
{
var moduleDefinitions = ast.Definitions.OfType<NodeDefinitionModule>().ToList();
var module = modules[moduleDefinitions[0].Name.Ident];
foreach (var structDef in ast.Definitions.OfType<NodeDefinitionStruct>())
{
var structType = module.ResolveStruct(structDef.Name.Ident);
var fields = structDef.Fields.Select(f => new NubTypeStruct.Field(f.Name.Ident, Resolve(f.Type))).ToList();
structType.ResolveFields(fields);
}
}
// Fourth pass: Register identifiers
foreach (var ast in asts)
{
var moduleDefinitions = ast.Definitions.OfType<NodeDefinitionModule>().ToList();
var module = modules[moduleDefinitions[0].Name.Ident];
foreach (var funcDef in ast.Definitions.OfType<NodeDefinitionFunc>())
{
var parameters = funcDef.Parameters.Select(x => Resolve(x.Type)).ToList();
var returnType = Resolve(funcDef.ReturnType);
var funcType = new NubTypeFunc(parameters, returnType);
module.AddIdentifier(funcDef.Name.Ident, funcType);
}
}
return new ModuleGraph(modules);
NubType Resolve(NodeType node)
{
return node switch
{
NodeTypeBool type => new NubTypeBool(),
NodeTypeCustom type => ResolveStruct(type),
NodeTypeFunc type => new NubTypeFunc(type.Parameters.Select(Resolve).ToList(), Resolve(type.ReturnType)),
NodeTypePointer type => new NubTypePointer(Resolve(type.To)),
NodeTypeSInt type => new NubTypeSInt(type.Width),
NodeTypeUInt type => new NubTypeUInt(type.Width),
NodeTypeString type => new NubTypeString(),
NodeTypeVoid type => new NubTypeVoid(),
_ => throw new ArgumentOutOfRangeException(nameof(node))
};
}
NubTypeStruct ResolveStruct(NodeTypeCustom type)
{
var module = modules.GetValueOrDefault(type.Module.Ident);
if (module == null)
throw new CompileException(Diagnostic.Error($"Unknown module: {type.Module.Ident}").Build());
var structType = module.ResolveStruct(type.Name.Ident);
if (structType == null)
throw new CompileException(Diagnostic.Error($"Unknown custom type: {type.Module.Ident}::{type.Name.Ident}").Build());
return structType;
}
}
}
}

View File

@@ -1,83 +1,5 @@
namespace Compiler;
public sealed class TypeResolver(string fileName)
{
private readonly Dictionary<(string Module, string Name), NubTypeStruct> structTypes = [];
public NubTypeStruct? GetNamedStruct(string module, string name) => structTypes.GetValueOrDefault((module, name));
public static TypeResolver Create(string fileName, Ast ast, out List<Diagnostic> diagnostics)
{
diagnostics = [];
var resolver = new TypeResolver(fileName);
var moduleDefinitions = ast.Definitions.OfType<NodeDefinitionModule>().ToList();
if (moduleDefinitions.Count == 0)
diagnostics.Add(Diagnostic.Error($"'{fileName}' is not part of a module").At(fileName, 1, 1, 1).Build());
foreach (var moduleDefinition in moduleDefinitions.Skip(1))
diagnostics.Add(Diagnostic.Warning("Duplicate module definition").At(fileName, moduleDefinition).Build());
if (moduleDefinitions.Count >= 1)
{
var currentModule = moduleDefinitions[0].Name.Ident;
foreach (var structDef in ast.Definitions.OfType<NodeDefinitionStruct>())
{
if (resolver.structTypes.ContainsKey((currentModule, structDef.Name.Ident)))
{
diagnostics.Add(Diagnostic.Error($"Duplicate struct: {structDef.Name.Ident}").At(fileName, structDef.Name).Build());
continue;
}
resolver.structTypes.Add((currentModule, structDef.Name.Ident), new NubTypeStruct());
}
foreach (var structDef in ast.Definitions.OfType<NodeDefinitionStruct>())
{
var structType = resolver.structTypes[(currentModule, structDef.Name.Ident)];
try
{
structType.ResolveFields(structDef.Fields.Select(f => new NubTypeStruct.Field(f.Name.Ident, resolver.Resolve(f.Type))).ToList());
}
catch (CompileException e)
{
diagnostics.Add(e.Diagnostic);
}
}
}
return resolver;
}
public NubType Resolve(NodeType node)
{
return node switch
{
NodeTypeBool type => new NubTypeBool(),
NodeTypeCustom type => ResolveStruct(type),
NodeTypeFunc type => new NubTypeFunc(type.Parameters.Select(Resolve).ToList(), Resolve(type.ReturnType)),
NodeTypePointer type => new NubTypePointer(Resolve(type.To)),
NodeTypeSInt type => new NubTypeSInt(type.Width),
NodeTypeUInt type => new NubTypeUInt(type.Width),
NodeTypeString type => new NubTypeString(),
NodeTypeVoid type => new NubTypeVoid(),
_ => throw new ArgumentOutOfRangeException(nameof(node))
};
}
private NubTypeStruct ResolveStruct(NodeTypeCustom type)
{
var structType = structTypes.GetValueOrDefault((type.Module.Ident, type.Name.Ident));
if (structType == null)
throw new CompileException(Diagnostic.Error($"Unknown custom type: {type.Module.Ident}::{type.Name.Ident}").At(fileName, type).Build());
return structType;
}
}
public abstract class NubType : IEquatable<NubType>
{
public abstract override string ToString();

View File

@@ -28,7 +28,7 @@ public sealed class Parser(string fileName, List<Token> tokens)
diagnostics.Add(e.Diagnostic);
}
return new Ast(definitions);
return new Ast(definitions, fileName);
}
private NodeDefinition ParseDefinition()
@@ -82,12 +82,6 @@ public sealed class Parser(string fileName, List<Token> tokens)
return new NodeDefinitionModule(TokensFrom(startIndex), name);
}
if (TryExpectKeyword(Keyword.Import))
{
var name = ExpectIdent();
return new NodeDefinitionImport(TokensFrom(startIndex), name);
}
throw new CompileException(Diagnostic.Error("Not a valid definition").At(fileName, Peek()).Build());
}
@@ -244,7 +238,15 @@ public sealed class Parser(string fileName, List<Token> tokens)
}
else if (TryExpectIdent(out var ident))
{
expr = new NodeExpressionIdent(TokensFrom(startIndex), ident);
if (TryExpectSymbol(Symbol.ColonColon))
{
var name = ExpectIdent();
expr = new NodeExpressionModuleIdent(TokensFrom(startIndex), ident, name);
}
else
{
expr = new NodeExpressionLocalIdent(TokensFrom(startIndex), ident);
}
}
else if (TryExpectKeyword(Keyword.Struct))
{
@@ -532,8 +534,9 @@ public sealed class Parser(string fileName, List<Token> tokens)
}
}
public sealed class Ast(List<NodeDefinition> definitions)
public sealed class Ast(List<NodeDefinition> definitions, string fileName)
{
public string FileName = fileName;
public readonly List<NodeDefinition> Definitions = definitions;
}
@@ -549,11 +552,6 @@ public sealed class NodeDefinitionModule(List<Token> tokens, TokenIdent name) :
public readonly TokenIdent Name = name;
}
public sealed class NodeDefinitionImport(List<Token> tokens, TokenIdent name) : NodeDefinition(tokens)
{
public readonly TokenIdent Name = name;
}
public sealed class NodeDefinitionFunc(List<Token> tokens, TokenIdent name, List<NodeDefinitionFunc.Param> parameters, NodeStatement body, NodeType returnType) : NodeDefinition(tokens)
{
public readonly TokenIdent Name = name;
@@ -660,11 +658,17 @@ public sealed class NodeExpressionMemberAccess(List<Token> tokens, NodeExpressio
public readonly TokenIdent Name = name;
}
public sealed class NodeExpressionIdent(List<Token> tokens, TokenIdent value) : NodeExpression(tokens)
public sealed class NodeExpressionLocalIdent(List<Token> tokens, TokenIdent value) : NodeExpression(tokens)
{
public readonly TokenIdent Value = value;
}
public sealed class NodeExpressionModuleIdent(List<Token> tokens, TokenIdent module, TokenIdent value) : NodeExpression(tokens)
{
public readonly TokenIdent Module = module;
public readonly TokenIdent Value = value;
}
public sealed class NodeExpressionBinary(List<Token> tokens, NodeExpression left, NodeExpressionBinary.Op operation, NodeExpression right) : NodeExpression(tokens)
{
public readonly NodeExpression Left = left;

View File

@@ -1,6 +1,9 @@
using System.Diagnostics;
using Compiler;
var moduleGraphBuilder = ModuleGraph.Create();
var asts = new List<Ast>();
foreach (var fileName in args)
{
var file = File.ReadAllText(fileName);
@@ -21,19 +24,25 @@ foreach (var fileName in args)
if (parserDiagnostics.Any(x => x.Severity == DiagnosticSeverity.Error))
return 1;
var typeResolver = TypeResolver.Create(fileName, ast, out var typeResolverDiagnostics);
moduleGraphBuilder.AddAst(ast);
asts.Add(ast);
}
foreach (var diagnostic in typeResolverDiagnostics)
var moduleGraph = moduleGraphBuilder.Build(out var moduleGraphDiagnostics);
foreach (var diagnostic in moduleGraphDiagnostics)
DiagnosticFormatter.Print(diagnostic, Console.Error);
if (typeResolverDiagnostics.Any(x => x.Severity == DiagnosticSeverity.Error))
if (moduleGraphDiagnostics.Any(x => x.Severity == DiagnosticSeverity.Error))
return 1;
var functions = new List<TypedNodeDefinitionFunc>();
foreach (var function in ast.Definitions.OfType<NodeDefinitionFunc>())
foreach (var ast in asts)
{
var typedFunction = TypeChecker.CheckFunction(fileName, function, typeResolver, out var typeCheckerDiagnostics);
foreach (var func in ast.Definitions.OfType<NodeDefinitionFunc>())
{
var typedFunction = TypeChecker.CheckFunction(ast.FileName, func, moduleGraph, out var typeCheckerDiagnostics);
foreach (var diagnostic in typeCheckerDiagnostics)
DiagnosticFormatter.Print(diagnostic, Console.Error);
@@ -43,16 +52,15 @@ foreach (var fileName in args)
functions.Add(typedFunction);
}
}
var output = Generator.Emit(functions);
var output = Generator.Emit(functions, moduleGraph);
Directory.Delete(".build", recursive: true);
Directory.CreateDirectory(".build");
var outFilePath = Path.Combine(".build", Path.ChangeExtension(fileName, "c"));
File.WriteAllText(outFilePath, output);
File.WriteAllText(".build/out.c", output);
Process.Start("gcc", ["-Og", "-g", "-c", "-o", Path.ChangeExtension(outFilePath, "o"), outFilePath]);
}
Process.Start("gcc", ["-Og", "-g", "-o", ".build/out", ".build/out.c"]);
return 0;

View File

@@ -347,8 +347,6 @@ public sealed class Tokenizer(string fileName, string contents)
"while" => new TokenKeyword(line, startColumn, column - startColumn, Keyword.While),
"return" => new TokenKeyword(line, startColumn, column - startColumn, Keyword.Return),
"module" => new TokenKeyword(line, startColumn, column - startColumn, Keyword.Module),
"import" => new TokenKeyword(line, startColumn, column - startColumn, Keyword.Import),
"export" => new TokenKeyword(line, startColumn, column - startColumn, Keyword.Export),
"true" => new TokenBoolLiteral(line, startColumn, column - startColumn, true),
"false" => new TokenBoolLiteral(line, startColumn, column - startColumn, false),
_ => new TokenIdent(line, startColumn, column - startColumn, value)
@@ -482,8 +480,6 @@ public enum Keyword
While,
Return,
Module,
Import,
Export,
}
public sealed class TokenKeyword(int line, int column, int length, Keyword keyword) : Token(line, column, length)
@@ -546,8 +542,6 @@ public static class TokenExtensions
Keyword.While => "while",
Keyword.Return => "return",
Keyword.Module => "module",
Keyword.Import => "import",
Keyword.Export => "export",
_ => throw new ArgumentOutOfRangeException(nameof(symbol), symbol, null)
};
}

View File

@@ -1,13 +1,13 @@
namespace Compiler;
public sealed class TypeChecker(string fileName, NodeDefinitionFunc function, TypeResolver typeResolver)
public sealed class TypeChecker(string fileName, NodeDefinitionFunc function, ModuleGraph moduleGraph)
{
public static TypedNodeDefinitionFunc? CheckFunction(string fileName, NodeDefinitionFunc function, TypeResolver typeResolver, out List<Diagnostic> diagnostics)
public static TypedNodeDefinitionFunc? CheckFunction(string fileName, NodeDefinitionFunc function, ModuleGraph moduleGraph, out List<Diagnostic> diagnostics)
{
return new TypeChecker(fileName, function, typeResolver).CheckFunction(out diagnostics);
return new TypeChecker(fileName, function, moduleGraph).CheckFunction(out diagnostics);
}
private Scope scope = new(null);
private readonly Scope scope = new(null);
private TypedNodeDefinitionFunc? CheckFunction(out List<Diagnostic> diagnostics)
{
@@ -42,7 +42,7 @@ public sealed class TypeChecker(string fileName, NodeDefinitionFunc function, Ty
try
{
returnType = typeResolver.Resolve(function.ReturnType);
returnType = ResolveType(function.ReturnType);
}
catch (CompileException e)
{
@@ -57,7 +57,7 @@ public sealed class TypeChecker(string fileName, NodeDefinitionFunc function, Ty
private TypedNodeDefinitionFunc.Param CheckDefinitionFuncParameter(NodeDefinitionFunc.Param node)
{
return new TypedNodeDefinitionFunc.Param(node.Tokens, node.Name, typeResolver.Resolve(node.Type));
return new TypedNodeDefinitionFunc.Param(node.Tokens, node.Name, ResolveType(node.Type));
}
private TypedNodeStatement CheckStatement(NodeStatement node)
@@ -102,7 +102,7 @@ public sealed class TypeChecker(string fileName, NodeDefinitionFunc function, Ty
private TypedNodeStatementVariableDeclaration CheckStatementVariableDeclaration(NodeStatementVariableDeclaration statement)
{
var type = typeResolver.Resolve(statement.Type);
var type = ResolveType(statement.Type);
var value = CheckExpression(statement.Value);
if (type != value.Type)
@@ -125,7 +125,8 @@ public sealed class TypeChecker(string fileName, NodeDefinitionFunc function, Ty
NodeExpressionBinary expression => CheckExpressionBinary(expression),
NodeExpressionUnary expression => CheckExpressionUnary(expression),
NodeExpressionBoolLiteral expression => CheckExpressionBoolLiteral(expression),
NodeExpressionIdent expression => CheckExpressionIdent(expression),
NodeExpressionLocalIdent expression => CheckExpressionIdent(expression),
NodeExpressionModuleIdent expression => CheckExpressionModuleIdent(expression),
NodeExpressionIntLiteral expression => CheckExpressionIntLiteral(expression),
NodeExpressionMemberAccess expression => CheckExpressionMemberAccess(expression),
NodeExpressionStringLiteral expression => CheckExpressionStringLiteral(expression),
@@ -272,13 +273,19 @@ public sealed class TypeChecker(string fileName, NodeDefinitionFunc function, Ty
return new TypedNodeExpressionBoolLiteral(expression.Tokens, new NubTypeBool(), expression.Value);
}
private TypedNodeExpressionIdent CheckExpressionIdent(NodeExpressionIdent expression)
private TypedNodeExpressionLocalIdent CheckExpressionIdent(NodeExpressionLocalIdent expression)
{
var type = scope.GetIdentifierType(expression.Value.Ident);
if (type == null)
throw new CompileException(Diagnostic.Error($"Identifier '{expression.Value.Ident}' is not declared").At(fileName, expression.Value).Build());
return new TypedNodeExpressionIdent(expression.Tokens, type, expression.Value);
return new TypedNodeExpressionLocalIdent(expression.Tokens, type, expression.Value);
}
private TypedNodeExpressionModuleIdent CheckExpressionModuleIdent(NodeExpressionModuleIdent expression)
{
var identifierType = moduleGraph.ResolveIdentifier(expression.Module.Ident, expression.Value.Ident);
return new TypedNodeExpressionModuleIdent(expression.Tokens, identifierType, expression.Module, expression.Value);
}
private TypedNodeExpressionIntLiteral CheckExpressionIntLiteral(NodeExpressionIntLiteral expression)
@@ -306,7 +313,7 @@ public sealed class TypeChecker(string fileName, NodeDefinitionFunc function, Ty
private TypedNodeExpressionStructLiteral CheckExpressionStructLiteral(NodeExpressionStructLiteral expression)
{
var type = typeResolver.GetNamedStruct(expression.Module.Ident, expression.Name.Ident);
var type = moduleGraph.ResolveStruct(expression.Module.Ident, expression.Name.Ident);
if (type == null)
throw new CompileException(Diagnostic.Error($"Undeclared struct '{expression.Module.Ident}::{expression.Name.Ident}'").At(fileName, expression.Name).Build());
@@ -327,6 +334,22 @@ public sealed class TypeChecker(string fileName, NodeDefinitionFunc function, Ty
return new TypedNodeExpressionStructLiteral(expression.Tokens, type, initializers);
}
private NubType ResolveType(NodeType node)
{
return node switch
{
NodeTypeBool type => new NubTypeBool(),
NodeTypeCustom type => moduleGraph.ResolveStruct(type.Module.Ident, type.Name.Ident),
NodeTypeFunc type => new NubTypeFunc(type.Parameters.Select(ResolveType).ToList(), ResolveType(type.ReturnType)),
NodeTypePointer type => new NubTypePointer(ResolveType(type.To)),
NodeTypeSInt type => new NubTypeSInt(type.Width),
NodeTypeUInt type => new NubTypeUInt(type.Width),
NodeTypeString type => new NubTypeString(),
NodeTypeVoid type => new NubTypeVoid(),
_ => throw new ArgumentOutOfRangeException(nameof(node))
};
}
private class Scope(Scope? parent)
{
private readonly Dictionary<string, NubType> identifiers = new();
@@ -366,18 +389,6 @@ public sealed class TypedNodeDefinitionFunc(List<Token> tokens, TokenIdent name,
}
}
public sealed class TypedNodeDefinitionStruct(List<Token> tokens, TokenIdent name, List<TypedNodeDefinitionStruct.Field> fields) : TypedNodeDefinition(tokens)
{
public readonly TokenIdent Name = name;
public readonly List<Field> Fields = fields;
public sealed class Field(List<Token> tokens, TokenIdent name, NubType type) : TypedNode(tokens)
{
public readonly TokenIdent Name = name;
public readonly NubType Type = type;
}
}
public abstract class TypedNodeStatement(List<Token> tokens) : TypedNode(tokens);
public sealed class TypedNodeStatementBlock(List<Token> tokens, List<TypedNodeStatement> statements) : TypedNodeStatement(tokens)
@@ -459,11 +470,17 @@ public sealed class TypedNodeExpressionMemberAccess(List<Token> tokens, NubType
public readonly TokenIdent Name = name;
}
public sealed class TypedNodeExpressionIdent(List<Token> tokens, NubType type, TokenIdent value) : TypedNodeExpression(tokens, type)
public sealed class TypedNodeExpressionLocalIdent(List<Token> tokens, NubType type, TokenIdent value) : TypedNodeExpression(tokens, type)
{
public readonly TokenIdent Value = value;
}
public sealed class TypedNodeExpressionModuleIdent(List<Token> tokens, NubType type, TokenIdent module, TokenIdent value) : TypedNodeExpression(tokens, type)
{
public readonly TokenIdent Module = module;
public readonly TokenIdent Value = value;
}
public sealed class TypedNodeExpressionBinary(List<Token> tokens, NubType type, TypedNodeExpression left, TypedNodeExpressionBinary.Op operation, TypedNodeExpression right) : TypedNodeExpression(tokens, type)
{
public readonly TypedNodeExpression Left = left;

View File

@@ -1,10 +1,5 @@
module main
struct person {
age: i32
name: string
}
func main(): i32 {
let x: i32 = 23
x = 24
@@ -25,11 +20,8 @@ func main(): i32 {
x = i
}
let me: main::person = struct main::person { age = 21 name = "Oliver" }
let me: test::person = struct test::person { age = 21 name = "Oliver" }
do_something(me.name)
test::do_something(me.name)
return x
}
func do_something(text: string): void {
}

9
compiler/test2.nub Normal file
View File

@@ -0,0 +1,9 @@
module test
struct person {
age: i32
name: string
}
func do_something(name: string): void {
}