WIP: dev #1
@@ -399,13 +399,13 @@ public class Generator
|
|||||||
|
|
||||||
private string EmitExpressionEnumLiteral(TypedNodeExpressionEnumLiteral expression)
|
private string EmitExpressionEnumLiteral(TypedNodeExpressionEnumLiteral expression)
|
||||||
{
|
{
|
||||||
var enumType = (NubTypeEnumVariant)expression.Type;
|
var enumType = (NubTypeEnum)expression.Type;
|
||||||
|
|
||||||
if (!moduleGraph.TryResolveType(enumType.Module, enumType.EnumName, true, out var info))
|
if (!moduleGraph.TryResolveType(enumType.Module, enumType.Name, true, out var info))
|
||||||
throw new UnreachableException();
|
throw new UnreachableException();
|
||||||
|
|
||||||
var enumInfo = (Module.TypeInfoEnum)info;
|
var enumInfo = (Module.TypeInfoEnum)info;
|
||||||
var tag = enumInfo.Variants.ToList().FindIndex(x => x.Name == enumType.VariantName);
|
var tag = enumInfo.Variants.ToList().FindIndex(x => x.Name == expression.EnumVariant);
|
||||||
|
|
||||||
var initializerValues = new Dictionary<string, string>();
|
var initializerValues = new Dictionary<string, string>();
|
||||||
|
|
||||||
@@ -417,7 +417,7 @@ public class Generator
|
|||||||
|
|
||||||
var initializerStrings = initializerValues.Select(x => $".{x.Key} = {x.Value}");
|
var initializerStrings = initializerValues.Select(x => $".{x.Key} = {x.Value}");
|
||||||
|
|
||||||
return $"({CType(expression.Type)}){{ .tag = {tag}, .{enumType.VariantName} = {{{string.Join(", ", initializerStrings)}}} }}";
|
return $"({CType(expression.Type)}){{ .tag = {tag}, .{expression.EnumVariant} = {{ {string.Join(", ", initializerStrings)} }} }}";
|
||||||
}
|
}
|
||||||
|
|
||||||
private string EmitExpressionMemberAccess(TypedNodeExpressionMemberAccess expression)
|
private string EmitExpressionMemberAccess(TypedNodeExpressionMemberAccess expression)
|
||||||
|
|||||||
@@ -135,32 +135,6 @@ public class NubTypeEnum : NubType
|
|||||||
public override string ToString() => $"enum {Module}::{Name}";
|
public override string ToString() => $"enum {Module}::{Name}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NubTypeEnumVariant : NubType
|
|
||||||
{
|
|
||||||
private static readonly Dictionary<(string Module, string EnumName, string VariantName), NubTypeEnumVariant> Cache = new();
|
|
||||||
|
|
||||||
public static NubTypeEnumVariant Get(string module, string enumName, string variantName)
|
|
||||||
{
|
|
||||||
if (!Cache.TryGetValue((module, enumName, variantName), out var enumType))
|
|
||||||
Cache[(module, enumName, variantName)] = enumType = new NubTypeEnumVariant(module, enumName, variantName);
|
|
||||||
|
|
||||||
return enumType;
|
|
||||||
}
|
|
||||||
|
|
||||||
private NubTypeEnumVariant(string module, string enumName, string variantName)
|
|
||||||
{
|
|
||||||
Module = module;
|
|
||||||
EnumName = enumName;
|
|
||||||
VariantName = variantName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Module { get; }
|
|
||||||
public string EnumName { get; }
|
|
||||||
public string VariantName { get; }
|
|
||||||
|
|
||||||
public override string ToString() => $"enum {Module}::{EnumName}.{VariantName}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public class NubTypePointer : NubType
|
public class NubTypePointer : NubType
|
||||||
{
|
{
|
||||||
private static readonly Dictionary<NubType, NubTypePointer> Cache = new();
|
private static readonly Dictionary<NubType, NubTypePointer> Cache = new();
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public class TypeChecker
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
scope.DeclareIdentifier(parameter.Name.Ident, parameterType);
|
scope.DeclareIdentifier(parameter.Name.Ident, parameterType, null);
|
||||||
parameters.Add(new TypedNodeDefinitionFunc.Param(parameter.Tokens, parameter.Name, parameterType));
|
parameters.Add(new TypedNodeDefinitionFunc.Param(parameter.Tokens, parameter.Name, parameterType));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,7 +132,7 @@ public class TypeChecker
|
|||||||
if (type != value.Type)
|
if (type != value.Type)
|
||||||
throw new CompileException(Diagnostic.Error("Type of variable does match type of assigned value").At(fileName, value).Build());
|
throw new CompileException(Diagnostic.Error("Type of variable does match type of assigned value").At(fileName, value).Build());
|
||||||
|
|
||||||
scope.DeclareIdentifier(statement.Name.Ident, type);
|
scope.DeclareIdentifier(statement.Name.Ident, type, value.EnumVariant);
|
||||||
|
|
||||||
return new TypedNodeStatementVariableDeclaration(statement.Tokens, statement.Name, type, value);
|
return new TypedNodeStatementVariableDeclaration(statement.Tokens, statement.Name, type, value);
|
||||||
}
|
}
|
||||||
@@ -152,7 +152,7 @@ public class TypeChecker
|
|||||||
{
|
{
|
||||||
using (scope.EnterScope())
|
using (scope.EnterScope())
|
||||||
{
|
{
|
||||||
scope.DeclareIdentifier(@case.VariableName.Ident, NubTypeEnumVariant.Get(enumType.Module, enumType.Name, @case.Type.Ident));
|
scope.DeclareIdentifier(@case.VariableName.Ident, NubTypeEnum.Get(enumType.Module, enumType.Name), @case.Type.Ident);
|
||||||
var body = CheckStatement(@case.Body);
|
var body = CheckStatement(@case.Body);
|
||||||
cases.Add(new TypedNodeStatementMatch.Case(@case.Tokens, @case.Type, @case.VariableName, body));
|
cases.Add(new TypedNodeStatementMatch.Case(@case.Tokens, @case.Type, @case.VariableName, body));
|
||||||
}
|
}
|
||||||
@@ -321,10 +321,13 @@ public class TypeChecker
|
|||||||
private TypedNodeExpressionLocalIdent CheckExpressionIdent(NodeExpressionLocalIdent expression)
|
private TypedNodeExpressionLocalIdent CheckExpressionIdent(NodeExpressionLocalIdent expression)
|
||||||
{
|
{
|
||||||
var type = scope.GetIdentifierType(expression.Value.Ident);
|
var type = scope.GetIdentifierType(expression.Value.Ident);
|
||||||
if (type == null)
|
if (!type.HasValue)
|
||||||
throw new CompileException(Diagnostic.Error($"Identifier '{expression.Value.Ident}' is not declared").At(fileName, expression.Value).Build());
|
throw new CompileException(Diagnostic.Error($"Identifier '{expression.Value.Ident}' is not declared").At(fileName, expression.Value).Build());
|
||||||
|
|
||||||
return new TypedNodeExpressionLocalIdent(expression.Tokens, type, expression.Value);
|
return new TypedNodeExpressionLocalIdent(expression.Tokens, type.Value.Type, expression.Value)
|
||||||
|
{
|
||||||
|
EnumVariant = type.Value.EnumVariant
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private TypedNodeExpressionModuleIdent CheckExpressionModuleIdent(NodeExpressionModuleIdent expression)
|
private TypedNodeExpressionModuleIdent CheckExpressionModuleIdent(NodeExpressionModuleIdent expression)
|
||||||
@@ -368,20 +371,23 @@ public class TypeChecker
|
|||||||
|
|
||||||
return new TypedNodeExpressionMemberAccess(expression.Tokens, field.Type, target, expression.Name);
|
return new TypedNodeExpressionMemberAccess(expression.Tokens, field.Type, target, expression.Name);
|
||||||
}
|
}
|
||||||
case NubTypeEnumVariant enumVariantType:
|
case NubTypeEnum enumType:
|
||||||
{
|
{
|
||||||
if (!moduleGraph.TryResolveModule(enumVariantType.Module, out var module))
|
if (target.EnumVariant == null)
|
||||||
throw new CompileException(Diagnostic.Error($"Module '{enumVariantType.Module}' not found").At(fileName, expression.Target).Build());
|
throw new CompileException(Diagnostic.Error($"Cannot access member '{expression.Name.Ident}' on enum '{enumType}' without knowing the variant").At(fileName, target).Build());
|
||||||
|
|
||||||
if (!module.TryResolveType(enumVariantType.EnumName, moduleName == enumVariantType.Module, out var typeDef))
|
if (!moduleGraph.TryResolveModule(enumType.Module, out var module))
|
||||||
throw new CompileException(Diagnostic.Error($"Type '{enumVariantType.EnumName}' not found in module '{enumVariantType.Module}'").At(fileName, expression.Target).Build());
|
throw new CompileException(Diagnostic.Error($"Module '{enumType.Module}' not found").At(fileName, expression.Target).Build());
|
||||||
|
|
||||||
|
if (!module.TryResolveType(enumType.Name, moduleName == enumType.Module, out var typeDef))
|
||||||
|
throw new CompileException(Diagnostic.Error($"Type '{enumType.Name}' not found in module '{enumType.Module}'").At(fileName, expression.Target).Build());
|
||||||
|
|
||||||
if (typeDef is not Module.TypeInfoEnum enumDef)
|
if (typeDef is not Module.TypeInfoEnum enumDef)
|
||||||
throw new CompileException(Diagnostic.Error($"Type '{enumVariantType.Module}::{enumVariantType.EnumName}' is not an enum").At(fileName, expression.Target).Build());
|
throw new CompileException(Diagnostic.Error($"Type '{enumType.Module}::{enumType.Name}' is not an enum").At(fileName, expression.Target).Build());
|
||||||
|
|
||||||
var variant = enumDef.Variants.FirstOrDefault(x => x.Name == enumVariantType.VariantName);
|
var variant = enumDef.Variants.FirstOrDefault(x => x.Name == target.EnumVariant);
|
||||||
if (variant == null)
|
if (variant == null)
|
||||||
throw new CompileException(Diagnostic.Error($"Type '{target.Type}' does not have a variant '{enumVariantType.VariantName}'").At(fileName, expression.Target).Build());
|
throw new CompileException(Diagnostic.Error($"Type '{target.Type}' does not have a variant '{target.EnumVariant}'").At(fileName, expression.Target).Build());
|
||||||
|
|
||||||
var field = variant.Fields.FirstOrDefault(x => x.Name == expression.Name.Ident);
|
var field = variant.Fields.FirstOrDefault(x => x.Name == expression.Name.Ident);
|
||||||
if (field == null)
|
if (field == null)
|
||||||
@@ -471,7 +477,10 @@ public class TypeChecker
|
|||||||
initializers.Add(new TypedNodeExpressionEnumLiteral.Initializer(initializer.Tokens, initializer.Name, value));
|
initializers.Add(new TypedNodeExpressionEnumLiteral.Initializer(initializer.Tokens, initializer.Name, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new TypedNodeExpressionEnumLiteral(expression.Tokens, NubTypeEnumVariant.Get(expression.Module.Ident, expression.EnumName.Ident, expression.VariantName.Ident), initializers);
|
return new TypedNodeExpressionEnumLiteral(expression.Tokens, NubTypeEnum.Get(expression.Module.Ident, expression.EnumName.Ident), initializers)
|
||||||
|
{
|
||||||
|
EnumVariant = expression.VariantName.Ident
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private NubType ResolveType(NodeType node)
|
private NubType ResolveType(NodeType node)
|
||||||
@@ -510,7 +519,7 @@ public class TypeChecker
|
|||||||
|
|
||||||
private sealed class Scope
|
private sealed class Scope
|
||||||
{
|
{
|
||||||
private readonly Stack<Dictionary<string, NubType>> scopes = new();
|
private readonly Stack<Dictionary<string, (NubType Type, string? EnumVariant)>> scopes = new();
|
||||||
|
|
||||||
public IDisposable EnterScope()
|
public IDisposable EnterScope()
|
||||||
{
|
{
|
||||||
@@ -518,12 +527,12 @@ public class TypeChecker
|
|||||||
return new ScopeGuard(this);
|
return new ScopeGuard(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DeclareIdentifier(string name, NubType type)
|
public void DeclareIdentifier(string name, NubType type, string? enumVariant)
|
||||||
{
|
{
|
||||||
scopes.Peek().Add(name, type);
|
scopes.Peek().Add(name, (type, enumVariant));
|
||||||
}
|
}
|
||||||
|
|
||||||
public NubType? GetIdentifierType(string name)
|
public (NubType Type, string? EnumVariant)? GetIdentifierType(string name)
|
||||||
{
|
{
|
||||||
foreach (var scope in scopes)
|
foreach (var scope in scopes)
|
||||||
{
|
{
|
||||||
@@ -640,6 +649,7 @@ public class TypedNodeStatementMatch(List<Token> tokens, TypedNodeExpression tar
|
|||||||
public abstract class TypedNodeExpression(List<Token> tokens, NubType type) : TypedNode(tokens)
|
public abstract class TypedNodeExpression(List<Token> tokens, NubType type) : TypedNode(tokens)
|
||||||
{
|
{
|
||||||
public NubType Type { get; } = type;
|
public NubType Type { get; } = type;
|
||||||
|
public string? EnumVariant { get; init; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class TypedNodeExpressionIntLiteral(List<Token> tokens, NubType type, TokenIntLiteral value) : TypedNodeExpression(tokens, type)
|
public class TypedNodeExpressionIntLiteral(List<Token> tokens, NubType type, TokenIntLiteral value) : TypedNodeExpression(tokens, type)
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
set -e
|
||||||
|
|
||||||
pushd math
|
pushd math
|
||||||
dotnet run --project ../../compiler math.nub --type=lib
|
dotnet run --project ../../compiler math.nub --type=lib
|
||||||
pushd .build
|
pushd .build
|
||||||
|
|||||||
Reference in New Issue
Block a user