...
This commit is contained in:
@@ -249,13 +249,14 @@ public class Diagnostic
|
|||||||
{
|
{
|
||||||
return ConsoleColors.Colorize(tokenText, ConsoleColors.BrightWhite);
|
return ConsoleColors.Colorize(tokenText, ConsoleColors.BrightWhite);
|
||||||
}
|
}
|
||||||
case LiteralToken literal:
|
case StringLiteralToken:
|
||||||
|
{
|
||||||
|
return ConsoleColors.Colorize(tokenText, ConsoleColors.Green);
|
||||||
|
}
|
||||||
|
case IntLiteralToken:
|
||||||
|
case FloatLiteralToken:
|
||||||
|
case BoolLiteralToken:
|
||||||
{
|
{
|
||||||
if (literal.Kind == LiteralKind.String)
|
|
||||||
{
|
|
||||||
return ConsoleColors.Colorize(tokenText, ConsoleColors.Green);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ConsoleColors.Colorize(tokenText, ConsoleColors.Magenta);
|
return ConsoleColors.Colorize(tokenText, ConsoleColors.Magenta);
|
||||||
}
|
}
|
||||||
case SymbolToken symbolToken:
|
case SymbolToken symbolToken:
|
||||||
|
|||||||
@@ -39,11 +39,11 @@ public sealed class Parser
|
|||||||
{
|
{
|
||||||
while (TryExpectSymbol(Symbol.Import))
|
while (TryExpectSymbol(Symbol.Import))
|
||||||
{
|
{
|
||||||
imports.Add(ExpectLiteral(LiteralKind.String).Value);
|
imports.Add(ExpectStringLiteral().Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
ExpectSymbol(Symbol.Module);
|
ExpectSymbol(Symbol.Module);
|
||||||
_moduleName = ExpectLiteral(LiteralKind.String).Value;
|
_moduleName = ExpectStringLiteral().Value;
|
||||||
}
|
}
|
||||||
catch (ParseException e)
|
catch (ParseException e)
|
||||||
{
|
{
|
||||||
@@ -75,9 +75,9 @@ public sealed class Parser
|
|||||||
|
|
||||||
if (TryExpectSymbol(Symbol.Extern))
|
if (TryExpectSymbol(Symbol.Extern))
|
||||||
{
|
{
|
||||||
var externSymbol = ExpectLiteral(LiteralKind.String).Value;
|
var externSymbol = ExpectStringLiteral();
|
||||||
ExpectSymbol(Symbol.Func);
|
ExpectSymbol(Symbol.Func);
|
||||||
definitions.Add(ParseFunc(startIndex, exported, externSymbol));
|
definitions.Add(ParseFunc(startIndex, exported, externSymbol.Value));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -464,7 +464,10 @@ public sealed class Parser
|
|||||||
var token = ExpectToken();
|
var token = ExpectToken();
|
||||||
var expr = token switch
|
var expr = token switch
|
||||||
{
|
{
|
||||||
LiteralToken literal => new LiteralSyntax(GetTokens(startIndex), literal.Value, literal.Kind),
|
BoolLiteralToken boolLiteral => new BoolLiteralSyntax(GetTokens(startIndex), boolLiteral.Value),
|
||||||
|
StringLiteralToken stringLiteral => new StringLiteralSyntax(GetTokens(startIndex), stringLiteral.Value),
|
||||||
|
FloatLiteralToken floatLiteral => new FloatLiteralSyntax(GetTokens(startIndex), floatLiteral.Value),
|
||||||
|
IntLiteralToken intLiteral => new IntLiteralSyntax(GetTokens(startIndex), intLiteral.Value, intLiteral.Base),
|
||||||
IdentifierToken identifier => ParseIdentifier(startIndex, identifier),
|
IdentifierToken identifier => ParseIdentifier(startIndex, identifier),
|
||||||
SymbolToken symbolToken => symbolToken.Symbol switch
|
SymbolToken symbolToken => symbolToken.Symbol switch
|
||||||
{
|
{
|
||||||
@@ -920,14 +923,14 @@ public sealed class Parser
|
|||||||
return identifier;
|
return identifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
private LiteralToken ExpectLiteral()
|
private IntLiteralToken ExpectIntLiteral()
|
||||||
{
|
{
|
||||||
var token = ExpectToken();
|
var token = ExpectToken();
|
||||||
if (token is not LiteralToken identifier)
|
if (token is not IntLiteralToken identifier)
|
||||||
{
|
{
|
||||||
throw new ParseException(Diagnostic
|
throw new ParseException(Diagnostic
|
||||||
.Error($"Expected literal, but found {token.GetType().Name}")
|
.Error($"Expected int literal, but found {token.GetType().Name}")
|
||||||
.WithHelp("Provide a valid literal name here")
|
.WithHelp("Provide a valid int literal")
|
||||||
.At(token)
|
.At(token)
|
||||||
.Build());
|
.Build());
|
||||||
}
|
}
|
||||||
@@ -935,19 +938,49 @@ public sealed class Parser
|
|||||||
return identifier;
|
return identifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
private LiteralToken ExpectLiteral(LiteralKind kind)
|
private FloatLiteralToken ExpectFloatLiteral()
|
||||||
{
|
{
|
||||||
var literal = ExpectLiteral();
|
var token = ExpectToken();
|
||||||
if (literal.Kind != kind)
|
if (token is not FloatLiteralToken identifier)
|
||||||
{
|
{
|
||||||
throw new ParseException(Diagnostic
|
throw new ParseException(Diagnostic
|
||||||
.Error($"Expected {kind} literal, but found {literal.Kind}")
|
.Error($"Expected float literal, but found {token.GetType().Name}")
|
||||||
.WithHelp($"Provide a {kind} literal name here")
|
.WithHelp("Provide a valid float literal")
|
||||||
.At(literal)
|
.At(token)
|
||||||
.Build());
|
.Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
return literal;
|
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();
|
||||||
|
if (token is not StringLiteralToken identifier)
|
||||||
|
{
|
||||||
|
throw new ParseException(Diagnostic
|
||||||
|
.Error($"Expected string literal, but found {token.GetType().Name}")
|
||||||
|
.WithHelp("Provide a valid string literal")
|
||||||
|
.At(token)
|
||||||
|
.Build());
|
||||||
|
}
|
||||||
|
|
||||||
|
return identifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Next()
|
private void Next()
|
||||||
|
|||||||
@@ -50,7 +50,13 @@ public record ArrayIndexAccessSyntax(List<Token> Tokens, ExpressionSyntax Target
|
|||||||
|
|
||||||
public record AddressOfSyntax(List<Token> Tokens, ExpressionSyntax Target) : ExpressionSyntax(Tokens);
|
public record AddressOfSyntax(List<Token> Tokens, ExpressionSyntax Target) : ExpressionSyntax(Tokens);
|
||||||
|
|
||||||
public record LiteralSyntax(List<Token> Tokens, string Value, LiteralKind Kind) : ExpressionSyntax(Tokens);
|
public record IntLiteralSyntax(List<Token> Tokens, string Value, int Base) : ExpressionSyntax(Tokens);
|
||||||
|
|
||||||
|
public record StringLiteralSyntax(List<Token> Tokens, string Value) : ExpressionSyntax(Tokens);
|
||||||
|
|
||||||
|
public record BoolLiteralSyntax(List<Token> Tokens, bool Value) : ExpressionSyntax(Tokens);
|
||||||
|
|
||||||
|
public record FloatLiteralSyntax(List<Token> Tokens, string Value) : ExpressionSyntax(Tokens);
|
||||||
|
|
||||||
public record MemberAccessSyntax(List<Token> Tokens, ExpressionSyntax Target, string Member) : ExpressionSyntax(Tokens);
|
public record MemberAccessSyntax(List<Token> Tokens, ExpressionSyntax Target, string Member) : ExpressionSyntax(Tokens);
|
||||||
|
|
||||||
|
|||||||
@@ -2,16 +2,6 @@
|
|||||||
|
|
||||||
namespace NubLang.Tokenization;
|
namespace NubLang.Tokenization;
|
||||||
|
|
||||||
public enum LiteralKind
|
|
||||||
{
|
|
||||||
Integer,
|
|
||||||
Hex,
|
|
||||||
Binary,
|
|
||||||
Float,
|
|
||||||
String,
|
|
||||||
Bool
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum Symbol
|
public enum Symbol
|
||||||
{
|
{
|
||||||
Func,
|
Func,
|
||||||
@@ -69,6 +59,12 @@ public abstract record Token(string FileName, SourceSpan Span);
|
|||||||
|
|
||||||
public record IdentifierToken(string FileName, SourceSpan Span, string Value) : Token(FileName, Span);
|
public record IdentifierToken(string FileName, SourceSpan Span, string Value) : Token(FileName, Span);
|
||||||
|
|
||||||
public record LiteralToken(string FileName, SourceSpan Span, LiteralKind Kind, string Value) : Token(FileName, Span);
|
public record IntLiteralToken(string FileName, SourceSpan Span, string Value, int Base) : Token(FileName, Span);
|
||||||
|
|
||||||
|
public record StringLiteralToken(string FileName, SourceSpan Span, string Value) : Token(FileName, Span);
|
||||||
|
|
||||||
|
public record BoolLiteralToken(string FileName, SourceSpan Span, bool Value) : Token(FileName, Span);
|
||||||
|
|
||||||
|
public record FloatLiteralToken(string FileName, SourceSpan Span, string Value) : Token(FileName, Span);
|
||||||
|
|
||||||
public record SymbolToken(string FileName, SourceSpan Span, Symbol Symbol) : Token(FileName, Span);
|
public record SymbolToken(string FileName, SourceSpan Span, Symbol Symbol) : Token(FileName, Span);
|
||||||
@@ -148,7 +148,7 @@ public sealed class Tokenizer
|
|||||||
|
|
||||||
if (buffer is "true" or "false")
|
if (buffer is "true" or "false")
|
||||||
{
|
{
|
||||||
return new LiteralToken(_fileName, CreateSpan(lineStart, columnStart), LiteralKind.Bool, buffer);
|
return new BoolLiteralToken(_fileName, CreateSpan(lineStart, columnStart), Convert.ToBoolean(buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new IdentifierToken(_fileName, CreateSpan(lineStart, columnStart), buffer);
|
return new IdentifierToken(_fileName, CreateSpan(lineStart, columnStart), buffer);
|
||||||
@@ -156,7 +156,6 @@ public sealed class Tokenizer
|
|||||||
|
|
||||||
if (char.IsDigit(current))
|
if (char.IsDigit(current))
|
||||||
{
|
{
|
||||||
var isFloat = false;
|
|
||||||
var buffer = string.Empty;
|
var buffer = string.Empty;
|
||||||
|
|
||||||
if (current == '0' && Peek(1) is 'x')
|
if (current == '0' && Peek(1) is 'x')
|
||||||
@@ -178,7 +177,7 @@ public sealed class Tokenizer
|
|||||||
.Build());
|
.Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
return new LiteralToken(_fileName, CreateSpan(lineStart, columnStart), LiteralKind.Hex, buffer);
|
return new IntLiteralToken(_fileName, CreateSpan(lineStart, columnStart), buffer, 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current == '0' && Peek(1) is 'b')
|
if (current == '0' && Peek(1) is 'b')
|
||||||
@@ -200,10 +199,10 @@ public sealed class Tokenizer
|
|||||||
.Build());
|
.Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
return new LiteralToken(_fileName, CreateSpan(lineStart, columnStart), LiteralKind.Binary, buffer);
|
return new IntLiteralToken(_fileName, CreateSpan(lineStart, columnStart), buffer, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer += current;
|
var isFloat = false;
|
||||||
while (Peek() != null)
|
while (Peek() != null)
|
||||||
{
|
{
|
||||||
var next = Peek()!.Value;
|
var next = Peek()!.Value;
|
||||||
@@ -232,12 +231,14 @@ public sealed class Tokenizer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new LiteralToken(
|
if (isFloat)
|
||||||
_fileName,
|
{
|
||||||
CreateSpan(lineStart, columnStart),
|
return new FloatLiteralToken(_fileName, CreateSpan(lineStart, columnStart), buffer);
|
||||||
isFloat ? LiteralKind.Float : LiteralKind.Integer,
|
}
|
||||||
buffer
|
else
|
||||||
);
|
{
|
||||||
|
return new IntLiteralToken(_fileName, CreateSpan(lineStart, columnStart), buffer, 10);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current == '"')
|
if (current == '"')
|
||||||
@@ -272,7 +273,7 @@ public sealed class Tokenizer
|
|||||||
Next();
|
Next();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new LiteralToken(_fileName, CreateSpan(lineStart, columnStart), LiteralKind.String, buffer);
|
return new StringLiteralToken(_fileName, CreateSpan(lineStart, columnStart), buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var (pattern, symbol) in OrderedSymbols)
|
foreach (var (pattern, symbol) in OrderedSymbols)
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Globalization;
|
|
||||||
using NubLang.Diagnostics;
|
using NubLang.Diagnostics;
|
||||||
using NubLang.Modules;
|
using NubLang.Modules;
|
||||||
using NubLang.Parsing.Syntax;
|
using NubLang.Parsing.Syntax;
|
||||||
using NubLang.Tokenization;
|
|
||||||
using NubLang.TypeChecking.Node;
|
using NubLang.TypeChecking.Node;
|
||||||
|
|
||||||
namespace NubLang.TypeChecking;
|
namespace NubLang.TypeChecking;
|
||||||
@@ -339,7 +337,10 @@ public sealed class TypeChecker
|
|||||||
FuncCallSyntax expression => CheckFuncCall(expression),
|
FuncCallSyntax expression => CheckFuncCall(expression),
|
||||||
LocalIdentifierSyntax expression => CheckLocalIdentifier(expression),
|
LocalIdentifierSyntax expression => CheckLocalIdentifier(expression),
|
||||||
ModuleIdentifierSyntax expression => CheckModuleIdentifier(expression),
|
ModuleIdentifierSyntax expression => CheckModuleIdentifier(expression),
|
||||||
LiteralSyntax expression => CheckLiteral(expression, expectedType),
|
BoolLiteralSyntax expression => CheckBoolLiteral(expression),
|
||||||
|
StringLiteralSyntax expression => CheckStringLiteral(expression, expectedType),
|
||||||
|
IntLiteralSyntax expression => CheckIntLiteral(expression, expectedType),
|
||||||
|
FloatLiteralSyntax expression => CheckFloatLiteral(expression, expectedType),
|
||||||
MemberAccessSyntax expression => CheckMemberAccess(expression),
|
MemberAccessSyntax expression => CheckMemberAccess(expression),
|
||||||
StructInitializerSyntax expression => CheckStructInitializer(expression, expectedType),
|
StructInitializerSyntax expression => CheckStructInitializer(expression, expectedType),
|
||||||
InterpretBuiltinSyntax expression => CheckExpression(expression.Target) with { Type = ResolveType(expression.Type) },
|
InterpretBuiltinSyntax expression => CheckExpression(expression.Target) with { Type = ResolveType(expression.Type) },
|
||||||
@@ -766,81 +767,50 @@ public sealed class TypeChecker
|
|||||||
.Build());
|
.Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
private ExpressionNode CheckLiteral(LiteralSyntax expression, NubType? expectedType)
|
private ExpressionNode CheckStringLiteral(StringLiteralSyntax expression, NubType? expectedType)
|
||||||
{
|
{
|
||||||
switch (expression.Kind)
|
return expectedType switch
|
||||||
{
|
{
|
||||||
case LiteralKind.Integer:
|
NubCStringType => new CStringLiteralNode(expectedType, expression.Value),
|
||||||
{
|
NubStringType => new StringLiteralNode(expectedType, expression.Value),
|
||||||
if (expectedType is NubIntType intType)
|
_ => new CStringLiteralNode(new NubCStringType(), expression.Value)
|
||||||
{
|
};
|
||||||
return intType.Signed
|
}
|
||||||
? new IntLiteralNode(intType, long.Parse(expression.Value))
|
|
||||||
: new UIntLiteralNode(intType, ulong.Parse(expression.Value));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (expectedType is NubFloatType floatType)
|
private ExpressionNode CheckIntLiteral(IntLiteralSyntax expression, NubType? expectedType)
|
||||||
{
|
{
|
||||||
return floatType.Width switch
|
if (expectedType is NubIntType intType)
|
||||||
{
|
{
|
||||||
32 => new Float32LiteralNode(floatType, float.Parse(expression.Value, CultureInfo.InvariantCulture)),
|
return intType.Signed
|
||||||
64 => new Float64LiteralNode(floatType, double.Parse(expression.Value, CultureInfo.InvariantCulture)),
|
? new IntLiteralNode(intType, Convert.ToInt64(expression.Value, expression.Base))
|
||||||
_ => throw new ArgumentOutOfRangeException()
|
: new UIntLiteralNode(intType, Convert.ToUInt64(expression.Value, expression.Base));
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
var type = new NubIntType(true, 64);
|
|
||||||
return new IntLiteralNode(type, long.Parse(expression.Value));
|
|
||||||
}
|
|
||||||
case LiteralKind.Float:
|
|
||||||
{
|
|
||||||
var type = expectedType as NubFloatType ?? new NubFloatType(64);
|
|
||||||
return type.Width == 32
|
|
||||||
? new Float32LiteralNode(type, float.Parse(expression.Value, CultureInfo.InvariantCulture))
|
|
||||||
: new Float64LiteralNode(type, double.Parse(expression.Value, CultureInfo.InvariantCulture));
|
|
||||||
}
|
|
||||||
case LiteralKind.Hex:
|
|
||||||
{
|
|
||||||
if (expectedType is NubIntType intType)
|
|
||||||
{
|
|
||||||
return intType.Signed
|
|
||||||
? new IntLiteralNode(intType, Convert.ToInt64(expression.Value, 16))
|
|
||||||
: new UIntLiteralNode(intType, Convert.ToUInt64(expression.Value, 16));
|
|
||||||
}
|
|
||||||
|
|
||||||
var type = new NubIntType(true, 64);
|
|
||||||
return new IntLiteralNode(type, Convert.ToInt64(expression.Value, 16));
|
|
||||||
}
|
|
||||||
case LiteralKind.Binary:
|
|
||||||
{
|
|
||||||
if (expectedType is NubIntType intType)
|
|
||||||
{
|
|
||||||
return intType.Signed
|
|
||||||
? new IntLiteralNode(intType, Convert.ToInt64(expression.Value[2..], 2))
|
|
||||||
: new UIntLiteralNode(intType, Convert.ToUInt64(expression.Value[2..], 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
var type = new NubIntType(true, 64);
|
|
||||||
return new IntLiteralNode(type, Convert.ToInt64(expression.Value.Substring(2), 2));
|
|
||||||
}
|
|
||||||
case LiteralKind.String:
|
|
||||||
{
|
|
||||||
return expectedType switch
|
|
||||||
{
|
|
||||||
NubCStringType => new CStringLiteralNode(expectedType, expression.Value),
|
|
||||||
NubStringType => new StringLiteralNode(expectedType, expression.Value),
|
|
||||||
_ => new CStringLiteralNode(new NubCStringType(), expression.Value)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
case LiteralKind.Bool:
|
|
||||||
{
|
|
||||||
return new BoolLiteralNode(new NubBoolType(), bool.Parse(expression.Value));
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(expression.Kind), $"Unknown literal kind: {expression.Kind}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (expectedType is NubFloatType floatType)
|
||||||
|
{
|
||||||
|
return floatType.Width switch
|
||||||
|
{
|
||||||
|
32 => new Float32LiteralNode(floatType, Convert.ToSingle(Convert.ToInt64(expression.Value, expression.Base))),
|
||||||
|
64 => new Float64LiteralNode(floatType, Convert.ToDouble(Convert.ToInt64(expression.Value, expression.Base))),
|
||||||
|
_ => throw new ArgumentOutOfRangeException()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var type = new NubIntType(true, 64);
|
||||||
|
return new IntLiteralNode(type, Convert.ToInt64(expression.Value, expression.Base));
|
||||||
|
}
|
||||||
|
|
||||||
|
private ExpressionNode CheckFloatLiteral(FloatLiteralSyntax expression, NubType? expectedType)
|
||||||
|
{
|
||||||
|
var type = expectedType as NubFloatType ?? new NubFloatType(64);
|
||||||
|
return type.Width == 32
|
||||||
|
? new Float32LiteralNode(type, Convert.ToSingle(expression.Value))
|
||||||
|
: new Float64LiteralNode(type, Convert.ToDouble(expression.Value));
|
||||||
|
}
|
||||||
|
|
||||||
|
private BoolLiteralNode CheckBoolLiteral(BoolLiteralSyntax expression)
|
||||||
|
{
|
||||||
|
return new BoolLiteralNode(new NubBoolType(), expression.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ExpressionNode CheckMemberAccess(MemberAccessSyntax expression)
|
private ExpressionNode CheckMemberAccess(MemberAccessSyntax expression)
|
||||||
|
|||||||
Reference in New Issue
Block a user