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
|
||||||
/// ## Documentation subtitle
|
/// ## Documentation subtitle
|
||||||
export func main(args: []string) {
|
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 {
|
// i = i + 1
|
||||||
c::printf("%s\n", args[i])
|
// }
|
||||||
|
|
||||||
i = i + 1
|
let arr = new [10]i64
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -558,6 +558,7 @@ public class Generator
|
|||||||
{
|
{
|
||||||
AddressOfNode addressOf => GenerateAddressOf(addressOf),
|
AddressOfNode addressOf => GenerateAddressOf(addressOf),
|
||||||
ArrayIndexNode arrayIndex => GenerateArrayIndex(arrayIndex),
|
ArrayIndexNode arrayIndex => GenerateArrayIndex(arrayIndex),
|
||||||
|
ArrayInitializerNode arrayInitializer => GenerateArrayInitializer(arrayInitializer),
|
||||||
BinaryExpressionNode binaryExpression => GenerateBinaryExpression(binaryExpression),
|
BinaryExpressionNode binaryExpression => GenerateBinaryExpression(binaryExpression),
|
||||||
CastNode cast => GenerateCast(cast),
|
CastNode cast => GenerateCast(cast),
|
||||||
DereferenceNode dereference => GenerateDereference(dereference),
|
DereferenceNode dereference => GenerateDereference(dereference),
|
||||||
@@ -589,6 +590,24 @@ public class Generator
|
|||||||
return $"%{outputName}";
|
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)
|
private string GenerateDereference(DereferenceNode dereference)
|
||||||
{
|
{
|
||||||
var result = GenerateExpression(dereference.Expression);
|
var result = GenerateExpression(dereference.Expression);
|
||||||
|
|||||||
@@ -89,52 +89,37 @@ public class Lexer
|
|||||||
ConsumeWhitespace();
|
ConsumeWhitespace();
|
||||||
var startIndex = _index;
|
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))
|
if (!Peek().TryGetValue(out var current))
|
||||||
{
|
{
|
||||||
return Optional<Token>.Empty();
|
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 == '_')
|
if (char.IsLetter(current) || current == '_')
|
||||||
{
|
{
|
||||||
var buffer = string.Empty;
|
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,37 +498,39 @@ public class Parser
|
|||||||
}
|
}
|
||||||
case Symbol.New:
|
case Symbol.New:
|
||||||
{
|
{
|
||||||
var type = ParseType();
|
var next = Peek();
|
||||||
switch (type)
|
if (next.Value is SymbolToken { Symbol: Symbol.OpenBracket })
|
||||||
{
|
{
|
||||||
case NubStructType structType:
|
Next();
|
||||||
|
var size = ParseExpression();
|
||||||
|
ExpectSymbol(Symbol.CloseBracket);
|
||||||
|
var type = ParseType();
|
||||||
|
expr = new ArrayInitializerNode(GetTokensForNode(startIndex), size, type);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var type = ParseType();
|
||||||
|
Dictionary<string, ExpressionNode> initializers = [];
|
||||||
|
ExpectSymbol(Symbol.OpenBrace);
|
||||||
|
while (!TryExpectSymbol(Symbol.CloseBrace))
|
||||||
{
|
{
|
||||||
Dictionary<string, ExpressionNode> initializers = [];
|
var name = ExpectIdentifier().Value;
|
||||||
ExpectSymbol(Symbol.OpenBrace);
|
ExpectSymbol(Symbol.Assign);
|
||||||
while (!TryExpectSymbol(Symbol.CloseBrace))
|
var value = ParseExpression();
|
||||||
{
|
initializers.Add(name, value);
|
||||||
var name = ExpectIdentifier().Value;
|
}
|
||||||
ExpectSymbol(Symbol.Assign);
|
|
||||||
var value = ParseExpression();
|
|
||||||
initializers.Add(name, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
expr = new StructInitializerNode(GetTokensForNode(startIndex), structType, initializers);
|
if (type is not NubStructType structType)
|
||||||
break;
|
|
||||||
}
|
|
||||||
case NubArrayType arrayType:
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
{
|
||||||
throw new ParseException(Diagnostic
|
throw new ParseException(Diagnostic
|
||||||
.Error($"Cannot use new keyword on type {type}")
|
.Error($"Cannot use new keyword on type {type}")
|
||||||
.At(symbolToken)
|
.At(symbolToken)
|
||||||
.Build());
|
.Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expr = new StructInitializerNode(GetTokensForNode(startIndex), structType, initializers);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Symbol.Ampersand:
|
case Symbol.Ampersand:
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ public abstract class NubType
|
|||||||
public override string ToString() => Name;
|
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;
|
public string Namespace { get; } = @namespace;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -315,6 +315,7 @@ public class TypeChecker
|
|||||||
{
|
{
|
||||||
AddressOfNode addressOf => TypeCheckAddressOf(addressOf),
|
AddressOfNode addressOf => TypeCheckAddressOf(addressOf),
|
||||||
ArrayIndexNode arrayIndex => TypeCheckArrayIndex(arrayIndex),
|
ArrayIndexNode arrayIndex => TypeCheckArrayIndex(arrayIndex),
|
||||||
|
ArrayInitializerNode arrayInitializer => TypeCheckArrayInitializer(arrayInitializer),
|
||||||
LiteralNode literal => literal.LiteralType,
|
LiteralNode literal => literal.LiteralType,
|
||||||
IdentifierNode identifier => TypeCheckIdentifier(identifier),
|
IdentifierNode identifier => TypeCheckIdentifier(identifier),
|
||||||
BinaryExpressionNode binaryExpr => TypeCheckBinaryExpression(binaryExpr),
|
BinaryExpressionNode binaryExpr => TypeCheckBinaryExpression(binaryExpr),
|
||||||
@@ -361,6 +362,17 @@ public class TypeChecker
|
|||||||
return arrayType.BaseType;
|
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)
|
private NubType? TypeCheckIdentifier(IdentifierNode identifier)
|
||||||
{
|
{
|
||||||
if (!_variables.TryGetValue(identifier.Identifier, out var varType))
|
if (!_variables.TryGetValue(identifier.Identifier, out var varType))
|
||||||
|
|||||||
Reference in New Issue
Block a user