using NubLang.Syntax; namespace NubLang.Ast; public abstract class Node(List tokens) { public List Tokens { get; } = tokens; public abstract IEnumerable Children(); public IEnumerable Descendants() { foreach (var child in Children()) { foreach (var descendant in child.DescendantsAndSelf()) { yield return descendant; } } } public IEnumerable DescendantsAndSelf() { yield return this; foreach (var descendant in Descendants()) { yield return descendant; } } } public abstract class TopLevelNode(List tokens) : Node(tokens); public class ImportNode(List tokens, IdentifierToken nameToken) : TopLevelNode(tokens) { public IdentifierToken NameToken { get; } = nameToken; public override IEnumerable Children() { return []; } } public class ModuleNode(List tokens, IdentifierToken nameToken) : TopLevelNode(tokens) { public IdentifierToken NameToken { get; } = nameToken; public override IEnumerable Children() { return []; } } #region Definitions public abstract class DefinitionNode(List tokens, IdentifierToken nameToken) : TopLevelNode(tokens) { public IdentifierToken NameToken { get; } = nameToken; } public class FuncParameterNode(List tokens, IdentifierToken nameToken, NubType type) : Node(tokens) { public IdentifierToken NameToken { get; } = nameToken; public NubType Type { get; } = type; public override IEnumerable Children() { return []; } } public class FuncPrototypeNode(List tokens, IdentifierToken nameToken, StringLiteralToken? externSymbolToken, List parameters, NubType returnType) : Node(tokens) { public IdentifierToken NameToken { get; } = nameToken; public StringLiteralToken? ExternSymbolToken { get; } = externSymbolToken; public List Parameters { get; } = parameters; public NubType ReturnType { get; } = returnType; public override IEnumerable Children() { return Parameters; } } public class FuncNode(List tokens, FuncPrototypeNode prototype, BlockNode? body) : DefinitionNode(tokens, prototype.NameToken) { public FuncPrototypeNode Prototype { get; } = prototype; public BlockNode? Body { get; } = body; public override IEnumerable Children() { yield return Prototype; if (Body != null) { yield return Body; } } } public class StructFieldNode(List tokens, IdentifierToken nameToken, NubType type, ExpressionNode? value) : Node(tokens) { public IdentifierToken NameToken { get; } = nameToken; public NubType Type { get; } = type; public ExpressionNode? Value { get; } = value; public override IEnumerable Children() { if (Value != null) { yield return Value; } } } public class StructNode(List tokens, IdentifierToken name, NubStructType structType, bool packed, List fields) : DefinitionNode(tokens, name) { public NubStructType StructType { get; } = structType; public bool Packed { get; } = packed; public List Fields { get; } = fields; public override IEnumerable Children() { foreach (var field in Fields) { yield return field; } } } #endregion #region Statements public abstract class StatementNode(List tokens) : Node(tokens); public class BlockNode(List tokens, List statements) : StatementNode(tokens) { public List Statements { get; } = statements; public override IEnumerable Children() { return Statements; } } public class StatementFuncCallNode(List tokens, FuncCallNode funcCall) : StatementNode(tokens) { public FuncCallNode FuncCall { get; } = funcCall; public override IEnumerable Children() { yield return FuncCall; } } public class ReturnNode(List tokens, ExpressionNode? value) : StatementNode(tokens) { public ExpressionNode? Value { get; } = value; public override IEnumerable Children() { if (Value != null) yield return Value; } } public class AssignmentNode(List tokens, ExpressionNode target, ExpressionNode value) : StatementNode(tokens) { public ExpressionNode Target { get; } = target; public ExpressionNode Value { get; } = value; public override IEnumerable Children() { yield return Target; yield return Value; } } public class IfNode(List tokens, ExpressionNode condition, BlockNode body, Variant? @else) : StatementNode(tokens) { public ExpressionNode Condition { get; } = condition; public BlockNode Body { get; } = body; public Variant? Else { get; } = @else; public override IEnumerable Children() { yield return Condition; yield return Body; if (Else.HasValue) { yield return Else.Value.Match(x => x, x => x); } } } public class VariableDeclarationNode(List tokens, IdentifierToken nameToken, ExpressionNode? assignment, NubType type) : StatementNode(tokens) { public IdentifierToken NameToken { get; } = nameToken; public ExpressionNode? Assignment { get; } = assignment; public NubType Type { get; } = type; public override IEnumerable Children() { if (Assignment != null) yield return Assignment; } } public class ContinueNode(List tokens) : StatementNode(tokens) { public override IEnumerable Children() { return []; } } public class BreakNode(List tokens) : StatementNode(tokens) { public override IEnumerable Children() { return []; } } public class WhileNode(List tokens, ExpressionNode condition, BlockNode body) : StatementNode(tokens) { public ExpressionNode Condition { get; } = condition; public BlockNode Body { get; } = body; public override IEnumerable Children() { yield return Condition; yield return Body; } } public class ForSliceNode(List tokens, IdentifierToken elementNameToken, IdentifierToken? indexNameToken, ExpressionNode target, BlockNode body) : StatementNode(tokens) { public IdentifierToken ElementNameToken { get; } = elementNameToken; public IdentifierToken? IndexNameToken { get; } = indexNameToken; public ExpressionNode Target { get; } = target; public BlockNode Body { get; } = body; public override IEnumerable Children() { yield return Target; yield return Body; } } public class ForConstArrayNode(List tokens, IdentifierToken elementNameToken, IdentifierToken? indexNameToken, ExpressionNode target, BlockNode body) : StatementNode(tokens) { public IdentifierToken ElementNameToken { get; } = elementNameToken; public IdentifierToken? IndexNameToken { get; } = indexNameToken; public ExpressionNode Target { get; } = target; public BlockNode Body { get; } = body; public override IEnumerable Children() { yield return Target; yield return Body; } } public class DeferNode(List tokens, StatementNode statement) : StatementNode(tokens) { public StatementNode Statement { get; } = statement; public override IEnumerable Children() { yield return Statement; } } #endregion #region Expressions public enum UnaryOperator { Negate, Invert } public enum BinaryOperator { Equal, NotEqual, GreaterThan, GreaterThanOrEqual, LessThan, LessThanOrEqual, LogicalAnd, LogicalOr, Plus, Minus, Multiply, Divide, Modulo, LeftShift, RightShift, BitwiseAnd, BitwiseXor, BitwiseOr } public abstract class ExpressionNode(List tokens, NubType type) : Node(tokens) { public NubType Type { get; } = type; } public class StringLiteralNode(List tokens, string value) : ExpressionNode(tokens, new NubStringType()) { public string Value { get; } = value; public override IEnumerable Children() { return []; } } public class CStringLiteralNode(List tokens, string value) : ExpressionNode(tokens, new NubPointerType(new NubIntType(true, 8))) { public string Value { get; } = value; public override IEnumerable Children() { return []; } } public class I8LiteralNode(List tokens, sbyte value) : ExpressionNode(tokens, new NubIntType(true, 8)) { public sbyte Value { get; } = value; public override IEnumerable Children() { return []; } } public class I16LiteralNode(List tokens, short value) : ExpressionNode(tokens, new NubIntType(true, 16)) { public short Value { get; } = value; public override IEnumerable Children() { return []; } } public class I32LiteralNode(List tokens, int value) : ExpressionNode(tokens, new NubIntType(true, 32)) { public int Value { get; } = value; public override IEnumerable Children() { return []; } } public class I64LiteralNode(List tokens, long value) : ExpressionNode(tokens, new NubIntType(true, 64)) { public long Value { get; } = value; public override IEnumerable Children() { return []; } } public class U8LiteralNode(List tokens, byte value) : ExpressionNode(tokens, new NubIntType(false, 8)) { public byte Value { get; } = value; public override IEnumerable Children() { return []; } } public class U16LiteralNode(List tokens, ushort value) : ExpressionNode(tokens, new NubIntType(false, 16)) { public ushort Value { get; } = value; public override IEnumerable Children() { return []; } } public class U32LiteralNode(List tokens, uint value) : ExpressionNode(tokens, new NubIntType(false, 32)) { public uint Value { get; } = value; public override IEnumerable Children() { return []; } } public class U64LiteralNode(List tokens, ulong value) : ExpressionNode(tokens, new NubIntType(false, 64)) { public ulong Value { get; } = value; public override IEnumerable Children() { return []; } } public class Float32LiteralNode(List tokens, float value) : ExpressionNode(tokens, new NubFloatType(32)) { public float Value { get; } = value; public override IEnumerable Children() { return []; } } public class Float64LiteralNode(List tokens, double value) : ExpressionNode(tokens, new NubFloatType(64)) { public double Value { get; } = value; public override IEnumerable Children() { return []; } } public class BoolLiteralNode(List tokens, bool value) : ExpressionNode(tokens, new NubBoolType()) { public bool Value { get; } = value; public override IEnumerable Children() { return []; } } public class BinaryExpressionNode(List tokens, NubType type, ExpressionNode left, BinaryOperator @operator, ExpressionNode right) : ExpressionNode(tokens, type) { public ExpressionNode Left { get; } = left; public BinaryOperator Operator { get; } = @operator; public ExpressionNode Right { get; } = right; public override IEnumerable Children() { yield return Left; yield return Right; } } public class UnaryExpressionNode(List tokens, NubType type, UnaryOperator @operator, ExpressionNode operand) : ExpressionNode(tokens, type) { public UnaryOperator Operator { get; } = @operator; public ExpressionNode Operand { get; } = operand; public override IEnumerable Children() { yield return Operand; } } public class FuncCallNode(List tokens, NubType type, ExpressionNode expression, List parameters) : ExpressionNode(tokens, type) { public ExpressionNode Expression { get; } = expression; public List Parameters { get; } = parameters; public override IEnumerable Children() { yield return Expression; foreach (var expressionNode in Parameters) { yield return expressionNode; } } } public class VariableIdentifierNode(List tokens, NubType type, IdentifierToken nameToken) : ExpressionNode(tokens, type) { public IdentifierToken NameToken { get; } = nameToken; public override IEnumerable Children() { return []; } } public class FuncIdentifierNode(List tokens, NubType type, IdentifierToken moduleToken, IdentifierToken nameToken, StringLiteralToken? externSymbolToken) : ExpressionNode(tokens, type) { public IdentifierToken ModuleToken { get; } = moduleToken; public IdentifierToken NameToken { get; } = nameToken; public StringLiteralToken? ExternSymbolToken { get; } = externSymbolToken; public override IEnumerable Children() { return []; } } public class ArrayInitializerNode(List tokens, NubType type, List values) : ExpressionNode(tokens, type) { public List Values { get; } = values; public override IEnumerable Children() { return Values; } } public class ConstArrayInitializerNode(List tokens, NubType type, List values) : ExpressionNode(tokens, type) { public List Values { get; } = values; public override IEnumerable Children() { return Values; } } public class ArrayIndexAccessNode(List tokens, NubType type, ExpressionNode target, ExpressionNode index) : ExpressionNode(tokens, type) { public ExpressionNode Target { get; } = target; public ExpressionNode Index { get; } = index; public override IEnumerable Children() { yield return Target; yield return Index; } } public class ConstArrayIndexAccessNode(List tokens, NubType type, ExpressionNode target, ExpressionNode index) : ExpressionNode(tokens, type) { public ExpressionNode Target { get; } = target; public ExpressionNode Index { get; } = index; public override IEnumerable Children() { yield return Target; yield return Index; } } public class SliceIndexAccessNode(List tokens, NubType type, ExpressionNode target, ExpressionNode index) : ExpressionNode(tokens, type) { public ExpressionNode Target { get; } = target; public ExpressionNode Index { get; } = index; public override IEnumerable Children() { yield return Target; yield return Index; } } public class AddressOfNode(List tokens, NubType type, ExpressionNode target) : ExpressionNode(tokens, type) { public ExpressionNode Target { get; } = target; public override IEnumerable Children() { yield return Target; } } public class StructFieldAccessNode(List tokens, NubType type, ExpressionNode target, IdentifierToken fieldToken) : ExpressionNode(tokens, type) { public ExpressionNode Target { get; } = target; public IdentifierToken FieldToken { get; } = fieldToken; public override IEnumerable Children() { yield return Target; } } public class StructInitializerNode(List tokens, NubType type, Dictionary initializers) : ExpressionNode(tokens, type) { public Dictionary Initializers { get; } = initializers; public override IEnumerable Children() { foreach (var initializer in Initializers) { yield return initializer.Value; } } } public class DereferenceNode(List tokens, NubType type, ExpressionNode target) : ExpressionNode(tokens, type) { public ExpressionNode Target { get; } = target; public override IEnumerable Children() { yield return Target; } } public class SizeNode(List tokens, NubType TargetType) : ExpressionNode(tokens, new NubIntType(false, 64)) { public NubType TargetType { get; } = TargetType; public override IEnumerable Children() { return []; } } public class CastNode(List tokens, NubType type, ExpressionNode value) : ExpressionNode(tokens, type) { public ExpressionNode Value { get; } = value; public override IEnumerable Children() { yield return Value; } } public abstract class IntermediateExpression(List tokens) : ExpressionNode(tokens, new NubVoidType()); public class EnumReferenceIntermediateNode(List tokens, IdentifierToken moduleToken, IdentifierToken nameToken) : IntermediateExpression(tokens) { public IdentifierToken ModuleToken { get; } = moduleToken; public IdentifierToken NameToken { get; } = nameToken; public override IEnumerable Children() { return []; } } #endregion