Array init support
This commit is contained in:
@@ -1,5 +0,0 @@
|
||||
namespace math
|
||||
|
||||
func add(a: i64, b: i64): i64 {
|
||||
return a + b
|
||||
}
|
||||
@@ -3,15 +3,15 @@ namespace main
|
||||
/// # Documentation
|
||||
/// ## Documentation subtitle
|
||||
export func main(args: []string) {
|
||||
let i: i64
|
||||
// let i: i64
|
||||
|
||||
let x = math::add(1, 1)
|
||||
// c::printf("%d\n", args.count)
|
||||
|
||||
c::printf("%d\n", args.count)
|
||||
// while i < args.count {
|
||||
// c::printf("%s\n", args[i])
|
||||
|
||||
while i < args.count {
|
||||
c::printf("%s\n", args[i])
|
||||
// i = i + 1
|
||||
// }
|
||||
|
||||
i = i + 1
|
||||
}
|
||||
let arr = new [10]i64
|
||||
}
|
||||
@@ -558,6 +558,7 @@ public class Generator
|
||||
{
|
||||
AddressOfNode addressOf => GenerateAddressOf(addressOf),
|
||||
ArrayIndexNode arrayIndex => GenerateArrayIndex(arrayIndex),
|
||||
ArrayInitializerNode arrayInitializer => GenerateArrayInitializer(arrayInitializer),
|
||||
BinaryExpressionNode binaryExpression => GenerateBinaryExpression(binaryExpression),
|
||||
CastNode cast => GenerateCast(cast),
|
||||
DereferenceNode dereference => GenerateDereference(dereference),
|
||||
@@ -589,6 +590,24 @@ public class Generator
|
||||
return $"%{outputName}";
|
||||
}
|
||||
|
||||
private string GenerateArrayInitializer(ArrayInitializerNode arrayInitializer)
|
||||
{
|
||||
var capacity = GenerateExpression(arrayInitializer.Capacity);
|
||||
var capacityInBytes = GenVarName();
|
||||
_builder.AppendLine($" %{capacityInBytes} =l mul {capacity}, {QbeTypeSize(arrayInitializer.ItemType)}");
|
||||
var totalArraySize = GenVarName();
|
||||
_builder.AppendLine($" %{totalArraySize} =l add %{capacityInBytes}, 8");
|
||||
var outputName = GenVarName();
|
||||
_builder.AppendLine($" %{outputName} =l alloc8 %{totalArraySize}");
|
||||
_builder.AppendLine($" storel {capacity}, %{outputName}");
|
||||
|
||||
var dataPtr = GenVarName();
|
||||
_builder.AppendLine($" %{dataPtr} =l add %{outputName}, 8");
|
||||
_builder.AppendLine($" call $nub_memset(l %{dataPtr}, w 0, l %{capacityInBytes})");
|
||||
|
||||
return $"%{outputName}";
|
||||
}
|
||||
|
||||
private string GenerateDereference(DereferenceNode dereference)
|
||||
{
|
||||
var result = GenerateExpression(dereference.Expression);
|
||||
|
||||
@@ -89,52 +89,37 @@ public class Lexer
|
||||
ConsumeWhitespace();
|
||||
var startIndex = _index;
|
||||
|
||||
string? documentation = null;
|
||||
while (Peek() is { Value: '/' } && Peek(1) is { Value: '/' })
|
||||
{
|
||||
Next();
|
||||
Next();
|
||||
|
||||
if (Peek() is { Value: '/' })
|
||||
{
|
||||
Next();
|
||||
|
||||
while (Peek().TryGetValue(out var character))
|
||||
{
|
||||
Next();
|
||||
documentation += character;
|
||||
if (character == '\n')
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (Peek().TryGetValue(out var character))
|
||||
{
|
||||
Next();
|
||||
if (character == '\n')
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (documentation != null)
|
||||
{
|
||||
return new DocumentationToken(_sourceText, startIndex, _index, documentation);
|
||||
}
|
||||
|
||||
ConsumeWhitespace();
|
||||
startIndex = _index;
|
||||
|
||||
if (!Peek().TryGetValue(out var current))
|
||||
{
|
||||
return Optional<Token>.Empty();
|
||||
}
|
||||
|
||||
if (current == '/' && Peek(1).TryGetValue(out var nextChar) && nextChar == '/')
|
||||
{
|
||||
Next();
|
||||
Next();
|
||||
|
||||
if (Peek().TryGetValue(out var thirdChar) && thirdChar == '/')
|
||||
{
|
||||
Next();
|
||||
var buffer = string.Empty;
|
||||
while (Peek().TryGetValue(out var character) && character != '\n')
|
||||
{
|
||||
buffer += character;
|
||||
Next();
|
||||
}
|
||||
Next();
|
||||
return new DocumentationToken(_sourceText, startIndex, _index, buffer);
|
||||
}
|
||||
|
||||
while (Peek().TryGetValue(out var character) && character != '\n')
|
||||
{
|
||||
Next();
|
||||
}
|
||||
Next();
|
||||
return ParseToken();
|
||||
}
|
||||
|
||||
if (char.IsLetter(current) || current == '_')
|
||||
{
|
||||
var buffer = string.Empty;
|
||||
|
||||
10
src/lang/Nub.Lang/Frontend/Parsing/ArrayInitializerNode.cs
Normal file
10
src/lang/Nub.Lang/Frontend/Parsing/ArrayInitializerNode.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
using Nub.Lang.Frontend.Lexing;
|
||||
using Nub.Lang.Frontend.Typing;
|
||||
|
||||
namespace Nub.Lang.Frontend.Parsing;
|
||||
|
||||
public class ArrayInitializerNode(IReadOnlyList<Token> tokens, ExpressionNode capacity, NubType itemType) : ExpressionNode(tokens)
|
||||
{
|
||||
public ExpressionNode Capacity { get; } = capacity;
|
||||
public NubType ItemType { get; } = itemType;
|
||||
}
|
||||
@@ -498,11 +498,18 @@ public class Parser
|
||||
}
|
||||
case Symbol.New:
|
||||
{
|
||||
var next = Peek();
|
||||
if (next.Value is SymbolToken { Symbol: Symbol.OpenBracket })
|
||||
{
|
||||
Next();
|
||||
var size = ParseExpression();
|
||||
ExpectSymbol(Symbol.CloseBracket);
|
||||
var type = ParseType();
|
||||
switch (type)
|
||||
{
|
||||
case NubStructType structType:
|
||||
expr = new ArrayInitializerNode(GetTokensForNode(startIndex), size, type);
|
||||
}
|
||||
else
|
||||
{
|
||||
var type = ParseType();
|
||||
Dictionary<string, ExpressionNode> initializers = [];
|
||||
ExpectSymbol(Symbol.OpenBrace);
|
||||
while (!TryExpectSymbol(Symbol.CloseBrace))
|
||||
@@ -513,20 +520,15 @@ public class Parser
|
||||
initializers.Add(name, value);
|
||||
}
|
||||
|
||||
expr = new StructInitializerNode(GetTokensForNode(startIndex), structType, initializers);
|
||||
break;
|
||||
}
|
||||
case NubArrayType arrayType:
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
default:
|
||||
if (type is not NubStructType structType)
|
||||
{
|
||||
throw new ParseException(Diagnostic
|
||||
.Error($"Cannot use new keyword on type {type}")
|
||||
.At(symbolToken)
|
||||
.Build());
|
||||
}
|
||||
|
||||
expr = new StructInitializerNode(GetTokensForNode(startIndex), structType, initializers);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
@@ -21,7 +21,7 @@ public abstract class NubType
|
||||
public override string ToString() => Name;
|
||||
}
|
||||
|
||||
public class NubStructType(string name, string @namespace) : NubType(name)
|
||||
public class NubStructType(string @namespace, string name) : NubType(name)
|
||||
{
|
||||
public string Namespace { get; } = @namespace;
|
||||
}
|
||||
|
||||
@@ -315,6 +315,7 @@ public class TypeChecker
|
||||
{
|
||||
AddressOfNode addressOf => TypeCheckAddressOf(addressOf),
|
||||
ArrayIndexNode arrayIndex => TypeCheckArrayIndex(arrayIndex),
|
||||
ArrayInitializerNode arrayInitializer => TypeCheckArrayInitializer(arrayInitializer),
|
||||
LiteralNode literal => literal.LiteralType,
|
||||
IdentifierNode identifier => TypeCheckIdentifier(identifier),
|
||||
BinaryExpressionNode binaryExpr => TypeCheckBinaryExpression(binaryExpr),
|
||||
@@ -361,6 +362,17 @@ public class TypeChecker
|
||||
return arrayType.BaseType;
|
||||
}
|
||||
|
||||
private NubType TypeCheckArrayInitializer(ArrayInitializerNode arrayInitializer)
|
||||
{
|
||||
var capacityType = TypeCheckExpression(arrayInitializer.Capacity);
|
||||
if (capacityType != null && !IsInteger(capacityType))
|
||||
{
|
||||
ReportError("Array capacity type must be an integer", arrayInitializer.Capacity);
|
||||
}
|
||||
|
||||
return new NubArrayType(arrayInitializer.ItemType);
|
||||
}
|
||||
|
||||
private NubType? TypeCheckIdentifier(IdentifierNode identifier)
|
||||
{
|
||||
if (!_variables.TryGetValue(identifier.Identifier, out var varType))
|
||||
|
||||
Reference in New Issue
Block a user