...
This commit is contained in:
@@ -122,10 +122,14 @@ public record VariableIdentifierNode(List<Token> Tokens, NubType Type, string Na
|
|||||||
|
|
||||||
public record FuncIdentifierNode(List<Token> Tokens, NubType Type, string Module, string Name, string? ExternSymbol) : RValueExpressionNode(Tokens, Type);
|
public record FuncIdentifierNode(List<Token> Tokens, NubType Type, string Module, string Name, string? ExternSymbol) : RValueExpressionNode(Tokens, Type);
|
||||||
|
|
||||||
public record ArrayInitializerNode(List<Token> Tokens, NubType Type, ExpressionNode Capacity, NubType ElementType) : RValueExpressionNode(Tokens, Type);
|
public record ArrayInitializerNode(List<Token> Tokens, NubType Type, List<ExpressionNode> Values) : RValueExpressionNode(Tokens, Type);
|
||||||
|
|
||||||
|
public record ConstArrayInitializerNode(List<Token> Tokens, NubType Type, List<ExpressionNode> Values) : RValueExpressionNode(Tokens, Type);
|
||||||
|
|
||||||
public record ArrayIndexAccessNode(List<Token> Tokens, NubType Type, ExpressionNode Target, ExpressionNode Index) : LValueExpressionNode(Tokens, Type);
|
public record ArrayIndexAccessNode(List<Token> Tokens, NubType Type, ExpressionNode Target, ExpressionNode Index) : LValueExpressionNode(Tokens, Type);
|
||||||
|
|
||||||
|
public record ConstArrayIndexAccessNode(List<Token> Tokens, NubType Type, ExpressionNode Target, ExpressionNode Index) : LValueExpressionNode(Tokens, Type);
|
||||||
|
|
||||||
public record SliceIndexAccessNode(List<Token> Tokens, NubType Type, ExpressionNode Target, ExpressionNode Index) : LValueExpressionNode(Tokens, Type);
|
public record SliceIndexAccessNode(List<Token> Tokens, NubType Type, ExpressionNode Target, ExpressionNode Index) : LValueExpressionNode(Tokens, Type);
|
||||||
|
|
||||||
public record AddressOfNode(List<Token> Tokens, NubType Type, LValueExpressionNode LValue) : RValueExpressionNode(Tokens, Type);
|
public record AddressOfNode(List<Token> Tokens, NubType Type, LValueExpressionNode LValue) : RValueExpressionNode(Tokens, Type);
|
||||||
@@ -140,14 +144,14 @@ public record ConvertIntNode(List<Token> Tokens, ExpressionNode Value, int Start
|
|||||||
|
|
||||||
public record ConvertFloatNode(List<Token> Tokens, ExpressionNode Value, int StartWidth, int TargetWidth) : RValueExpressionNode(Tokens, new NubFloatType(TargetWidth));
|
public record ConvertFloatNode(List<Token> Tokens, ExpressionNode Value, int StartWidth, int TargetWidth) : RValueExpressionNode(Tokens, new NubFloatType(TargetWidth));
|
||||||
|
|
||||||
public record ConvertStringToCStringNode(List<Token> Tokens, ExpressionNode Value) : RValueExpressionNode(Tokens, new NubCStringType());
|
|
||||||
|
|
||||||
public record ConvertCStringToStringNode(List<Token> Tokens, ExpressionNode Value) : RValueExpressionNode(Tokens, new NubStringType());
|
public record ConvertCStringToStringNode(List<Token> Tokens, ExpressionNode Value) : RValueExpressionNode(Tokens, new NubStringType());
|
||||||
|
|
||||||
public record SizeBuiltinNode(List<Token> Tokens, NubType Type, NubType TargetType) : RValueExpressionNode(Tokens, Type);
|
public record SizeBuiltinNode(List<Token> Tokens, NubType Type, NubType TargetType) : RValueExpressionNode(Tokens, Type);
|
||||||
|
|
||||||
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 ConstArrayToSliceNode(List<Token> Tokens, NubType Type, ExpressionNode Array) : RValueExpressionNode(Tokens, Type);
|
||||||
|
|
||||||
public record EnumReferenceIntermediateNode(List<Token> Tokens, string Module, string Name) : IntermediateExpression(Tokens);
|
public record EnumReferenceIntermediateNode(List<Token> Tokens, string Module, string Name) : IntermediateExpression(Tokens);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -272,8 +272,8 @@ public sealed class TypeChecker
|
|||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
throw new TypeCheckerException(Diagnostic
|
throw new TypeCheckerException(Diagnostic
|
||||||
.Error($"For statement not supported for type {target.Type}")
|
.Error($"Cannot iterate over type {target.Type} which does not have size information")
|
||||||
.At(forSyntax)
|
.At(forSyntax.Target)
|
||||||
.Build());
|
.Build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -292,7 +292,7 @@ public sealed class TypeChecker
|
|||||||
|
|
||||||
private ExpressionNode CheckExpression(ExpressionSyntax node, NubType? expectedType = null)
|
private ExpressionNode CheckExpression(ExpressionSyntax node, NubType? expectedType = null)
|
||||||
{
|
{
|
||||||
return node switch
|
var result = node switch
|
||||||
{
|
{
|
||||||
AddressOfSyntax expression => CheckAddressOf(expression, expectedType),
|
AddressOfSyntax expression => CheckAddressOf(expression, expectedType),
|
||||||
ArrayIndexAccessSyntax expression => CheckArrayIndexAccess(expression, expectedType),
|
ArrayIndexAccessSyntax expression => CheckArrayIndexAccess(expression, expectedType),
|
||||||
@@ -314,6 +314,40 @@ public sealed class TypeChecker
|
|||||||
FloatToIntBuiltinSyntax expression => CheckFloatToInt(expression, expectedType),
|
FloatToIntBuiltinSyntax expression => CheckFloatToInt(expression, expectedType),
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(node))
|
_ => throw new ArgumentOutOfRangeException(nameof(node))
|
||||||
};
|
};
|
||||||
|
|
||||||
|
switch (expectedType)
|
||||||
|
{
|
||||||
|
// note(nub31): Implicit conversion of const array to unsized array
|
||||||
|
case NubArrayType when result.Type is NubConstArrayType constArrayType:
|
||||||
|
{
|
||||||
|
return result with { Type = new NubArrayType(constArrayType.ElementType) };
|
||||||
|
}
|
||||||
|
// note(nub31): Implicit conversion of const array to slice
|
||||||
|
case NubSliceType when result.Type is NubConstArrayType constArrayType:
|
||||||
|
{
|
||||||
|
return new ConstArrayToSliceNode(result.Tokens, new NubSliceType(constArrayType.ElementType), result);
|
||||||
|
}
|
||||||
|
// note(nub31): Implicit conversion of int to larger int
|
||||||
|
case NubIntType expectedIntType when result.Type is NubIntType intType && expectedIntType.Width > intType.Width:
|
||||||
|
{
|
||||||
|
return new ConvertIntNode(result.Tokens, result, intType.Width, expectedIntType.Width, intType.Signed, expectedIntType.Signed);
|
||||||
|
}
|
||||||
|
// note(nub31): Implicit conversion of f32 to f64
|
||||||
|
case NubFloatType expectedFloatType when result.Type is NubFloatType floatType && expectedFloatType.Width > floatType.Width:
|
||||||
|
{
|
||||||
|
return new ConvertFloatNode(result.Tokens, result, floatType.Width, expectedFloatType.Width);
|
||||||
|
}
|
||||||
|
// note(nub31): Implicit conversion of cstring to string
|
||||||
|
case NubStringType when result.Type is NubCStringType:
|
||||||
|
{
|
||||||
|
return new ConvertCStringToStringNode(result.Tokens, result);
|
||||||
|
}
|
||||||
|
// note(nub31): No implicit conversion was possible or the result value was already the correct type
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo(nub31): Infer int type instead of explicit type syntax
|
// todo(nub31): Infer int type instead of explicit type syntax
|
||||||
@@ -368,18 +402,61 @@ public sealed class TypeChecker
|
|||||||
return target.Type switch
|
return target.Type switch
|
||||||
{
|
{
|
||||||
NubArrayType arrayType => new ArrayIndexAccessNode(expression.Tokens, arrayType.ElementType, target, index),
|
NubArrayType arrayType => new ArrayIndexAccessNode(expression.Tokens, arrayType.ElementType, target, index),
|
||||||
|
NubConstArrayType constArrayType => new ConstArrayIndexAccessNode(expression.Tokens, constArrayType.ElementType, target, index),
|
||||||
NubSliceType sliceType => new SliceIndexAccessNode(expression.Tokens, sliceType.ElementType, target, index),
|
NubSliceType sliceType => new SliceIndexAccessNode(expression.Tokens, sliceType.ElementType, target, index),
|
||||||
_ => throw new TypeCheckerException(Diagnostic.Error($"Cannot use array indexer on type {target.Type}").At(expression).Build())
|
_ => throw new TypeCheckerException(Diagnostic.Error($"Cannot use array indexer on type {target.Type}").At(expression).Build())
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo(nub31): Allow type inference instead of specifying type in syntax. Something like just []
|
private ExpressionNode CheckArrayInitializer(ArrayInitializerSyntax expression, NubType? expectedType)
|
||||||
private ArrayInitializerNode CheckArrayInitializer(ArrayInitializerSyntax expression, NubType? _)
|
|
||||||
{
|
{
|
||||||
var elementType = ResolveType(expression.ElementType);
|
var elementType = expectedType switch
|
||||||
var capacity = CheckExpression(expression.Capacity);
|
{
|
||||||
var type = new NubArrayType(elementType);
|
NubArrayType arrayType => arrayType.ElementType,
|
||||||
return new ArrayInitializerNode(expression.Tokens, type, capacity, elementType);
|
NubConstArrayType constArrayType => constArrayType.ElementType,
|
||||||
|
NubSliceType sliceType => sliceType.ElementType,
|
||||||
|
_ => null
|
||||||
|
};
|
||||||
|
|
||||||
|
if (elementType == null)
|
||||||
|
{
|
||||||
|
var firstValue = expression.Values.FirstOrDefault();
|
||||||
|
if (firstValue != null)
|
||||||
|
{
|
||||||
|
elementType = CheckExpression(firstValue).Type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (elementType == null)
|
||||||
|
{
|
||||||
|
throw new TypeCheckerException(Diagnostic
|
||||||
|
.Error("Unable to infer type of array initializer")
|
||||||
|
.At(expression)
|
||||||
|
.WithHelp("Provide a type for a variable assignment")
|
||||||
|
.Build());
|
||||||
|
}
|
||||||
|
|
||||||
|
var values = new List<ExpressionNode>();
|
||||||
|
foreach (var valueExpression in expression.Values)
|
||||||
|
{
|
||||||
|
var value = CheckExpression(valueExpression, elementType);
|
||||||
|
if (value.Type != elementType)
|
||||||
|
{
|
||||||
|
throw new TypeCheckerException(Diagnostic
|
||||||
|
.Error("Value in array initializer is not the same as the array type")
|
||||||
|
.At(valueExpression)
|
||||||
|
.Build());
|
||||||
|
}
|
||||||
|
|
||||||
|
values.Add(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return expectedType switch
|
||||||
|
{
|
||||||
|
NubArrayType => new ArrayInitializerNode(expression.Tokens, new NubArrayType(elementType), values),
|
||||||
|
NubConstArrayType constArrayType => new ConstArrayInitializerNode(expression.Tokens, constArrayType, values),
|
||||||
|
_ => new ConstArrayInitializerNode(expression.Tokens, new NubConstArrayType(elementType, expression.Values.Count), values)
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private BinaryExpressionNode CheckBinaryExpression(BinaryExpressionSyntax expression, NubType? expectedType)
|
private BinaryExpressionNode CheckBinaryExpression(BinaryExpressionSyntax expression, NubType? expectedType)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ namespace NubLang.Generation;
|
|||||||
|
|
||||||
public static class CType
|
public static class CType
|
||||||
{
|
{
|
||||||
public static string Create(NubType type, string? variableName = null)
|
public static string Create(NubType type, string? variableName = null, bool constArraysAsPointers = true)
|
||||||
{
|
{
|
||||||
return type switch
|
return type switch
|
||||||
{
|
{
|
||||||
@@ -16,7 +16,7 @@ public static class CType
|
|||||||
NubPointerType ptr => CreatePointerType(ptr, variableName),
|
NubPointerType ptr => CreatePointerType(ptr, variableName),
|
||||||
NubSliceType => "slice" + (variableName != null ? $" {variableName}" : ""),
|
NubSliceType => "slice" + (variableName != null ? $" {variableName}" : ""),
|
||||||
NubStringType => "string" + (variableName != null ? $" {variableName}" : ""),
|
NubStringType => "string" + (variableName != null ? $" {variableName}" : ""),
|
||||||
NubConstArrayType arr => CreateConstArrayType(arr, variableName),
|
NubConstArrayType arr => CreateConstArrayType(arr, variableName, constArraysAsPointers),
|
||||||
NubArrayType arr => CreateArrayType(arr, variableName),
|
NubArrayType arr => CreateArrayType(arr, variableName),
|
||||||
NubFuncType fn => CreateFuncType(fn, variableName),
|
NubFuncType fn => CreateFuncType(fn, variableName),
|
||||||
NubStructType st => $"{st.Module}_{st.Name}" + (variableName != null ? $" {variableName}" : ""),
|
NubStructType st => $"{st.Module}_{st.Name}" + (variableName != null ? $" {variableName}" : ""),
|
||||||
@@ -54,9 +54,16 @@ public static class CType
|
|||||||
return baseType + "*" + (varName != null ? $" {varName}" : "");
|
return baseType + "*" + (varName != null ? $" {varName}" : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string CreateConstArrayType(NubConstArrayType arr, string? varName)
|
private static string CreateConstArrayType(NubConstArrayType arr, string? varName, bool inStructDef)
|
||||||
{
|
{
|
||||||
var elementType = Create(arr.ElementType);
|
var elementType = Create(arr.ElementType);
|
||||||
|
|
||||||
|
// Treat const arrays as pointers unless in a struct definition
|
||||||
|
if (!inStructDef)
|
||||||
|
{
|
||||||
|
return elementType + "*" + (varName != null ? $" {varName}" : "");
|
||||||
|
}
|
||||||
|
|
||||||
if (varName != null)
|
if (varName != null)
|
||||||
{
|
{
|
||||||
return $"{elementType} {varName}[{arr.Size}]";
|
return $"{elementType} {varName}[{arr.Size}]";
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ public class Generator
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
size_t length;
|
size_t length;
|
||||||
uint8_t *data;
|
char *data;
|
||||||
} string;
|
} string;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
@@ -62,7 +62,7 @@ public class Generator
|
|||||||
{
|
{
|
||||||
foreach (var field in structType.Fields)
|
foreach (var field in structType.Fields)
|
||||||
{
|
{
|
||||||
_writer.WriteLine($"{CType.Create(field.Type, field.Name)};");
|
_writer.WriteLine($"{CType.Create(field.Type, field.Name, constArraysAsPointers: false)};");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,7 +202,7 @@ public class Generator
|
|||||||
_writer.WriteLine("{");
|
_writer.WriteLine("{");
|
||||||
using (_writer.Indent())
|
using (_writer.Indent())
|
||||||
{
|
{
|
||||||
_writer.WriteLine($"{CType.Create(targetType.ElementType, forSliceNode.ElementName)} = {target}.data[{indexName}];");
|
_writer.WriteLine($"{CType.Create(targetType.ElementType, forSliceNode.ElementName)} = (({CType.Create(targetType.ElementType)}*){target}.data)[{indexName}];");
|
||||||
EmitBlock(forSliceNode.Body);
|
EmitBlock(forSliceNode.Body);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,10 +337,12 @@ public class Generator
|
|||||||
ArrayInitializerNode arrayInitializerNode => EmitArrayInitializer(arrayInitializerNode),
|
ArrayInitializerNode arrayInitializerNode => EmitArrayInitializer(arrayInitializerNode),
|
||||||
BinaryExpressionNode binaryExpressionNode => EmitBinaryExpression(binaryExpressionNode),
|
BinaryExpressionNode binaryExpressionNode => EmitBinaryExpression(binaryExpressionNode),
|
||||||
BoolLiteralNode boolLiteralNode => boolLiteralNode.Value ? "true" : "false",
|
BoolLiteralNode boolLiteralNode => boolLiteralNode.Value ? "true" : "false",
|
||||||
|
ConstArrayIndexAccessNode constArrayIndexAccessNode => EmitConstArrayIndexAccess(constArrayIndexAccessNode),
|
||||||
|
ConstArrayInitializerNode constArrayInitializerNode => EmitConstArrayInitializer(constArrayInitializerNode),
|
||||||
|
ConstArrayToSliceNode constArrayToSliceNode => EmitConstArrayToSlice(constArrayToSliceNode),
|
||||||
ConvertCStringToStringNode convertCStringToStringNode => EmitConvertCStringToString(convertCStringToStringNode),
|
ConvertCStringToStringNode convertCStringToStringNode => EmitConvertCStringToString(convertCStringToStringNode),
|
||||||
ConvertFloatNode convertFloatNode => EmitConvertFloat(convertFloatNode),
|
ConvertFloatNode convertFloatNode => EmitConvertFloat(convertFloatNode),
|
||||||
ConvertIntNode convertIntNode => EmitConvertInt(convertIntNode),
|
ConvertIntNode convertIntNode => EmitConvertInt(convertIntNode),
|
||||||
ConvertStringToCStringNode convertStringToCStringNode => EmitConvertStringToCString(convertStringToCStringNode),
|
|
||||||
CStringLiteralNode cStringLiteralNode => $"\"{cStringLiteralNode.Value}\"",
|
CStringLiteralNode cStringLiteralNode => $"\"{cStringLiteralNode.Value}\"",
|
||||||
DereferenceNode dereferenceNode => EmitDereference(dereferenceNode),
|
DereferenceNode dereferenceNode => EmitDereference(dereferenceNode),
|
||||||
Float32LiteralNode float32LiteralNode => EmitFloat32Literal(float32LiteralNode),
|
Float32LiteralNode float32LiteralNode => EmitFloat32Literal(float32LiteralNode),
|
||||||
@@ -372,16 +374,22 @@ public class Generator
|
|||||||
|
|
||||||
private string EmitArrayIndexAccess(ArrayIndexAccessNode arrayIndexAccessNode)
|
private string EmitArrayIndexAccess(ArrayIndexAccessNode arrayIndexAccessNode)
|
||||||
{
|
{
|
||||||
var array = EmitExpression(arrayIndexAccessNode.Target);
|
var target = EmitExpression(arrayIndexAccessNode.Target);
|
||||||
var index = EmitExpression(arrayIndexAccessNode.Index);
|
var index = EmitExpression(arrayIndexAccessNode.Index);
|
||||||
return $"{array}[{index}]";
|
return $"{target}[{index}]";
|
||||||
}
|
}
|
||||||
|
|
||||||
private string EmitArrayInitializer(ArrayInitializerNode arrayInitializerNode)
|
private string EmitArrayInitializer(ArrayInitializerNode arrayInitializerNode)
|
||||||
{
|
{
|
||||||
var capacity = EmitExpression(arrayInitializerNode.Capacity);
|
var values = new List<string>();
|
||||||
|
foreach (var value in arrayInitializerNode.Values)
|
||||||
|
{
|
||||||
|
values.Add(EmitExpression(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
var arrayType = (NubArrayType)arrayInitializerNode.Type;
|
||||||
var tmp = NewTmp();
|
var tmp = NewTmp();
|
||||||
_writer.WriteLine($"{CType.Create(arrayInitializerNode.ElementType)} {tmp}[{capacity}];");
|
_writer.WriteLine($"{CType.Create(arrayType.ElementType)} {tmp}[] = {{{string.Join(", ", values)}}};");
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -416,6 +424,35 @@ public class Generator
|
|||||||
return $"{left} {op} {right}";
|
return $"{left} {op} {right}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string EmitConstArrayIndexAccess(ConstArrayIndexAccessNode constArrayIndexAccessNode)
|
||||||
|
{
|
||||||
|
var target = EmitExpression(constArrayIndexAccessNode.Target);
|
||||||
|
var index = EmitExpression(constArrayIndexAccessNode.Index);
|
||||||
|
// todo(nub31): We can emit bounds checking here
|
||||||
|
return $"{target}[{index}]";
|
||||||
|
}
|
||||||
|
|
||||||
|
private string EmitConstArrayInitializer(ConstArrayInitializerNode arrayInitializerNode)
|
||||||
|
{
|
||||||
|
var values = new List<string>();
|
||||||
|
foreach (var value in arrayInitializerNode.Values)
|
||||||
|
{
|
||||||
|
values.Add(EmitExpression(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
var arrayType = (NubConstArrayType)arrayInitializerNode.Type;
|
||||||
|
var tmp = NewTmp();
|
||||||
|
_writer.WriteLine($"{CType.Create(arrayType.ElementType)} {tmp}[{arrayType.Size}] = {{{string.Join(", ", values)}}};");
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string EmitConstArrayToSlice(ConstArrayToSliceNode constArrayToSliceNode)
|
||||||
|
{
|
||||||
|
var arrayType = (NubConstArrayType)constArrayToSliceNode.Array.Type;
|
||||||
|
var array = EmitExpression(constArrayToSliceNode.Array);
|
||||||
|
return $"(slice){{.length = {arrayType.Size}, .data = (void*){array}}}";
|
||||||
|
}
|
||||||
|
|
||||||
private string EmitConvertCStringToString(ConvertCStringToStringNode convertCStringToStringNode)
|
private string EmitConvertCStringToString(ConvertCStringToStringNode convertCStringToStringNode)
|
||||||
{
|
{
|
||||||
var value = EmitExpression(convertCStringToStringNode.Value);
|
var value = EmitExpression(convertCStringToStringNode.Value);
|
||||||
@@ -449,12 +486,6 @@ public class Generator
|
|||||||
return $"({targetType}){value}";
|
return $"({targetType}){value}";
|
||||||
}
|
}
|
||||||
|
|
||||||
private string EmitConvertStringToCString(ConvertStringToCStringNode convertStringToCStringNode)
|
|
||||||
{
|
|
||||||
var value = EmitExpression(convertStringToCStringNode.Value);
|
|
||||||
return $"(char*){value}.data";
|
|
||||||
}
|
|
||||||
|
|
||||||
private string EmitDereference(DereferenceNode dereferenceNode)
|
private string EmitDereference(DereferenceNode dereferenceNode)
|
||||||
{
|
{
|
||||||
var pointer = EmitExpression(dereferenceNode.Target);
|
var pointer = EmitExpression(dereferenceNode.Target);
|
||||||
@@ -512,10 +543,11 @@ public class Generator
|
|||||||
|
|
||||||
private string EmitSliceArrayIndexAccess(SliceIndexAccessNode sliceIndexAccessNode)
|
private string EmitSliceArrayIndexAccess(SliceIndexAccessNode sliceIndexAccessNode)
|
||||||
{
|
{
|
||||||
var value = EmitExpression(sliceIndexAccessNode.Target);
|
var targetType = (NubSliceType)sliceIndexAccessNode.Target.Type;
|
||||||
|
var target = EmitExpression(sliceIndexAccessNode.Target);
|
||||||
var index = EmitExpression(sliceIndexAccessNode.Index);
|
var index = EmitExpression(sliceIndexAccessNode.Index);
|
||||||
// todo(nub31): We can emit bounds checking here
|
// todo(nub31): We can emit bounds checking here
|
||||||
return $"(({CType.Create(sliceIndexAccessNode.Target.Type)}){value}.data)[{index}]";
|
return $"(({CType.Create(targetType.ElementType)}*){target}.data)[{index}]";
|
||||||
}
|
}
|
||||||
|
|
||||||
private string EmitStringLiteral(StringLiteralNode stringLiteralNode)
|
private string EmitStringLiteral(StringLiteralNode stringLiteralNode)
|
||||||
|
|||||||
@@ -609,10 +609,18 @@ public sealed class Parser
|
|||||||
|
|
||||||
private ExpressionSyntax ParseArrayInitializer(int startIndex)
|
private ExpressionSyntax ParseArrayInitializer(int startIndex)
|
||||||
{
|
{
|
||||||
var capacity = ParseExpression();
|
var values = new List<ExpressionSyntax>();
|
||||||
ExpectSymbol(Symbol.CloseBracket);
|
while (!TryExpectSymbol(Symbol.CloseBracket))
|
||||||
var type = ParseType();
|
{
|
||||||
return new ArrayInitializerSyntax(GetTokens(startIndex), capacity, type);
|
values.Add(ParseExpression());
|
||||||
|
if (!TryExpectSymbol(Symbol.Comma))
|
||||||
|
{
|
||||||
|
ExpectSymbol(Symbol.CloseBracket);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ArrayInitializerSyntax(GetTokens(startIndex), values);
|
||||||
}
|
}
|
||||||
|
|
||||||
private StructInitializerSyntax ParseStructInitializer(int startIndex)
|
private StructInitializerSyntax ParseStructInitializer(int startIndex)
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ public record LocalIdentifierSyntax(List<Token> Tokens, string Name) : Expressio
|
|||||||
|
|
||||||
public record ModuleIdentifierSyntax(List<Token> Tokens, string Module, string Name) : ExpressionSyntax(Tokens);
|
public record ModuleIdentifierSyntax(List<Token> Tokens, string Module, string Name) : ExpressionSyntax(Tokens);
|
||||||
|
|
||||||
public record ArrayInitializerSyntax(List<Token> Tokens, ExpressionSyntax Capacity, TypeSyntax ElementType) : ExpressionSyntax(Tokens);
|
public record ArrayInitializerSyntax(List<Token> Tokens, List<ExpressionSyntax> Values) : ExpressionSyntax(Tokens);
|
||||||
|
|
||||||
public record ArrayIndexAccessSyntax(List<Token> Tokens, ExpressionSyntax Target, ExpressionSyntax Index) : ExpressionSyntax(Tokens);
|
public record ArrayIndexAccessSyntax(List<Token> Tokens, ExpressionSyntax Target, ExpressionSyntax Index) : ExpressionSyntax(Tokens);
|
||||||
|
|
||||||
|
|||||||
@@ -2,16 +2,14 @@ module "main"
|
|||||||
|
|
||||||
extern "puts" func puts(text: cstring)
|
extern "puts" func puts(text: cstring)
|
||||||
|
|
||||||
struct Test
|
|
||||||
{
|
|
||||||
data: [23]cstring
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "main" func main(argc: i64, argv: [?]cstring): i64
|
extern "main" func main(argc: i64, argv: [?]cstring): i64
|
||||||
{
|
{
|
||||||
let names = struct Test {}
|
let names: []cstring = ["test", "test2"]
|
||||||
|
|
||||||
for name, i in names.data
|
puts(names[0])
|
||||||
|
puts(names[1])
|
||||||
|
|
||||||
|
for name, i in names
|
||||||
{
|
{
|
||||||
puts(name)
|
puts(name)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user