enums
This commit is contained in:
@@ -80,6 +80,8 @@ public abstract record LValueExpressionNode(List<Token> Tokens, NubType Type) :
|
|||||||
|
|
||||||
public abstract record RValueExpressionNode(List<Token> Tokens, NubType Type) : ExpressionNode(Tokens, Type);
|
public abstract record RValueExpressionNode(List<Token> Tokens, NubType Type) : ExpressionNode(Tokens, Type);
|
||||||
|
|
||||||
|
public abstract record IntermediateExpression(List<Token> Tokens) : ExpressionNode(Tokens, new NubVoidType());
|
||||||
|
|
||||||
public record StringLiteralNode(List<Token> Tokens, string Value) : RValueExpressionNode(Tokens, new NubStringType());
|
public record StringLiteralNode(List<Token> Tokens, string Value) : RValueExpressionNode(Tokens, new NubStringType());
|
||||||
|
|
||||||
public record CStringLiteralNode(List<Token> Tokens, string Value) : RValueExpressionNode(Tokens, new NubCStringType());
|
public record CStringLiteralNode(List<Token> Tokens, string Value) : RValueExpressionNode(Tokens, new NubCStringType());
|
||||||
@@ -142,4 +144,6 @@ public record SizeBuiltinNode(List<Token> Tokens, NubType Type, NubType TargetTy
|
|||||||
|
|
||||||
public record FloatToIntBuiltinNode(List<Token> Tokens, NubType Type, ExpressionNode Value, NubFloatType ValueType, NubIntType TargetType) : RValueExpressionNode(Tokens, Type);
|
public record FloatToIntBuiltinNode(List<Token> Tokens, NubType Type, ExpressionNode Value, NubFloatType ValueType, NubIntType TargetType) : RValueExpressionNode(Tokens, Type);
|
||||||
|
|
||||||
|
public record EnumReferenceIntermediateNode(List<Token> Tokens, string Module, string Name) : IntermediateExpression(Tokens);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -557,55 +557,56 @@ public sealed class TypeChecker
|
|||||||
return new FuncCallNode(expression.Tokens, funcType.ReturnType, accessor, parameters);
|
return new FuncCallNode(expression.Tokens, funcType.ReturnType, accessor, parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ExpressionNode CheckIdentifier(ExpressionSyntax expression, string moduleName, string name)
|
||||||
|
{
|
||||||
|
if (!_importedModules.TryGetValue(moduleName, out var module))
|
||||||
|
{
|
||||||
|
throw new TypeCheckerException(Diagnostic
|
||||||
|
.Error($"Module {moduleName} not found")
|
||||||
|
.WithHelp($"import \"{moduleName}\"")
|
||||||
|
.At(expression)
|
||||||
|
.Build());
|
||||||
|
}
|
||||||
|
|
||||||
|
var function = module.Functions(IsCurretModule(moduleName)).FirstOrDefault(x => x.Name == name);
|
||||||
|
if (function != null)
|
||||||
|
{
|
||||||
|
using (BeginRootScope(moduleName))
|
||||||
|
{
|
||||||
|
var parameters = function.Prototype.Parameters.Select(x => ResolveType(x.Type)).ToList();
|
||||||
|
var type = new NubFuncType(parameters, ResolveType(function.Prototype.ReturnType));
|
||||||
|
return new FuncIdentifierNode(expression.Tokens, type, moduleName, name, function.Prototype.ExternSymbol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var enumDef = module.Enums(IsCurretModule(moduleName)).FirstOrDefault(x => x.Name == name);
|
||||||
|
if (enumDef != null)
|
||||||
|
{
|
||||||
|
return new EnumReferenceIntermediateNode(expression.Tokens, moduleName, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new TypeCheckerException(Diagnostic
|
||||||
|
.Error($"No exported symbol {name} not found in module {moduleName}")
|
||||||
|
.At(expression)
|
||||||
|
.Build());
|
||||||
|
}
|
||||||
|
|
||||||
private ExpressionNode CheckLocalIdentifier(LocalIdentifierSyntax expression, NubType? _)
|
private ExpressionNode CheckLocalIdentifier(LocalIdentifierSyntax expression, NubType? _)
|
||||||
{
|
{
|
||||||
|
// note(nub31): Local identifiers can be variables or a symbol in a module
|
||||||
var scopeIdent = Scope.LookupVariable(expression.Name);
|
var scopeIdent = Scope.LookupVariable(expression.Name);
|
||||||
if (scopeIdent != null)
|
if (scopeIdent != null)
|
||||||
{
|
{
|
||||||
return new VariableIdentifierNode(expression.Tokens, scopeIdent.Type, expression.Name);
|
return new VariableIdentifierNode(expression.Tokens, scopeIdent.Type, expression.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
var module = _importedModules[Scope.Module];
|
return CheckIdentifier(expression, Scope.Module, expression.Name);
|
||||||
var function = module.Functions(true).FirstOrDefault(x => x.Name == expression.Name);
|
|
||||||
|
|
||||||
if (function != null)
|
|
||||||
{
|
|
||||||
var parameters = function.Prototype.Parameters.Select(x => ResolveType(x.Type)).ToList();
|
|
||||||
var type = new NubFuncType(parameters, ResolveType(function.Prototype.ReturnType));
|
|
||||||
return new FuncIdentifierNode(expression.Tokens, type, Scope.Module, expression.Name, function.Prototype.ExternSymbol);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new TypeCheckerException(Diagnostic.Error($"Symbol {expression.Name} not found").At(expression).Build());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ExpressionNode CheckModuleIdentifier(ModuleIdentifierSyntax expression, NubType? _)
|
private ExpressionNode CheckModuleIdentifier(ModuleIdentifierSyntax expression, NubType? _)
|
||||||
{
|
{
|
||||||
if (!_importedModules.TryGetValue(expression.Module, out var module))
|
// note(nub31): Unlike local identifiers, module identifiers does not look for local variables
|
||||||
{
|
return CheckIdentifier(expression, expression.Module, expression.Name);
|
||||||
throw new TypeCheckerException(Diagnostic
|
|
||||||
.Error($"Module {expression.Module} not found")
|
|
||||||
.WithHelp($"import \"{expression.Module}\"")
|
|
||||||
.At(expression)
|
|
||||||
.Build());
|
|
||||||
}
|
|
||||||
|
|
||||||
var includePrivate = expression.Module == Scope.Module;
|
|
||||||
|
|
||||||
var function = module.Functions(includePrivate).FirstOrDefault(x => x.Name == expression.Name);
|
|
||||||
if (function != null)
|
|
||||||
{
|
|
||||||
using (BeginRootScope(expression.Module))
|
|
||||||
{
|
|
||||||
var parameters = function.Prototype.Parameters.Select(x => ResolveType(x.Type)).ToList();
|
|
||||||
var type = new NubFuncType(parameters, ResolveType(function.Prototype.ReturnType));
|
|
||||||
return new FuncIdentifierNode(expression.Tokens, type, expression.Module, expression.Name, function.Prototype.ExternSymbol);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new TypeCheckerException(Diagnostic
|
|
||||||
.Error($"No exported symbol {expression.Name} not found in module {expression.Module}")
|
|
||||||
.At(expression)
|
|
||||||
.Build());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ExpressionNode CheckStringLiteral(StringLiteralSyntax expression, NubType? expectedType)
|
private ExpressionNode CheckStringLiteral(StringLiteralSyntax expression, NubType? expectedType)
|
||||||
@@ -668,29 +669,56 @@ public sealed class TypeChecker
|
|||||||
private ExpressionNode CheckMemberAccess(MemberAccessSyntax expression, NubType? _)
|
private ExpressionNode CheckMemberAccess(MemberAccessSyntax expression, NubType? _)
|
||||||
{
|
{
|
||||||
var target = CheckExpression(expression.Target);
|
var target = CheckExpression(expression.Target);
|
||||||
switch (target.Type)
|
|
||||||
{
|
|
||||||
case NubStructType structType:
|
|
||||||
{
|
|
||||||
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(expression.Tokens, field.Type, target, expression.Member);
|
if (target is EnumReferenceIntermediateNode enumReferenceIntermediate)
|
||||||
}
|
{
|
||||||
default:
|
var enumDef = _importedModules[enumReferenceIntermediate.Module]
|
||||||
|
.Enums(IsCurretModule(enumReferenceIntermediate.Module))
|
||||||
|
.First(x => x.Name == enumReferenceIntermediate.Name);
|
||||||
|
|
||||||
|
var field = enumDef.Fields.FirstOrDefault(x => x.Name == expression.Member);
|
||||||
|
if (field == null)
|
||||||
{
|
{
|
||||||
throw new TypeCheckerException(Diagnostic
|
throw new TypeCheckerException(Diagnostic
|
||||||
.Error($"Cannot access struct member on non-struct type {target.Type}")
|
.Error($"Enum {Scope.Module}::{enumReferenceIntermediate.Name} does not have a field named {expression.Member}")
|
||||||
|
.At(enumDef)
|
||||||
|
.Build());
|
||||||
|
}
|
||||||
|
|
||||||
|
var enumType = enumDef.Type != null ? ResolveType(enumDef.Type) : new NubIntType(false, 64);
|
||||||
|
if (enumType is not NubIntType enumIntType)
|
||||||
|
{
|
||||||
|
throw new TypeCheckerException(Diagnostic.Error("Enum type must be an int type").At(enumDef.Type).Build());
|
||||||
|
}
|
||||||
|
|
||||||
|
return enumIntType.Width switch
|
||||||
|
{
|
||||||
|
8 => enumIntType.Signed ? new I8LiteralNode(expression.Tokens, (sbyte)field.Value) : new U8LiteralNode(expression.Tokens, (byte)field.Value),
|
||||||
|
16 => enumIntType.Signed ? new I16LiteralNode(expression.Tokens, (short)field.Value) : new U16LiteralNode(expression.Tokens, (ushort)field.Value),
|
||||||
|
32 => enumIntType.Signed ? new I32LiteralNode(expression.Tokens, (int)field.Value) : new U32LiteralNode(expression.Tokens, (uint)field.Value),
|
||||||
|
64 => enumIntType.Signed ? new I64LiteralNode(expression.Tokens, field.Value) : new U64LiteralNode(expression.Tokens, (ulong)field.Value),
|
||||||
|
_ => throw new ArgumentOutOfRangeException()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target.Type is NubStructType structType)
|
||||||
|
{
|
||||||
|
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)
|
.At(expression)
|
||||||
.Build());
|
.Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return new StructFieldAccessNode(expression.Tokens, field.Type, target, expression.Member);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
throw new TypeCheckerException(Diagnostic
|
||||||
|
.Error($"Cannot access struct member {expression.Member} on type {target.Type}")
|
||||||
|
.At(expression)
|
||||||
|
.Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
private StructInitializerNode CheckStructInitializer(StructInitializerSyntax expression, NubType? expectedType)
|
private StructInitializerNode CheckStructInitializer(StructInitializerSyntax expression, NubType? expectedType)
|
||||||
@@ -831,35 +859,39 @@ public sealed class TypeChecker
|
|||||||
|
|
||||||
private NubType ResolveCustomType(CustomTypeSyntax customType)
|
private NubType ResolveCustomType(CustomTypeSyntax customType)
|
||||||
{
|
{
|
||||||
var key = (customType.Module ?? Scope.Module, customType.Name);
|
if (!_importedModules.TryGetValue(customType.Module ?? Scope.Module, out var module))
|
||||||
|
|
||||||
if (_typeCache.TryGetValue(key, out var cachedType))
|
|
||||||
{
|
{
|
||||||
return cachedType;
|
throw new TypeCheckerException(Diagnostic
|
||||||
|
.Error($"Module {customType.Module ?? Scope.Module} not found")
|
||||||
|
.WithHelp($"import \"{customType.Module ?? Scope.Module}\"")
|
||||||
|
.At(customType)
|
||||||
|
.Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_resolvingTypes.Add(key))
|
var enumDef = module.Enums(IsCurretModule(customType.Module)).FirstOrDefault(x => x.Name == customType.Name);
|
||||||
|
if (enumDef != null)
|
||||||
{
|
{
|
||||||
var placeholder = new NubStructType(customType.Module ?? Scope.Module, customType.Name, []);
|
return enumDef.Type != null ? ResolveType(enumDef.Type) : new NubIntType(false, 64);
|
||||||
_typeCache[key] = placeholder;
|
|
||||||
return placeholder;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
var structDef = module.Structs(IsCurretModule(customType.Module)).FirstOrDefault(x => x.Name == customType.Name);
|
||||||
|
if (structDef != null)
|
||||||
{
|
{
|
||||||
if (!_importedModules.TryGetValue(customType.Module ?? Scope.Module, out var module))
|
var key = (customType.Module ?? Scope.Module, customType.Name);
|
||||||
|
|
||||||
|
if (_typeCache.TryGetValue(key, out var cachedType))
|
||||||
{
|
{
|
||||||
throw new TypeCheckerException(Diagnostic
|
return cachedType;
|
||||||
.Error($"Module {customType.Module} not found")
|
|
||||||
.WithHelp($"import \"{customType.Module}\"")
|
|
||||||
.At(customType)
|
|
||||||
.Build());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var includePrivate = customType.Module == Scope.Module;
|
if (!_resolvingTypes.Add(key))
|
||||||
|
{
|
||||||
|
var placeholder = new NubStructType(customType.Module ?? Scope.Module, customType.Name, []);
|
||||||
|
_typeCache[key] = placeholder;
|
||||||
|
return placeholder;
|
||||||
|
}
|
||||||
|
|
||||||
var structDef = module.Structs(includePrivate).FirstOrDefault(x => x.Name == customType.Name);
|
try
|
||||||
if (structDef != null)
|
|
||||||
{
|
{
|
||||||
var result = new NubStructType(customType.Module ?? Scope.Module, structDef.Name, []);
|
var result = new NubStructType(customType.Module ?? Scope.Module, structDef.Name, []);
|
||||||
_typeCache[key] = result;
|
_typeCache[key] = result;
|
||||||
@@ -871,16 +903,26 @@ public sealed class TypeChecker
|
|||||||
result.Fields.AddRange(fields);
|
result.Fields.AddRange(fields);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_resolvingTypes.Remove(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
throw new TypeCheckerException(Diagnostic
|
throw new TypeCheckerException(Diagnostic
|
||||||
.Error($"Type {customType.Name} not found in module {customType.Module}")
|
.Error($"Type {customType.Name} not found in module {customType.Module ?? Scope.Module}")
|
||||||
.At(customType)
|
.At(customType)
|
||||||
.Build());
|
.Build());
|
||||||
}
|
}
|
||||||
finally
|
|
||||||
|
private bool IsCurretModule(string? module)
|
||||||
|
{
|
||||||
|
if (module == null)
|
||||||
{
|
{
|
||||||
_resolvingTypes.Remove(key);
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return module == Scope.Module;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using NubLang.Ast;
|
using NubLang.Ast;
|
||||||
using NubLang.Syntax;
|
using NubLang.Syntax;
|
||||||
@@ -255,6 +256,11 @@ public class Generator
|
|||||||
|
|
||||||
private string EmitExpression(ExpressionNode expressionNode)
|
private string EmitExpression(ExpressionNode expressionNode)
|
||||||
{
|
{
|
||||||
|
if (expressionNode is IntermediateExpression)
|
||||||
|
{
|
||||||
|
throw new UnreachableException("Type checker fucked up");
|
||||||
|
}
|
||||||
|
|
||||||
var expr = expressionNode switch
|
var expr = expressionNode switch
|
||||||
{
|
{
|
||||||
ArrayIndexAccessNode arrayIndexAccessNode => EmitArrayIndexAccess(arrayIndexAccessNode),
|
ArrayIndexAccessNode arrayIndexAccessNode => EmitArrayIndexAccess(arrayIndexAccessNode),
|
||||||
|
|||||||
@@ -36,4 +36,12 @@ public sealed class Module
|
|||||||
.Where(x => x.Exported || includePrivate)
|
.Where(x => x.Exported || includePrivate)
|
||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<EnumSyntax> Enums(bool includePrivate)
|
||||||
|
{
|
||||||
|
return _definitions
|
||||||
|
.OfType<EnumSyntax>()
|
||||||
|
.Where(x => x.Exported || includePrivate)
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -78,9 +78,10 @@ public sealed class Parser
|
|||||||
{
|
{
|
||||||
Symbol.Func => ParseFunc(startIndex, exported, null),
|
Symbol.Func => ParseFunc(startIndex, exported, null),
|
||||||
Symbol.Struct => ParseStruct(startIndex, exported),
|
Symbol.Struct => ParseStruct(startIndex, exported),
|
||||||
|
Symbol.Enum => ParseEnum(startIndex, exported),
|
||||||
_ => throw new ParseException(Diagnostic
|
_ => throw new ParseException(Diagnostic
|
||||||
.Error($"Expected 'func', 'struct', 'import' or 'module' but found '{keyword.Symbol}'")
|
.Error($"Expected 'func', 'struct', 'enum', 'import' or 'module' but found '{keyword.Symbol}'")
|
||||||
.WithHelp("Valid top level statements are 'func', 'struct', 'import' and 'module'")
|
.WithHelp("Valid top level statements are 'func', 'struct', 'enum', 'import' and 'module'")
|
||||||
.At(keyword)
|
.At(keyword)
|
||||||
.Build())
|
.Build())
|
||||||
};
|
};
|
||||||
@@ -176,6 +177,54 @@ public sealed class Parser
|
|||||||
return new StructSyntax(GetTokens(startIndex), name.Value, exported, fields);
|
return new StructSyntax(GetTokens(startIndex), name.Value, exported, fields);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private EnumSyntax ParseEnum(int startIndex, bool exported)
|
||||||
|
{
|
||||||
|
var name = ExpectIdentifier();
|
||||||
|
|
||||||
|
TypeSyntax? type = null;
|
||||||
|
|
||||||
|
if (TryExpectSymbol(Symbol.Colon))
|
||||||
|
{
|
||||||
|
type = ParseType();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<EnumFieldSyntax> fields = [];
|
||||||
|
|
||||||
|
ExpectSymbol(Symbol.OpenBrace);
|
||||||
|
|
||||||
|
long value = -1;
|
||||||
|
|
||||||
|
while (!TryExpectSymbol(Symbol.CloseBrace))
|
||||||
|
{
|
||||||
|
var memberStartIndex = _tokenIndex;
|
||||||
|
var fieldName = ExpectIdentifier().Value;
|
||||||
|
long fieldValue;
|
||||||
|
|
||||||
|
if (TryExpectSymbol(Symbol.Assign))
|
||||||
|
{
|
||||||
|
if (!TryExpectIntLiteral(out var intLiteralToken))
|
||||||
|
{
|
||||||
|
throw new ParseException(Diagnostic
|
||||||
|
.Error("Value of enum field must be an integer literal")
|
||||||
|
.At(CurrentToken)
|
||||||
|
.Build());
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldValue = Convert.ToInt64(intLiteralToken.Value, intLiteralToken.Base);
|
||||||
|
value = fieldValue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fieldValue = value + 1;
|
||||||
|
value = fieldValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
fields.Add(new EnumFieldSyntax(GetTokens(memberStartIndex), fieldName, fieldValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new EnumSyntax(GetTokens(startIndex), name.Value, exported, type, fields);
|
||||||
|
}
|
||||||
|
|
||||||
private StatementSyntax ParseStatement()
|
private StatementSyntax ParseStatement()
|
||||||
{
|
{
|
||||||
var startIndex = _tokenIndex;
|
var startIndex = _tokenIndex;
|
||||||
|
|||||||
@@ -16,6 +16,10 @@ public record StructFieldSyntax(List<Token> Tokens, string Name, TypeSyntax Type
|
|||||||
|
|
||||||
public record StructSyntax(List<Token> Tokens, string Name, bool Exported, List<StructFieldSyntax> Fields) : DefinitionSyntax(Tokens, Name, Exported);
|
public record StructSyntax(List<Token> Tokens, string Name, bool Exported, List<StructFieldSyntax> Fields) : DefinitionSyntax(Tokens, Name, Exported);
|
||||||
|
|
||||||
|
public record EnumFieldSyntax(List<Token> Tokens, string Name, long Value) : SyntaxNode(Tokens);
|
||||||
|
|
||||||
|
public record EnumSyntax(List<Token> Tokens, string Name, bool Exported, TypeSyntax? Type, List<EnumFieldSyntax> Fields) : DefinitionSyntax(Tokens, Name, Exported);
|
||||||
|
|
||||||
public enum UnaryOperatorSyntax
|
public enum UnaryOperatorSyntax
|
||||||
{
|
{
|
||||||
Negate,
|
Negate,
|
||||||
|
|||||||
@@ -17,11 +17,14 @@ public enum Symbol
|
|||||||
// Declaration
|
// Declaration
|
||||||
Func,
|
Func,
|
||||||
Struct,
|
Struct,
|
||||||
|
Enum,
|
||||||
|
Import,
|
||||||
|
Module,
|
||||||
|
|
||||||
// Modifier
|
// Modifier
|
||||||
Extern,
|
Extern,
|
||||||
Export,
|
Export,
|
||||||
|
|
||||||
Colon,
|
Colon,
|
||||||
DoubleColon,
|
DoubleColon,
|
||||||
OpenParen,
|
OpenParen,
|
||||||
@@ -53,10 +56,8 @@ public enum Symbol
|
|||||||
Pipe,
|
Pipe,
|
||||||
And,
|
And,
|
||||||
Or,
|
Or,
|
||||||
Module,
|
|
||||||
Import,
|
|
||||||
At,
|
At,
|
||||||
QuestionMark
|
QuestionMark,
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract record Token(SourceSpan Span);
|
public abstract record Token(SourceSpan Span);
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ public sealed class Tokenizer
|
|||||||
["export"] = Symbol.Export,
|
["export"] = Symbol.Export,
|
||||||
["import"] = Symbol.Import,
|
["import"] = Symbol.Import,
|
||||||
["defer"] = Symbol.Defer,
|
["defer"] = Symbol.Defer,
|
||||||
|
["enum"] = Symbol.Enum,
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly Dictionary<char[], Symbol> Symbols = new()
|
private static readonly Dictionary<char[], Symbol> Symbols = new()
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ module "main"
|
|||||||
|
|
||||||
extern "main" func main(argc: i64, argv: [?]cstring): i64
|
extern "main" func main(argc: i64, argv: [?]cstring): i64
|
||||||
{
|
{
|
||||||
raylib::SetConfigFlags(4 | 64)
|
raylib::SetConfigFlags(raylib::ConfigFlags.FLAG_VSYNC_HINT | raylib::ConfigFlags.FLAG_WINDOW_RESIZABLE)
|
||||||
|
|
||||||
raylib::InitWindow(1600, 900, "Hi from nub-lang")
|
raylib::InitWindow(1600, 900, "Hi from nub-lang")
|
||||||
defer raylib::CloseWindow()
|
defer raylib::CloseWindow()
|
||||||
|
|||||||
Reference in New Issue
Block a user