...
This commit is contained in:
@@ -45,6 +45,10 @@ def map_type(clang_type: Type):
|
|||||||
size = canonical.get_array_size()
|
size = canonical.get_array_size()
|
||||||
return f"[{size}]{map_type(element_type)}"
|
return f"[{size}]{map_type(element_type)}"
|
||||||
|
|
||||||
|
if kind == TypeKind.INCOMPLETEARRAY:
|
||||||
|
element_type = canonical.get_array_element_type()
|
||||||
|
return f"[?]{map_type(element_type)}"
|
||||||
|
|
||||||
if kind == TypeKind.FUNCTIONPROTO or kind == TypeKind.FUNCTIONNOPROTO:
|
if kind == TypeKind.FUNCTIONPROTO or kind == TypeKind.FUNCTIONNOPROTO:
|
||||||
arg_types = []
|
arg_types = []
|
||||||
|
|
||||||
|
|||||||
@@ -103,10 +103,11 @@ if (modules.TryGetValue("main", out var mainModule))
|
|||||||
.text
|
.text
|
||||||
.globl _start
|
.globl _start
|
||||||
_start:
|
_start:
|
||||||
mov rdi, rsp # Pass stack pointer to main (length + cstring pointers)
|
mov rdi, [rsp] # argc
|
||||||
|
mov rsi, [rsp + 8] # argv
|
||||||
call {mainFunction.Prototype.ExternSymbol}
|
call {mainFunction.Prototype.ExternSymbol}
|
||||||
mov rdi, rax # Move return value into rdi
|
mov rdi, rax # Move return value into rdi
|
||||||
mov rax, 60 # syscall: exit
|
mov rax, 60 # syscall: exit
|
||||||
syscall
|
syscall
|
||||||
|
|
||||||
""";
|
""";
|
||||||
|
|||||||
@@ -108,8 +108,14 @@ public record FuncIdentifierNode(List<Token> Tokens, NubType Type, string Module
|
|||||||
|
|
||||||
public record ArrayInitializerNode(List<Token> Tokens, NubType Type, ExpressionNode Capacity, NubType ElementType) : 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 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);
|
public record AddressOfNode(List<Token> Tokens, NubType Type, LValueExpressionNode LValue) : RValueExpressionNode(Tokens, Type);
|
||||||
|
|
||||||
public record StructFieldAccessNode(List<Token> Tokens, NubType Type, ExpressionNode Target, string Field) : LValueExpressionNode(Tokens, Type);
|
public record StructFieldAccessNode(List<Token> Tokens, NubType Type, ExpressionNode Target, string Field) : LValueExpressionNode(Tokens, Type);
|
||||||
|
|||||||
@@ -5,9 +5,6 @@ namespace NubLang.Ast;
|
|||||||
|
|
||||||
public abstract class NubType : IEquatable<NubType>
|
public abstract class NubType : IEquatable<NubType>
|
||||||
{
|
{
|
||||||
public abstract bool IsValueType { get; }
|
|
||||||
public abstract bool IsScalar { get; }
|
|
||||||
|
|
||||||
public override bool Equals(object? obj) => obj is NubType other && Equals(other);
|
public override bool Equals(object? obj) => obj is NubType other && Equals(other);
|
||||||
public abstract bool Equals(NubType? other);
|
public abstract bool Equals(NubType? other);
|
||||||
|
|
||||||
@@ -20,9 +17,6 @@ public abstract class NubType : IEquatable<NubType>
|
|||||||
|
|
||||||
public class NubVoidType : NubType
|
public class NubVoidType : NubType
|
||||||
{
|
{
|
||||||
public override bool IsValueType => false;
|
|
||||||
public override bool IsScalar => false;
|
|
||||||
|
|
||||||
public override string ToString() => "void";
|
public override string ToString() => "void";
|
||||||
public override bool Equals(NubType? other) => other is NubVoidType;
|
public override bool Equals(NubType? other) => other is NubVoidType;
|
||||||
public override int GetHashCode() => HashCode.Combine(typeof(NubVoidType));
|
public override int GetHashCode() => HashCode.Combine(typeof(NubVoidType));
|
||||||
@@ -30,9 +24,6 @@ public class NubVoidType : NubType
|
|||||||
|
|
||||||
public sealed class NubIntType(bool signed, int width) : NubType
|
public sealed class NubIntType(bool signed, int width) : NubType
|
||||||
{
|
{
|
||||||
public override bool IsValueType => true;
|
|
||||||
public override bool IsScalar => true;
|
|
||||||
|
|
||||||
public bool Signed { get; } = signed;
|
public bool Signed { get; } = signed;
|
||||||
public int Width { get; } = width;
|
public int Width { get; } = width;
|
||||||
|
|
||||||
@@ -43,9 +34,6 @@ public sealed class NubIntType(bool signed, int width) : NubType
|
|||||||
|
|
||||||
public sealed class NubFloatType(int width) : NubType
|
public sealed class NubFloatType(int width) : NubType
|
||||||
{
|
{
|
||||||
public override bool IsValueType => true;
|
|
||||||
public override bool IsScalar => true;
|
|
||||||
|
|
||||||
public int Width { get; } = width;
|
public int Width { get; } = width;
|
||||||
|
|
||||||
public override string ToString() => $"f{Width}";
|
public override string ToString() => $"f{Width}";
|
||||||
@@ -55,9 +43,6 @@ public sealed class NubFloatType(int width) : NubType
|
|||||||
|
|
||||||
public class NubBoolType : NubType
|
public class NubBoolType : NubType
|
||||||
{
|
{
|
||||||
public override bool IsValueType => true;
|
|
||||||
public override bool IsScalar => true;
|
|
||||||
|
|
||||||
public override string ToString() => "bool";
|
public override string ToString() => "bool";
|
||||||
public override bool Equals(NubType? other) => other is NubBoolType;
|
public override bool Equals(NubType? other) => other is NubBoolType;
|
||||||
public override int GetHashCode() => HashCode.Combine(typeof(NubBoolType));
|
public override int GetHashCode() => HashCode.Combine(typeof(NubBoolType));
|
||||||
@@ -65,9 +50,6 @@ public class NubBoolType : NubType
|
|||||||
|
|
||||||
public sealed class NubPointerType(NubType baseType) : NubType
|
public sealed class NubPointerType(NubType baseType) : NubType
|
||||||
{
|
{
|
||||||
public override bool IsValueType => true;
|
|
||||||
public override bool IsScalar => true;
|
|
||||||
|
|
||||||
public NubType BaseType { get; } = baseType;
|
public NubType BaseType { get; } = baseType;
|
||||||
|
|
||||||
public override string ToString() => "^" + BaseType;
|
public override string ToString() => "^" + BaseType;
|
||||||
@@ -77,9 +59,6 @@ public sealed class NubPointerType(NubType baseType) : NubType
|
|||||||
|
|
||||||
public class NubFuncType(List<NubType> parameters, NubType returnType) : NubType
|
public class NubFuncType(List<NubType> parameters, NubType returnType) : NubType
|
||||||
{
|
{
|
||||||
public override bool IsValueType => true;
|
|
||||||
public override bool IsScalar => true;
|
|
||||||
|
|
||||||
public List<NubType> Parameters { get; } = parameters;
|
public List<NubType> Parameters { get; } = parameters;
|
||||||
public NubType ReturnType { get; } = returnType;
|
public NubType ReturnType { get; } = returnType;
|
||||||
|
|
||||||
@@ -102,9 +81,6 @@ public class NubFuncType(List<NubType> parameters, NubType returnType) : NubType
|
|||||||
|
|
||||||
public class NubStructType(string module, string name, List<NubStructFieldType> fields) : NubType
|
public class NubStructType(string module, string name, List<NubStructFieldType> fields) : NubType
|
||||||
{
|
{
|
||||||
public override bool IsValueType => true;
|
|
||||||
public override bool IsScalar => false;
|
|
||||||
|
|
||||||
public string Module { get; } = module;
|
public string Module { get; } = module;
|
||||||
public string Name { get; } = name;
|
public string Name { get; } = name;
|
||||||
public List<NubStructFieldType> Fields { get; set; } = fields;
|
public List<NubStructFieldType> Fields { get; set; } = fields;
|
||||||
@@ -121,43 +97,36 @@ public class NubStructFieldType(string name, NubType type, bool hasDefaultValue)
|
|||||||
public bool HasDefaultValue { get; } = hasDefaultValue;
|
public bool HasDefaultValue { get; } = hasDefaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NubStructFuncType(string name, List<NubType> parameters, NubType returnType)
|
public class NubSliceType(NubType elementType) : NubType
|
||||||
{
|
{
|
||||||
public string Name { get; } = name;
|
|
||||||
public List<NubType> Parameters { get; } = parameters;
|
|
||||||
public NubType ReturnType { get; } = returnType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class NubArrayType(NubType elementType) : NubType
|
|
||||||
{
|
|
||||||
public override bool IsValueType => false;
|
|
||||||
public override bool IsScalar => true;
|
|
||||||
|
|
||||||
public NubType ElementType { get; } = elementType;
|
public NubType ElementType { get; } = elementType;
|
||||||
|
|
||||||
public override string ToString() => "[]" + ElementType;
|
public override string ToString() => "[]" + ElementType;
|
||||||
public override bool Equals(NubType? other) => other is NubArrayType array && ElementType.Equals(array.ElementType);
|
public override bool Equals(NubType? other) => other is NubSliceType slice && ElementType.Equals(slice.ElementType);
|
||||||
public override int GetHashCode() => HashCode.Combine(typeof(NubArrayType), ElementType);
|
public override int GetHashCode() => HashCode.Combine(typeof(NubSliceType), ElementType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NubConstArrayType(NubType elementType, int size) : NubType
|
public class NubConstArrayType(NubType elementType, long size) : NubType
|
||||||
{
|
{
|
||||||
public override bool IsValueType => false;
|
|
||||||
public override bool IsScalar => true;
|
|
||||||
|
|
||||||
public NubType ElementType { get; } = elementType;
|
public NubType ElementType { get; } = elementType;
|
||||||
public int Size { get; } = size;
|
public long Size { get; } = size;
|
||||||
|
|
||||||
public override string ToString() => $"[{Size}]{ElementType}";
|
public override string ToString() => $"[{Size}]{ElementType}";
|
||||||
public override bool Equals(NubType? other) => other is NubConstArrayType array && ElementType.Equals(array.ElementType) && Size == array.Size;
|
public override bool Equals(NubType? other) => other is NubConstArrayType array && ElementType.Equals(array.ElementType) && Size == array.Size;
|
||||||
public override int GetHashCode() => HashCode.Combine(typeof(NubConstArrayType), ElementType, Size);
|
public override int GetHashCode() => HashCode.Combine(typeof(NubConstArrayType), ElementType, Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class NubArrayType(NubType elementType) : NubType
|
||||||
|
{
|
||||||
|
public NubType ElementType { get; } = elementType;
|
||||||
|
|
||||||
|
public override string ToString() => $"[?]{ElementType}";
|
||||||
|
public override bool Equals(NubType? other) => other is NubArrayType array && ElementType.Equals(array.ElementType);
|
||||||
|
public override int GetHashCode() => HashCode.Combine(typeof(NubArrayType), ElementType);
|
||||||
|
}
|
||||||
|
|
||||||
public class NubCStringType : NubType
|
public class NubCStringType : NubType
|
||||||
{
|
{
|
||||||
public override bool IsValueType => false;
|
|
||||||
public override bool IsScalar => false;
|
|
||||||
|
|
||||||
public override string ToString() => "cstring";
|
public override string ToString() => "cstring";
|
||||||
public override bool Equals(NubType? other) => other is NubCStringType;
|
public override bool Equals(NubType? other) => other is NubCStringType;
|
||||||
public override int GetHashCode() => HashCode.Combine(typeof(NubCStringType));
|
public override int GetHashCode() => HashCode.Combine(typeof(NubCStringType));
|
||||||
@@ -165,9 +134,6 @@ public class NubCStringType : NubType
|
|||||||
|
|
||||||
public class NubStringType : NubType
|
public class NubStringType : NubType
|
||||||
{
|
{
|
||||||
public override bool IsValueType => false;
|
|
||||||
public override bool IsScalar => false;
|
|
||||||
|
|
||||||
public override string ToString() => "string";
|
public override string ToString() => "string";
|
||||||
public override bool Equals(NubType? other) => other is NubStringType;
|
public override bool Equals(NubType? other) => other is NubStringType;
|
||||||
public override int GetHashCode() => HashCode.Combine(typeof(NubStringType));
|
public override int GetHashCode() => HashCode.Combine(typeof(NubStringType));
|
||||||
@@ -190,7 +156,7 @@ public static class NameMangler
|
|||||||
NubCStringType => "CS",
|
NubCStringType => "CS",
|
||||||
NubStringType => "S",
|
NubStringType => "S",
|
||||||
NubPointerType p => "P" + EncodeType(p.BaseType),
|
NubPointerType p => "P" + EncodeType(p.BaseType),
|
||||||
NubArrayType a => "A" + EncodeType(a.ElementType),
|
NubSliceType a => "A" + EncodeType(a.ElementType),
|
||||||
NubFuncType fn => "FN(" + string.Join(",", fn.Parameters.Select(EncodeType)) + ")" + EncodeType(fn.ReturnType),
|
NubFuncType fn => "FN(" + string.Join(",", fn.Parameters.Select(EncodeType)) + ")" + EncodeType(fn.ReturnType),
|
||||||
NubStructType st => "ST(" + st.Module + "." + st.Name + ")",
|
NubStructType st => "ST(" + st.Module + "." + st.Name + ")",
|
||||||
_ => throw new NotSupportedException($"Cannot encode type: {node}")
|
_ => throw new NotSupportedException($"Cannot encode type: {node}")
|
||||||
|
|||||||
@@ -248,6 +248,7 @@ public sealed class TypeChecker
|
|||||||
LocalIdentifierSyntax expression => CheckLocalIdentifier(expression),
|
LocalIdentifierSyntax expression => CheckLocalIdentifier(expression),
|
||||||
ModuleIdentifierSyntax expression => CheckModuleIdentifier(expression),
|
ModuleIdentifierSyntax expression => CheckModuleIdentifier(expression),
|
||||||
BoolLiteralSyntax expression => CheckBoolLiteral(expression),
|
BoolLiteralSyntax expression => CheckBoolLiteral(expression),
|
||||||
|
ConstArrayInitializerSyntax expression => CheckConstArrayInitializer(expression),
|
||||||
StringLiteralSyntax expression => CheckStringLiteral(expression, expectedType),
|
StringLiteralSyntax expression => CheckStringLiteral(expression, expectedType),
|
||||||
IntLiteralSyntax expression => CheckIntLiteral(expression, expectedType),
|
IntLiteralSyntax expression => CheckIntLiteral(expression, expectedType),
|
||||||
FloatLiteralSyntax expression => CheckFloatLiteral(expression, expectedType),
|
FloatLiteralSyntax expression => CheckFloatLiteral(expression, expectedType),
|
||||||
@@ -264,6 +265,11 @@ public sealed class TypeChecker
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (result.Type is NubConstArrayType && expectedType is NubArrayType)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
if (result.Type is NubIntType sourceIntType && expectedType is NubIntType targetIntType)
|
if (result.Type is NubIntType sourceIntType && expectedType is NubIntType targetIntType)
|
||||||
{
|
{
|
||||||
if (sourceIntType.Signed == targetIntType.Signed && sourceIntType.Width < targetIntType.Width)
|
if (sourceIntType.Signed == targetIntType.Signed && sourceIntType.Width < targetIntType.Width)
|
||||||
@@ -283,6 +289,13 @@ public sealed class TypeChecker
|
|||||||
throw new TypeCheckerException(Diagnostic.Error($"Cannot convert {result.Type} to {expectedType}").At(node).Build());
|
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)
|
private FloatToIntBuiltinNode CheckFloatToInt(FloatToIntBuiltinSyntax expression)
|
||||||
{
|
{
|
||||||
var value = CheckExpression(expression.Value);
|
var value = CheckExpression(expression.Value);
|
||||||
@@ -318,16 +331,18 @@ public sealed class TypeChecker
|
|||||||
return new AddressOfNode(expression.Tokens, type, lvalue);
|
return new AddressOfNode(expression.Tokens, type, lvalue);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ArrayIndexAccessNode CheckArrayIndexAccess(ArrayIndexAccessSyntax expression)
|
private ExpressionNode CheckArrayIndexAccess(ArrayIndexAccessSyntax expression)
|
||||||
{
|
{
|
||||||
var index = CheckExpression(expression.Index, new NubIntType(false, 64));
|
var index = CheckExpression(expression.Index, new NubIntType(false, 64));
|
||||||
var target = CheckExpression(expression.Target);
|
var target = CheckExpression(expression.Target);
|
||||||
if (target.Type is not NubArrayType arrayType)
|
|
||||||
{
|
|
||||||
throw new TypeCheckerException(Diagnostic.Error($"Cannot use array indexer on type {target.Type}").At(expression).Build());
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ArrayIndexAccessNode(expression.Tokens, arrayType.ElementType, target, index);
|
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())
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private ArrayInitializerNode CheckArrayInitializer(ArrayInitializerSyntax expression)
|
private ArrayInitializerNode CheckArrayInitializer(ArrayInitializerSyntax expression)
|
||||||
@@ -808,12 +823,13 @@ public sealed class TypeChecker
|
|||||||
{
|
{
|
||||||
return type switch
|
return type switch
|
||||||
{
|
{
|
||||||
|
ArrayTypeSyntax arr => new NubArrayType(ResolveType(arr.BaseType)),
|
||||||
BoolTypeSyntax => new NubBoolType(),
|
BoolTypeSyntax => new NubBoolType(),
|
||||||
CStringTypeSyntax => new NubCStringType(),
|
CStringTypeSyntax => new NubCStringType(),
|
||||||
IntTypeSyntax i => new NubIntType(i.Signed, i.Width),
|
IntTypeSyntax i => new NubIntType(i.Signed, i.Width),
|
||||||
FloatTypeSyntax f => new NubFloatType(f.Width),
|
FloatTypeSyntax f => new NubFloatType(f.Width),
|
||||||
FuncTypeSyntax func => new NubFuncType(func.Parameters.Select(ResolveType).ToList(), ResolveType(func.ReturnType)),
|
FuncTypeSyntax func => new NubFuncType(func.Parameters.Select(ResolveType).ToList(), ResolveType(func.ReturnType)),
|
||||||
ArrayTypeSyntax arr => new NubArrayType(ResolveType(arr.BaseType)),
|
SliceTypeSyntax slice => new NubSliceType(ResolveType(slice.BaseType)),
|
||||||
ConstArrayTypeSyntax arr => new NubConstArrayType(ResolveType(arr.BaseType), arr.Size),
|
ConstArrayTypeSyntax arr => new NubConstArrayType(ResolveType(arr.BaseType), arr.Size),
|
||||||
PointerTypeSyntax ptr => new NubPointerType(ResolveType(ptr.BaseType)),
|
PointerTypeSyntax ptr => new NubPointerType(ResolveType(ptr.BaseType)),
|
||||||
StringTypeSyntax => new NubStringType(),
|
StringTypeSyntax => new NubStringType(),
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ public class Generator
|
|||||||
return $"_t{++_tmpIndex}";
|
return $"_t{++_tmpIndex}";
|
||||||
}
|
}
|
||||||
|
|
||||||
private string MapNameWithType(NubType nubType, string name)
|
private static string MapNameWithType(NubType nubType, string name)
|
||||||
{
|
{
|
||||||
var prefix = "";
|
var prefix = "";
|
||||||
var postfix = "";
|
var postfix = "";
|
||||||
@@ -46,8 +46,9 @@ public class Generator
|
|||||||
{
|
{
|
||||||
return type switch
|
return type switch
|
||||||
{
|
{
|
||||||
|
NubSliceType sliceType => throw new NotImplementedException(),
|
||||||
|
NubConstArrayType constArrayType => MapBaseType(constArrayType.ElementType),
|
||||||
NubArrayType arrayType => MapBaseType(arrayType.ElementType),
|
NubArrayType arrayType => MapBaseType(arrayType.ElementType),
|
||||||
NubConstArrayType arrayType => MapBaseType(arrayType.ElementType),
|
|
||||||
NubBoolType => "bool",
|
NubBoolType => "bool",
|
||||||
NubCStringType => "char",
|
NubCStringType => "char",
|
||||||
NubFloatType floatType => floatType.Width switch
|
NubFloatType floatType => floatType.Width switch
|
||||||
@@ -121,6 +122,22 @@ public class Generator
|
|||||||
|
|
||||||
_writer.WriteLine();
|
_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 => MapNameWithType(x.Type, x.Name)))
|
||||||
|
: "void";
|
||||||
|
|
||||||
|
var name = FuncName(funcNode.Module, funcNode.Name, funcNode.Prototype.ExternSymbol);
|
||||||
|
_writer.WriteLine($"{MapNameWithType(funcNode.Prototype.ReturnType, name)}({parameters});");
|
||||||
|
}
|
||||||
|
|
||||||
|
_writer.WriteLine();
|
||||||
|
|
||||||
// note(nub31): Normal functions
|
// note(nub31): Normal functions
|
||||||
foreach (var funcNode in _compilationUnit.Functions)
|
foreach (var funcNode in _compilationUnit.Functions)
|
||||||
{
|
{
|
||||||
@@ -317,7 +334,7 @@ public class Generator
|
|||||||
|
|
||||||
private void EmitVariableDeclaration(VariableDeclarationNode variableDeclarationNode)
|
private void EmitVariableDeclaration(VariableDeclarationNode variableDeclarationNode)
|
||||||
{
|
{
|
||||||
if (variableDeclarationNode.Assignment != null)
|
if (variableDeclarationNode.Assignment is { Type: not NubArrayType and not NubConstArrayType })
|
||||||
{
|
{
|
||||||
var value = EmitExpression(variableDeclarationNode.Assignment);
|
var value = EmitExpression(variableDeclarationNode.Assignment);
|
||||||
_writer.WriteLine($"{MapNameWithType(variableDeclarationNode.Type, variableDeclarationNode.Name)} = {value};");
|
_writer.WriteLine($"{MapNameWithType(variableDeclarationNode.Type, variableDeclarationNode.Name)} = {value};");
|
||||||
@@ -343,6 +360,8 @@ public class Generator
|
|||||||
ArrayInitializerNode arrayInitializerNode => EmitArrayInitializer(arrayInitializerNode),
|
ArrayInitializerNode arrayInitializerNode => EmitArrayInitializer(arrayInitializerNode),
|
||||||
BinaryExpressionNode binaryExpressionNode => EmitBinaryExpression(binaryExpressionNode),
|
BinaryExpressionNode binaryExpressionNode => EmitBinaryExpression(binaryExpressionNode),
|
||||||
BoolLiteralNode boolLiteralNode => EmitBoolLiteral(boolLiteralNode),
|
BoolLiteralNode boolLiteralNode => EmitBoolLiteral(boolLiteralNode),
|
||||||
|
ConstArrayIndexAccessNode constArrayIndexAccessNode => EmitConstArrayIndexAccess(constArrayIndexAccessNode),
|
||||||
|
ConstArrayInitializerNode constArrayInitializerNode => EmitConstArrayInitializer(constArrayInitializerNode),
|
||||||
ConvertFloatNode convertFloatNode => EmitConvertFloat(convertFloatNode),
|
ConvertFloatNode convertFloatNode => EmitConvertFloat(convertFloatNode),
|
||||||
ConvertIntNode convertIntNode => EmitConvertInt(convertIntNode),
|
ConvertIntNode convertIntNode => EmitConvertInt(convertIntNode),
|
||||||
CStringLiteralNode cStringLiteralNode => EmitCStringLiteral(cStringLiteralNode),
|
CStringLiteralNode cStringLiteralNode => EmitCStringLiteral(cStringLiteralNode),
|
||||||
@@ -357,6 +376,7 @@ public class Generator
|
|||||||
LValueIdentifierNode lValueIdentifierNode => EmitLValueIdentifier(lValueIdentifierNode),
|
LValueIdentifierNode lValueIdentifierNode => EmitLValueIdentifier(lValueIdentifierNode),
|
||||||
RValueIdentifierNode rValueIdentifierNode => EmitRValueIdentifier(rValueIdentifierNode),
|
RValueIdentifierNode rValueIdentifierNode => EmitRValueIdentifier(rValueIdentifierNode),
|
||||||
SizeBuiltinNode sizeBuiltinNode => EmitSizeBuiltin(sizeBuiltinNode),
|
SizeBuiltinNode sizeBuiltinNode => EmitSizeBuiltin(sizeBuiltinNode),
|
||||||
|
SliceIndexAccessNode sliceIndexAccessNode => EmitSliceArrayIndexAccess(sliceIndexAccessNode),
|
||||||
StringLiteralNode stringLiteralNode => EmitStringLiteral(stringLiteralNode),
|
StringLiteralNode stringLiteralNode => EmitStringLiteral(stringLiteralNode),
|
||||||
StructFieldAccessNode structFieldAccessNode => EmitStructFieldAccess(structFieldAccessNode),
|
StructFieldAccessNode structFieldAccessNode => EmitStructFieldAccess(structFieldAccessNode),
|
||||||
StructInitializerNode structInitializerNode => EmitStructInitializer(structInitializerNode),
|
StructInitializerNode structInitializerNode => EmitStructInitializer(structInitializerNode),
|
||||||
@@ -416,6 +436,19 @@ public class Generator
|
|||||||
return boolLiteralNode.Value ? "true" : "false";
|
return boolLiteralNode.Value ? "true" : "false";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
private string EmitConvertFloat(ConvertFloatNode convertFloatNode)
|
private string EmitConvertFloat(ConvertFloatNode convertFloatNode)
|
||||||
{
|
{
|
||||||
var value = EmitExpression(convertFloatNode.Value);
|
var value = EmitExpression(convertFloatNode.Value);
|
||||||
@@ -544,6 +577,14 @@ public class Generator
|
|||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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}]";
|
||||||
|
}
|
||||||
|
|
||||||
private string EmitStringLiteral(StringLiteralNode stringLiteralNode)
|
private string EmitStringLiteral(StringLiteralNode stringLiteralNode)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
|
|||||||
@@ -530,12 +530,21 @@ public sealed class Parser
|
|||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ArrayInitializerSyntax ParseArrayInitializer(int startIndex)
|
private ExpressionSyntax ParseArrayInitializer(int startIndex)
|
||||||
{
|
{
|
||||||
var capacity = ParseExpression();
|
if (TryExpectIntLiteral(out var intLiteral))
|
||||||
ExpectSymbol(Symbol.CloseBracket);
|
{
|
||||||
var type = ParseType();
|
ExpectSymbol(Symbol.CloseBracket);
|
||||||
return new ArrayInitializerSyntax(GetTokens(startIndex), capacity, type);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private StructInitializerSyntax ParseStructInitializer(int startIndex)
|
private StructInitializerSyntax ParseStructInitializer(int startIndex)
|
||||||
@@ -707,13 +716,19 @@ public sealed class Parser
|
|||||||
{
|
{
|
||||||
ExpectSymbol(Symbol.CloseBracket);
|
ExpectSymbol(Symbol.CloseBracket);
|
||||||
var baseType = ParseType();
|
var baseType = ParseType();
|
||||||
return new ConstArrayTypeSyntax(GetTokens(startIndex), baseType, int.Parse(intLiteral.Value));
|
return new ConstArrayTypeSyntax(GetTokens(startIndex), baseType, Convert.ToInt64(intLiteral.Value, intLiteral.Base));
|
||||||
|
}
|
||||||
|
else if (TryExpectSymbol(Symbol.QuestionMark))
|
||||||
|
{
|
||||||
|
ExpectSymbol(Symbol.CloseBracket);
|
||||||
|
var baseType = ParseType();
|
||||||
|
return new ArrayTypeSyntax(GetTokens(startIndex), baseType);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ExpectSymbol(Symbol.CloseBracket);
|
ExpectSymbol(Symbol.CloseBracket);
|
||||||
var baseType = ParseType();
|
var baseType = ParseType();
|
||||||
return new ArrayTypeSyntax(GetTokens(startIndex), baseType);
|
return new SliceTypeSyntax(GetTokens(startIndex), baseType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -88,6 +88,8 @@ public record ModuleIdentifierSyntax(List<Token> Tokens, string Module, string N
|
|||||||
|
|
||||||
public record ArrayInitializerSyntax(List<Token> Tokens, ExpressionSyntax Capacity, TypeSyntax ElementType) : ExpressionSyntax(Tokens);
|
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 ArrayIndexAccessSyntax(List<Token> Tokens, ExpressionSyntax Target, ExpressionSyntax Index) : ExpressionSyntax(Tokens);
|
||||||
|
|
||||||
public record AddressOfSyntax(List<Token> Tokens, ExpressionSyntax Target) : ExpressionSyntax(Tokens);
|
public record AddressOfSyntax(List<Token> Tokens, ExpressionSyntax Target) : ExpressionSyntax(Tokens);
|
||||||
@@ -134,9 +136,11 @@ public record StringTypeSyntax(List<Token> Tokens) : TypeSyntax(Tokens);
|
|||||||
|
|
||||||
public record CStringTypeSyntax(List<Token> Tokens) : TypeSyntax(Tokens);
|
public record CStringTypeSyntax(List<Token> Tokens) : TypeSyntax(Tokens);
|
||||||
|
|
||||||
|
public record SliceTypeSyntax(List<Token> Tokens, TypeSyntax BaseType) : TypeSyntax(Tokens);
|
||||||
|
|
||||||
public record ArrayTypeSyntax(List<Token> Tokens, TypeSyntax BaseType) : TypeSyntax(Tokens);
|
public record ArrayTypeSyntax(List<Token> Tokens, TypeSyntax BaseType) : TypeSyntax(Tokens);
|
||||||
|
|
||||||
public record ConstArrayTypeSyntax(List<Token> Tokens, TypeSyntax BaseType, int Size) : TypeSyntax(Tokens);
|
public record ConstArrayTypeSyntax(List<Token> Tokens, TypeSyntax BaseType, long Size) : TypeSyntax(Tokens);
|
||||||
|
|
||||||
public record CustomTypeSyntax(List<Token> Tokens, string Module, string Name) : TypeSyntax(Tokens);
|
public record CustomTypeSyntax(List<Token> Tokens, string Module, string Name) : TypeSyntax(Tokens);
|
||||||
|
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ public enum Symbol
|
|||||||
Module,
|
Module,
|
||||||
Import,
|
Import,
|
||||||
At,
|
At,
|
||||||
|
QuestionMark
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract record Token(SourceSpan Span);
|
public abstract record Token(SourceSpan Span);
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ public sealed class Tokenizer
|
|||||||
[['%']] = Symbol.Percent,
|
[['%']] = Symbol.Percent,
|
||||||
[['|']] = Symbol.Pipe,
|
[['|']] = Symbol.Pipe,
|
||||||
[['@']] = Symbol.At,
|
[['@']] = Symbol.At,
|
||||||
|
[['?']] = Symbol.QuestionMark,
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly (char[] Pattern, Symbol Symbol)[] OrderedSymbols = Symbols
|
private static readonly (char[] Pattern, Symbol Symbol)[] OrderedSymbols = Symbols
|
||||||
|
|||||||
Reference in New Issue
Block a user