This commit is contained in:
nub31
2025-10-22 11:22:06 +02:00
parent 8709eeb09d
commit e2da6cccff
9 changed files with 91 additions and 233 deletions

View File

@@ -71,10 +71,10 @@ var objectPaths = new List<string>();
foreach (var cPath in cPaths)
{
var objectPath = Path.ChangeExtension(cPath, "o");
using var compileProcess = Process.Start("gcc", [
"-ffreestanding", "-nostartfiles", "-std=c23",
"-g", "-lm",
"-c", "-o", objectPath,
using var compileProcess = Process.Start("clang", [
"-ffreestanding", "-std=c23",
"-g", "-c",
"-o", objectPath,
cPath,
]);
@@ -82,79 +82,13 @@ foreach (var cPath in cPaths)
if (compileProcess.ExitCode != 0)
{
Console.Error.WriteLine($"gcc failed with exit code {compileProcess.ExitCode}");
Console.Error.WriteLine($"clang failed with exit code {compileProcess.ExitCode}");
return 1;
}
objectPaths.Add(objectPath);
}
if (modules.TryGetValue("main", out var mainModule))
{
var mainFunction = mainModule
.Functions(true)
.FirstOrDefault(x => x.Prototype.ExternSymbol == "main");
if (mainFunction is { Prototype.ExternSymbol: not null })
{
var runtime = $"""
.intel_syntax noprefix
.text
.globl _start
_start:
mov rdi, [rsp] # argc
mov rsi, [rsp + 8] # argv
call {mainFunction.Prototype.ExternSymbol}
mov rdi, rax # Move return value into rdi
mov rax, 60 # syscall: exit
syscall
""";
var runtimePath = Path.Combine(".build", "runtime.s");
File.WriteAllText(runtimePath, runtime);
using var assembleProcess = Process.Start(new ProcessStartInfo("as", ["-g", "-c", runtimePath, "-o", Path.Combine(".build", "runtime.o")]));
if (assembleProcess == null) return 1;
assembleProcess.WaitForExit();
if (assembleProcess.ExitCode != 0)
{
Console.Error.WriteLine($"gcc failed with exit code {assembleProcess.ExitCode}");
return 1;
}
if (assembleProcess.ExitCode != 0) return 1;
using var linkProcess = Process.Start(new ProcessStartInfo("gcc", [
"-ffreestanding", "-nostartfiles", "-std=c23",
"-g", "-lm",
"-o", Path.Combine(".build", "out"),
..objectPaths,
Path.Combine(".build", "runtime.o"),
..objectFileArgs
]));
if (linkProcess == null) return 1;
linkProcess.WaitForExit();
if (linkProcess.ExitCode != 0)
{
Console.Error.WriteLine($"gcc failed with exit code {linkProcess.ExitCode}");
return 1;
}
Console.WriteLine("Build successful: .build/out");
}
else
{
Console.WriteLine("No main function found in module main, skipping link step");
}
}
else
{
Console.WriteLine("No main function found in module main, skipping link step");
}
Console.Out.WriteLine(string.Join(' ', objectPaths));
return 0;

View File

@@ -100,20 +100,14 @@ public record UnaryExpressionNode(List<Token> Tokens, NubType Type, UnaryOperato
public record FuncCallNode(List<Token> Tokens, NubType Type, ExpressionNode Expression, List<ExpressionNode> Parameters) : RValueExpressionNode(Tokens, Type);
public record LValueIdentifierNode(List<Token> Tokens, NubType Type, string Name) : LValueExpressionNode(Tokens, Type);
public record RValueIdentifierNode(List<Token> Tokens, NubType Type, string Name) : RValueExpressionNode(Tokens, Type);
public record VariableIdentifierNode(List<Token> Tokens, NubType Type, string Name) : LValueExpressionNode(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 ConstArrayInitializerNode(List<Token> Tokens, NubType Type, long Capacity, NubType ElementType) : RValueExpressionNode(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 AddressOfNode(List<Token> Tokens, NubType Type, LValueExpressionNode LValue) : RValueExpressionNode(Tokens, Type);
@@ -128,7 +122,9 @@ public record ConvertIntNode(List<Token> Tokens, NubType Type, ExpressionNode Va
public record ConvertFloatNode(List<Token> Tokens, NubType Type, ExpressionNode Value, NubFloatType ValueType, NubFloatType TargetType) : RValueExpressionNode(Tokens, Type);
// public record ConvertConstArrayToArrayNode(List<Token> Tokens, NubType Type, ExpressionNode Value) : RValueExpressionNode(Tokens, Type);
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 SizeBuiltinNode(List<Token> Tokens, NubType Type, NubType TargetType) : RValueExpressionNode(Tokens, Type);

View File

@@ -54,7 +54,7 @@ public sealed class TypeChecker
foreach (var (name, module) in _importedModules)
{
foreach (var structSyntax in module.Structs(false))
foreach (var structSyntax in module.Structs(true))
{
var fields = structSyntax.Fields
.Select(f => new NubStructFieldType(f.Name, ResolveType(f.Type), f.Value != null))
@@ -63,7 +63,7 @@ public sealed class TypeChecker
importedStructTypes.Add(new NubStructType(name, structSyntax.Name, fields));
}
foreach (var funcSyntax in module.Functions(false))
foreach (var funcSyntax in module.Functions(true))
{
importedFunctions.Add(CheckFuncPrototype(funcSyntax.Prototype));
}
@@ -109,7 +109,7 @@ public sealed class TypeChecker
{
foreach (var parameter in node.Prototype.Parameters)
{
CurrentScope.DeclareVariable(new Variable(parameter.Name, ResolveType(parameter.Type), VariableKind.RValue));
CurrentScope.DeclareVariable(new Variable(parameter.Name, ResolveType(parameter.Type)));
}
var prototype = CheckFuncPrototype(node.Prototype);
@@ -211,7 +211,7 @@ public sealed class TypeChecker
throw new TypeCheckerException(Diagnostic.Error($"Cannot infer type of variable {statement.Name}").At(statement).Build());
}
CurrentScope.DeclareVariable(new Variable(statement.Name, type, VariableKind.LValue));
CurrentScope.DeclareVariable(new Variable(statement.Name, type));
return new VariableDeclarationNode(statement.Tokens, statement.Name, assignmentNode, type);
}
@@ -248,7 +248,6 @@ public sealed class TypeChecker
LocalIdentifierSyntax expression => CheckLocalIdentifier(expression),
ModuleIdentifierSyntax expression => CheckModuleIdentifier(expression),
BoolLiteralSyntax expression => CheckBoolLiteral(expression),
ConstArrayInitializerSyntax expression => CheckConstArrayInitializer(expression),
StringLiteralSyntax expression => CheckStringLiteral(expression, expectedType),
IntLiteralSyntax expression => CheckIntLiteral(expression, expectedType),
FloatLiteralSyntax expression => CheckFloatLiteral(expression, expectedType),
@@ -265,10 +264,15 @@ public sealed class TypeChecker
return result;
}
// if (result.Type is NubConstArrayType && expectedType is NubArrayType)
// {
// return new ConvertConstArrayToArrayNode(node.Tokens, expectedType, result);
// }
if (result.Type is NubStringType && expectedType is NubCStringType)
{
return new ConvertStringToCStringNode(node.Tokens, result);
}
if (result.Type is NubCStringType && expectedType is NubStringType)
{
return new ConvertCStringToStringNode(node.Tokens, result);
}
if (result.Type is NubIntType sourceIntType && expectedType is NubIntType targetIntType)
{
@@ -289,13 +293,6 @@ public sealed class TypeChecker
throw new TypeCheckerException(Diagnostic.Error($"Cannot convert {result.Type} to {expectedType}").At(node).Build());
}
private ConstArrayInitializerNode CheckConstArrayInitializer(ConstArrayInitializerSyntax expression)
{
var elementType = ResolveType(expression.ElementType);
var type = new NubConstArrayType(elementType, expression.Capacity);
return new ConstArrayInitializerNode(expression.Tokens, type, expression.Capacity, elementType);
}
private FloatToIntBuiltinNode CheckFloatToInt(FloatToIntBuiltinSyntax expression)
{
var value = CheckExpression(expression.Value);
@@ -333,13 +330,20 @@ public sealed class TypeChecker
private ExpressionNode CheckArrayIndexAccess(ArrayIndexAccessSyntax expression)
{
var index = CheckExpression(expression.Index, new NubIntType(false, 64));
var index = CheckExpression(expression.Index);
if (index.Type is not NubIntType)
{
throw new TypeCheckerException(Diagnostic
.Error("Array indexer must be of type int")
.At(expression.Index)
.Build());
}
var target = CheckExpression(expression.Target);
return target.Type switch
{
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),
_ => throw new TypeCheckerException(Diagnostic.Error($"Cannot use array indexer on type {target.Type}").At(expression).Build())
};
@@ -581,12 +585,7 @@ public sealed class TypeChecker
var scopeIdent = CurrentScope.LookupVariable(expression.Name);
if (scopeIdent != null)
{
return scopeIdent.Kind switch
{
VariableKind.LValue => new LValueIdentifierNode(expression.Tokens, scopeIdent.Type, expression.Name),
VariableKind.RValue => new RValueIdentifierNode(expression.Tokens, scopeIdent.Type, expression.Name),
_ => throw new ArgumentOutOfRangeException()
};
return new VariableIdentifierNode(expression.Tokens, scopeIdent.Type, expression.Name);
}
var module = _importedModules[CurrentScope.Module];
@@ -635,7 +634,7 @@ public sealed class TypeChecker
{
NubCStringType => new CStringLiteralNode(expression.Tokens, expectedType, expression.Value),
NubStringType => new StringLiteralNode(expression.Tokens, expectedType, expression.Value),
_ => new CStringLiteralNode(expression.Tokens, new NubCStringType(), expression.Value)
_ => new StringLiteralNode(expression.Tokens, new NubStringType(), expression.Value)
};
}
@@ -894,13 +893,7 @@ public sealed class TypeChecker
}
}
public enum VariableKind
{
LValue,
RValue
}
public record Variable(string Name, NubType Type, VariableKind Kind);
public record Variable(string Name, NubType Type);
public class Scope(string module, Scope? parent = null)
{

View File

@@ -14,6 +14,8 @@ public static class CType
NubFloatType floatType => CreateFloatType(floatType, variableName),
NubCStringType => "char*" + (variableName != null ? $" {variableName}" : ""),
NubPointerType ptr => CreatePointerType(ptr, variableName),
NubSliceType nubSliceType => "slice" + (variableName != null ? $" {variableName}" : ""),
NubStringType nubStringType => "string" + (variableName != null ? $" {variableName}" : ""),
NubConstArrayType arr => CreateConstArrayType(arr, variableName),
NubArrayType arr => CreateArrayType(arr, variableName),
NubFuncType fn => CreateFuncType(fn, variableName),

View File

@@ -1,3 +1,4 @@
using System.Text;
using NubLang.Ast;
using NubLang.Syntax;
@@ -39,6 +40,21 @@ public class Generator
_writer.WriteLine("#include <stddef.h>");
_writer.WriteLine();
_writer.WriteLine("""
typedef struct
{
size_t length;
uint8_t *data;
} string;
typedef struct
{
size_t length;
void *data;
} slice;
""");
foreach (var structType in _compilationUnit.ImportedStructTypes)
{
_writer.WriteLine("typedef struct");
@@ -68,22 +84,6 @@ public class Generator
_writer.WriteLine();
}
// note(nub31): declare extern functions
foreach (var funcNode in _compilationUnit.Functions)
{
if (funcNode.Body != null) continue;
EmitLine(funcNode.Tokens.FirstOrDefault());
var parameters = funcNode.Prototype.Parameters.Count != 0
? string.Join(", ", funcNode.Prototype.Parameters.Select(x => CType.Create(x.Type, x.Name)))
: "void";
var name = FuncName(funcNode.Module, funcNode.Name, funcNode.Prototype.ExternSymbol);
_writer.WriteLine($"{CType.Create(funcNode.Prototype.ReturnType, name)}({parameters});");
}
_writer.WriteLine();
// note(nub31): Normal functions
foreach (var funcNode in _compilationUnit.Functions)
{
@@ -94,11 +94,6 @@ public class Generator
? string.Join(", ", funcNode.Prototype.Parameters.Select(x => CType.Create(x.Type, x.Name)))
: "void";
if (funcNode.Prototype.ExternSymbol == null)
{
_writer.Write("static ");
}
var name = FuncName(funcNode.Module, funcNode.Name, funcNode.Prototype.ExternSymbol);
_writer.WriteLine($"{CType.Create(funcNode.Prototype.ReturnType, name)}({parameters})");
EmitBlock(funcNode.Body);
@@ -165,11 +160,13 @@ public class Generator
private void EmitBreak(BreakNode _)
{
// todo(nub31): Emit deferred statements
_writer.WriteLine("break;");
}
private void EmitContinue(ContinueNode _)
{
// todo(nub31): Emit deferred statements
_writer.WriteLine("continue;");
}
@@ -265,38 +262,31 @@ public class Generator
ArrayIndexAccessNode arrayIndexAccessNode => EmitArrayIndexAccess(arrayIndexAccessNode),
ArrayInitializerNode arrayInitializerNode => EmitArrayInitializer(arrayInitializerNode),
BinaryExpressionNode binaryExpressionNode => EmitBinaryExpression(binaryExpressionNode),
BoolLiteralNode boolLiteralNode => EmitBoolLiteral(boolLiteralNode),
ConstArrayIndexAccessNode constArrayIndexAccessNode => EmitConstArrayIndexAccess(constArrayIndexAccessNode),
ConstArrayInitializerNode constArrayInitializerNode => EmitConstArrayInitializer(constArrayInitializerNode),
// ConvertConstArrayToArrayNode convertConstArrayToArrayNode => EmitConvertConstArrayToArray(convertConstArrayToArrayNode),
BoolLiteralNode boolLiteralNode => boolLiteralNode.Value ? "true" : "false",
ConvertCStringToStringNode convertCStringToStringNode => EmitConvertCStringToString(convertCStringToStringNode),
ConvertFloatNode convertFloatNode => EmitConvertFloat(convertFloatNode),
ConvertIntNode convertIntNode => EmitConvertInt(convertIntNode),
CStringLiteralNode cStringLiteralNode => EmitCStringLiteral(cStringLiteralNode),
ConvertStringToCStringNode convertStringToCStringNode => EmitConvertStringToCString(convertStringToCStringNode),
CStringLiteralNode cStringLiteralNode => $"\"{cStringLiteralNode.Value}\"",
DereferenceNode dereferenceNode => EmitDereference(dereferenceNode),
Float32LiteralNode float32LiteralNode => EmitFloat32Literal(float32LiteralNode),
Float64LiteralNode float64LiteralNode => EmitFloat64Literal(float64LiteralNode),
FloatToIntBuiltinNode floatToIntBuiltinNode => EmitFloatToIntBuiltin(floatToIntBuiltinNode),
FuncCallNode funcCallNode => EmitFuncCall(funcCallNode),
FuncIdentifierNode funcIdentifierNode => EmitFuncIdentifier(funcIdentifierNode),
FuncIdentifierNode funcIdentifierNode => FuncName(funcIdentifierNode.Module, funcIdentifierNode.Name, funcIdentifierNode.ExternSymbol),
IntLiteralNode intLiteralNode => EmitIntLiteral(intLiteralNode),
AddressOfNode addressOfNode => EmitAddressOf(addressOfNode),
LValueIdentifierNode lValueIdentifierNode => EmitLValueIdentifier(lValueIdentifierNode),
RValueIdentifierNode rValueIdentifierNode => EmitRValueIdentifier(rValueIdentifierNode),
SizeBuiltinNode sizeBuiltinNode => EmitSizeBuiltin(sizeBuiltinNode),
SizeBuiltinNode sizeBuiltinNode => $"sizeof({CType.Create(sizeBuiltinNode.TargetType)})",
SliceIndexAccessNode sliceIndexAccessNode => EmitSliceArrayIndexAccess(sliceIndexAccessNode),
StringLiteralNode stringLiteralNode => EmitStringLiteral(stringLiteralNode),
StructFieldAccessNode structFieldAccessNode => EmitStructFieldAccess(structFieldAccessNode),
StructInitializerNode structInitializerNode => EmitStructInitializer(structInitializerNode),
UIntLiteralNode uIntLiteralNode => EmitUIntLiteral(uIntLiteralNode),
UnaryExpressionNode unaryExpressionNode => EmitUnaryExpression(unaryExpressionNode),
VariableIdentifierNode variableIdentifierNode => variableIdentifierNode.Name,
_ => throw new ArgumentOutOfRangeException(nameof(expressionNode))
};
if (expressionNode is ConstArrayInitializerNode)
{
return expr;
}
return $"({expr})";
}
@@ -309,10 +299,9 @@ public class Generator
private string EmitArrayInitializer(ArrayInitializerNode arrayInitializerNode)
{
var type = (NubArrayType)arrayInitializerNode.Type;
var capacity = EmitExpression(arrayInitializerNode.Capacity);
var tmp = NewTmp();
_writer.WriteLine($"{CType.Create(type.ElementType)} {tmp}[{capacity}];");
_writer.WriteLine($"{CType.Create(arrayInitializerNode.ElementType)} {tmp}[{capacity}];");
return tmp;
}
@@ -347,30 +336,12 @@ public class Generator
return $"{left} {op} {right}";
}
private string EmitBoolLiteral(BoolLiteralNode boolLiteralNode)
private string EmitConvertCStringToString(ConvertCStringToStringNode convertCStringToStringNode)
{
return boolLiteralNode.Value ? "true" : "false";
var value = EmitExpression(convertCStringToStringNode.Value);
return $"(string){{.length = strlen({value}), .data = {value}}}";
}
private string EmitConstArrayIndexAccess(ConstArrayIndexAccessNode constArrayIndexAccessNode)
{
var array = EmitExpression(constArrayIndexAccessNode.Target);
var index = EmitExpression(constArrayIndexAccessNode.Index);
// todo(nub31): We can emit bounds checking here
return $"{array}[{index}]";
}
private string EmitConstArrayInitializer(ConstArrayInitializerNode constArrayInitializerNode)
{
return "{0}";
}
// private string EmitConvertConstArrayToArray(ConvertConstArrayToArrayNode convertConstArrayToArrayNode)
// {
// var value = EmitExpression(convertConstArrayToArrayNode.Value);
// return $"({CType.Create(convertConstArrayToArrayNode.Type)}){value}";
// }
private string EmitConvertFloat(ConvertFloatNode convertFloatNode)
{
var value = EmitExpression(convertFloatNode.Value);
@@ -387,24 +358,21 @@ public class Generator
private string EmitConvertInt(ConvertIntNode convertIntNode)
{
var value = EmitExpression(convertIntNode.Value);
var targetType = (convertIntNode.TargetType.Signed, convertIntNode.TargetType.Width) switch
var targetType = convertIntNode.TargetType.Width switch
{
(false, 8) => "u8",
(false, 16) => "u16",
(false, 32) => "u32",
(false, 64) => "u64",
(true, 8) => "i8",
(true, 16) => "i16",
(true, 32) => "i32",
(true, 64) => "i64",
8 => convertIntNode.TargetType.Signed ? "int8_t" : "uint8_t",
16 => convertIntNode.TargetType.Signed ? "int16_t" : "uint16_t",
32 => convertIntNode.TargetType.Signed ? "int32_t" : "uint32_t",
64 => convertIntNode.TargetType.Signed ? "int64_t" : "uint64_t",
_ => throw new ArgumentOutOfRangeException()
};
return $"({targetType}){value}";
}
private string EmitCStringLiteral(CStringLiteralNode cStringLiteralNode)
private string EmitConvertStringToCString(ConvertStringToCStringNode convertStringToCStringNode)
{
return $"\"{cStringLiteralNode.Value}\"";
var value = EmitExpression(convertStringToCStringNode.Value);
return $"(char*){value}.data";
}
private string EmitDereference(DereferenceNode dereferenceNode)
@@ -438,16 +406,12 @@ public class Generator
private string EmitFloatToIntBuiltin(FloatToIntBuiltinNode floatToIntBuiltinNode)
{
var value = EmitExpression(floatToIntBuiltinNode.Value);
var targetType = (floatToIntBuiltinNode.TargetType.Signed, floatToIntBuiltinNode.TargetType.Width) switch
var targetType = floatToIntBuiltinNode.TargetType.Width switch
{
(false, 8) => "u8",
(false, 16) => "u16",
(false, 32) => "u32",
(false, 64) => "u64",
(true, 8) => "i8",
(true, 16) => "i16",
(true, 32) => "i32",
(true, 64) => "i64",
8 => floatToIntBuiltinNode.TargetType.Signed ? "int8_t" : "uint8_t",
16 => floatToIntBuiltinNode.TargetType.Signed ? "int16_t" : "uint16_t",
32 => floatToIntBuiltinNode.TargetType.Signed ? "int32_t" : "uint32_t",
64 => floatToIntBuiltinNode.TargetType.Signed ? "int64_t" : "uint64_t",
_ => throw new ArgumentOutOfRangeException()
};
return $"({targetType}){value}";
@@ -460,11 +424,6 @@ public class Generator
return $"{name}({string.Join(", ", parameterNames)})";
}
private string EmitFuncIdentifier(FuncIdentifierNode funcIdentifierNode)
{
return FuncName(funcIdentifierNode.Module, funcIdentifierNode.Name, funcIdentifierNode.ExternSymbol);
}
private string EmitIntLiteral(IntLiteralNode intLiteralNode)
{
var type = (NubIntType)intLiteralNode.Type;
@@ -482,32 +441,18 @@ public class Generator
return $"&{value}";
}
private string EmitLValueIdentifier(LValueIdentifierNode lValueIdentifierNode)
{
return lValueIdentifierNode.Name;
}
private string EmitRValueIdentifier(RValueIdentifierNode rValueIdentifierNode)
{
return rValueIdentifierNode.Name;
}
private string EmitSizeBuiltin(SizeBuiltinNode sizeBuiltinNode)
{
return $"sizeof({CType.Create(sizeBuiltinNode.TargetType)})";
}
private string EmitSliceArrayIndexAccess(SliceIndexAccessNode sliceIndexAccessNode)
{
var value = EmitExpression(sliceIndexAccessNode.Target);
var index = EmitExpression(sliceIndexAccessNode.Index);
// todo(nub31): We can emit bounds checking here
return $"{value}.data[{index}]";
return $"(({CType.Create(sliceIndexAccessNode.Target.Type)}){value}.data)[{index}]";
}
private string EmitStringLiteral(StringLiteralNode stringLiteralNode)
{
throw new NotImplementedException();
var length = Encoding.UTF8.GetByteCount(stringLiteralNode.Value);
return $"(string){{.length = {length}, .data = \"{stringLiteralNode.Value}\"}}";
}
private string EmitStructFieldAccess(StructFieldAccessNode structFieldAccessNode)

View File

@@ -532,19 +532,10 @@ public sealed class Parser
private ExpressionSyntax ParseArrayInitializer(int startIndex)
{
if (TryExpectIntLiteral(out var intLiteral))
{
ExpectSymbol(Symbol.CloseBracket);
var type = ParseType();
return new ConstArrayInitializerSyntax(GetTokens(startIndex), Convert.ToInt64(intLiteral.Value, intLiteral.Base), type);
}
else
{
var capacity = ParseExpression();
ExpectSymbol(Symbol.CloseBracket);
var type = ParseType();
return new ArrayInitializerSyntax(GetTokens(startIndex), capacity, type);
}
var capacity = ParseExpression();
ExpectSymbol(Symbol.CloseBracket);
var type = ParseType();
return new ArrayInitializerSyntax(GetTokens(startIndex), capacity, type);
}
private StructInitializerSyntax ParseStructInitializer(int startIndex)

View File

@@ -88,8 +88,6 @@ public record ModuleIdentifierSyntax(List<Token> Tokens, string Module, string N
public record ArrayInitializerSyntax(List<Token> Tokens, ExpressionSyntax Capacity, TypeSyntax ElementType) : ExpressionSyntax(Tokens);
public record ConstArrayInitializerSyntax(List<Token> Tokens, long Capacity, TypeSyntax ElementType) : ExpressionSyntax(Tokens);
public record ArrayIndexAccessSyntax(List<Token> Tokens, ExpressionSyntax Target, ExpressionSyntax Index) : ExpressionSyntax(Tokens);
public record AddressOfSyntax(List<Token> Tokens, ExpressionSyntax Target) : ExpressionSyntax(Tokens);

View File

@@ -4,7 +4,6 @@ extern "puts" func puts(text: cstring)
extern "main" func main(argc: i64, argv: [?]cstring): i64
{
let x = [10]i32
x[0] = 23
return 0
let x = [23]i32
return x[0]
}

View File

@@ -2,9 +2,9 @@ module "main"
extern "puts" func puts(text: cstring)
extern "main" func main(args: []cstring): i64
func main(argc: i32, argv: [?]cstring): i32
{
defer puts("Goodybye World")
puts("Hello World")
defer puts("Bye cruel world!")
puts("Hello world!")
return 0
}