Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Organize AST definitions #1644

Merged
merged 16 commits into from
Feb 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 11 additions & 19 deletions DMCompiler/Bytecode/DreamProcOpcode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ public static class StringFormatEncoder {
/// (DM uses this because it uses UTF8 and 0xFF is just an invalid character in that encoding, no biggie)<br/>
/// See: "Halfwidth and Fullwidth Forms" on https://en.wikibooks.org/wiki/Unicode/Character_reference/F000-FFFF
/// </remarks>
public static UInt16 FormatPrefix = 0xFF00;
public static ushort FormatPrefix = 0xFF00;

/// <summary>
/// The lower byte of the aforementioned formatting marker thingies we stuff into our UTF16 strings.<br/>
Expand All @@ -164,14 +164,14 @@ public static class StringFormatEncoder {
/// <remarks>
/// <see langword="DO NOT CAST TO CHAR!"/> This requires FormatPrefix to be added to it in order to be a useful formatting character!!
/// </remarks>
public enum FormatSuffix : UInt16 {
public enum FormatSuffix : ushort {
//States that Interpolated values can have (the [] thingies)
StringifyWithArticle = 0x0, //[] and we include an appropriate article for the resulting value, if necessary
StringifyNoArticle = 0x1, //[] and we never include an article (because it's elsewhere)
ReferenceOfValue = 0x2, //\ref[]

//States that macros can have
//(these can have any arbitrary value as long as compiler/server/cilent all agree)
//(these can have any arbitrary value as long as compiler/server/client all agree)
//(Some of these values may not align with what they are internally in BYOND; too bad!!)
UpperDefiniteArticle, //The
LowerDefiniteArticle, //the
Expand Down Expand Up @@ -214,12 +214,12 @@ public enum FormatSuffix : UInt16 {

/// <returns>The UTF16 character we should be actually storing to articulate this format marker.</returns>
public static char Encode(FormatSuffix suffix) {
return (char)(FormatPrefix | ((UInt16)suffix));
return (char)(FormatPrefix | ((ushort)suffix));
}

/// <returns>true if the input character was actually a formatting codepoint. false if not.</returns>
public static bool Decode(char c, [NotNullWhen(true)] out FormatSuffix? suffix) {
UInt16 bytes = c; // this is an implicit reinterpret_cast, in C++ lingo
ushort bytes = c; // this is an implicit reinterpret_cast, in C++ lingo
suffix = null;
if((bytes & FormatPrefix) != FormatPrefix)
return false;
Expand All @@ -228,7 +228,7 @@ public static bool Decode(char c, [NotNullWhen(true)] out FormatSuffix? suffix)
}

public static bool Decode(char c) {
UInt16 bytes = c;
ushort bytes = c;
return (bytes & FormatPrefix) == FormatPrefix; // Could also check that the lower byte is a valid enum but... ehhhhh
}

Expand Down Expand Up @@ -386,23 +386,15 @@ public static string GetOpcodesHash() {
/// Custom attribute for declaring <see cref="OpcodeMetadata"/> metadata for individual opcodes
/// </summary>
[AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
internal sealed class OpcodeMetadataAttribute : Attribute {
public OpcodeMetadata Metadata;

public OpcodeMetadataAttribute(int stackDelta = 0) {
Metadata = new OpcodeMetadata(stackDelta);
}
internal sealed class OpcodeMetadataAttribute(int stackDelta = 0) : Attribute {
public OpcodeMetadata Metadata = new(stackDelta);
}

/// <summary>
/// Miscellaneous metadata associated with individual <see cref="DreamProcOpcode"/> opcodes using the <see cref="OpcodeMetadataAttribute"/> attribute
/// </summary>
public struct OpcodeMetadata {
public readonly int StackDelta; // Net change in stack size caused by this opcode

public OpcodeMetadata(int stackDelta = 0) {
StackDelta = stackDelta;
}
public struct OpcodeMetadata(int stackDelta = 0) {
public readonly int StackDelta = stackDelta; // Net change in stack size caused by this opcode
}

/// <summary>
Expand All @@ -415,7 +407,7 @@ static OpcodeMetadataCache() {
foreach (DreamProcOpcode opcode in Enum.GetValues(typeof(DreamProcOpcode))) {
var field = typeof(DreamProcOpcode).GetField(opcode.ToString());
var attribute = Attribute.GetCustomAttribute(field!, typeof(OpcodeMetadataAttribute));
var metadataAttribute = (OpcodeMetadataAttribute)attribute;
var metadataAttribute = (OpcodeMetadataAttribute?)attribute;
MetadataCache[(byte)opcode] = metadataAttribute?.Metadata ?? new OpcodeMetadata();
}
}
Expand Down
234 changes: 234 additions & 0 deletions DMCompiler/Compiler/DM/AST/DMAST.Expression.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
using System.Collections.Generic;
using System.Linq;
using DMCompiler.DM;

namespace DMCompiler.Compiler.DM.AST;

public abstract class DMASTExpression(Location location) : DMASTNode(location) {
public virtual IEnumerable<DMASTExpression> Leaves() {
yield break;
}

/// <summary>
/// If this is a <see cref="DMASTExpressionWrapped"/>, returns the expression inside.
/// Returns this expression if not.
/// </summary>
public virtual DMASTExpression GetUnwrapped() {
return this;
}
}

public sealed class DMASTVoid(Location location) : DMASTExpression(location);

public sealed class DMASTIdentifier(Location location, string identifier) : DMASTExpression(location) {
public readonly string Identifier = identifier;
}

public sealed class DMASTSwitchCaseRange(Location location, DMASTExpression rangeStart, DMASTExpression rangeEnd)
: DMASTExpression(location) {
public DMASTExpression RangeStart = rangeStart, RangeEnd = rangeEnd;
}

public sealed class DMASTStringFormat(Location location, string value, DMASTExpression?[] interpolatedValues)
: DMASTExpression(location) {
public readonly string Value = value;
public readonly DMASTExpression?[] InterpolatedValues = interpolatedValues;
}

public sealed class DMASTList(Location location, DMASTCallParameter[] values) : DMASTExpression(location) {
public readonly DMASTCallParameter[] Values = values;

public bool AllValuesConstant() {
return Values.All(
value => (value is {
Key: DMASTExpressionConstant,
Value: DMASTExpressionConstant
})
||
(value is {
Key: DMASTExpressionConstant,
Value: DMASTList valueList
} && valueList.AllValuesConstant())
);
}
}

/// <summary>
/// Represents the value of a var defined as <code>var/list/L[1][2][3]</code>
/// </summary>
public sealed class DMASTDimensionalList(Location location, List<DMASTExpression> sizes)
: DMASTExpression(location) {
public readonly List<DMASTExpression> Sizes = sizes;
}

public sealed class DMASTAddText(Location location, DMASTCallParameter[] parameters) : DMASTExpression(location) {
public readonly DMASTCallParameter[] Parameters = parameters;
}

public sealed class DMASTNewList(Location location, DMASTCallParameter[] parameters) : DMASTExpression(location) {
public readonly DMASTCallParameter[] Parameters = parameters;
}

public sealed class DMASTInput(
Location location,
DMASTCallParameter[] parameters,
DMValueType? types,
DMASTExpression? list) : DMASTExpression(location) {
public readonly DMASTCallParameter[] Parameters = parameters;
public DMValueType? Types = types;
public readonly DMASTExpression? List = list;
}

public sealed class DMASTLocateCoordinates(
Location location,
DMASTExpression x,
DMASTExpression y,
DMASTExpression z) : DMASTExpression(location) {
public readonly DMASTExpression X = x, Y = y, Z = z;
}

public sealed class DMASTLocate(Location location, DMASTExpression? expression, DMASTExpression? container)
: DMASTExpression(location) {
public readonly DMASTExpression? Expression = expression;
public readonly DMASTExpression? Container = container;
}

public sealed class DMASTGradient(Location location, DMASTCallParameter[] parameters) : DMASTExpression(location) {
public readonly DMASTCallParameter[] Parameters = parameters;
}

public sealed class DMASTPick(Location location, DMASTPick.PickValue[] values) : DMASTExpression(location) {
public struct PickValue(DMASTExpression? weight, DMASTExpression value) {
public readonly DMASTExpression? Weight = weight;
public readonly DMASTExpression Value = value;
}

public readonly PickValue[] Values = values;
}

public class DMASTLog(Location location, DMASTExpression expression, DMASTExpression? baseExpression)
: DMASTExpression(location) {
public readonly DMASTExpression Expression = expression;
public readonly DMASTExpression? BaseExpression = baseExpression;
}

public sealed class DMASTCall(
Location location,
DMASTCallParameter[] callParameters,
DMASTCallParameter[] procParameters) : DMASTExpression(location) {
public readonly DMASTCallParameter[] CallParameters = callParameters, ProcParameters = procParameters;
}

public class DMASTVarDeclExpression(Location location, DMASTPath path) : DMASTExpression(location) {
public readonly DMASTPath DeclPath = path;
}

public sealed class DMASTNewPath(Location location, DMASTConstantPath path, DMASTCallParameter[]? parameters)
: DMASTExpression(location) {
public readonly DMASTConstantPath Path = path;
public readonly DMASTCallParameter[]? Parameters = parameters;
}

public sealed class DMASTNewExpr(Location location, DMASTExpression expression, DMASTCallParameter[]? parameters)
: DMASTExpression(location) {
public readonly DMASTExpression Expression = expression;
public readonly DMASTCallParameter[]? Parameters = parameters;
}

public sealed class DMASTNewInferred(Location location, DMASTCallParameter[] parameters)
: DMASTExpression(location) {
public readonly DMASTCallParameter[] Parameters = parameters;
}

public sealed class DMASTTernary(Location location, DMASTExpression a, DMASTExpression b, DMASTExpression c)
: DMASTExpression(location) {
public readonly DMASTExpression A = a, B = b, C = c;

public override IEnumerable<DMASTExpression> Leaves() {
yield return A;
yield return B;
yield return C;
}
}

public sealed class DMASTExpressionInRange(
Location location,
DMASTExpression value,
DMASTExpression startRange,
DMASTExpression endRange,
DMASTExpression? step = null) : DMASTExpression(location) {
public DMASTExpression Value = value;
public DMASTExpression StartRange = startRange;
public DMASTExpression EndRange = endRange;
public readonly DMASTExpression? Step = step;

public override IEnumerable<DMASTExpression> Leaves() {
yield return Value;
yield return StartRange;
yield return EndRange;
}
}

public sealed class DMASTProcCall(Location location, IDMASTCallable callable, DMASTCallParameter[] parameters)
: DMASTExpression(location) {
public readonly IDMASTCallable Callable = callable;
public readonly DMASTCallParameter[] Parameters = parameters;
}

public sealed class DMASTDereference(
Location location,
DMASTExpression expression,
DMASTDereference.Operation[] operations) : DMASTExpression(location) {
public abstract class Operation {
/// <summary>
/// The location of the operation.
/// </summary>
public required Location Location;
/// <summary>
/// Whether we should short circuit if the expression we are accessing is null.
/// </summary>
public required bool Safe; // x?.y, x?.y() etc
}

public abstract class NamedOperation : Operation {
/// <summary>
/// Name of the identifier.
/// </summary>
public required string Identifier;
/// <summary>
/// Whether we should check if the variable exists or not.
/// </summary>
public required bool NoSearch; // x:y, x:y()
}

public sealed class FieldOperation : NamedOperation;

public sealed class IndexOperation : Operation {
/// <summary>
/// The index expression that we use to index this expression (constant or otherwise).
/// </summary>
public required DMASTExpression Index; // x[y], x?[y]
}

public sealed class CallOperation : NamedOperation {
/// <summary>
/// The parameters that we call this proc with.
/// </summary>
public required DMASTCallParameter[] Parameters; // x.y(),
}

public readonly DMASTExpression Expression = expression;

// Always contains at least one operation
public readonly Operation[] Operations = operations;
}

public interface IDMASTCallable;

public sealed class DMASTCallableProcIdentifier(Location location, string identifier) : DMASTExpression(location), IDMASTCallable {
public readonly string Identifier = identifier;
}

public sealed class DMASTCallableSuper(Location location) : DMASTExpression(location), IDMASTCallable;

public sealed class DMASTCallableSelf(Location location) : DMASTExpression(location), IDMASTCallable;
56 changes: 56 additions & 0 deletions DMCompiler/Compiler/DM/AST/DMAST.ExpressionBinary.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
using System.Collections.Generic;

namespace DMCompiler.Compiler.DM.AST;

public class DMASTBinary(Location location, DMASTExpression lhs, DMASTExpression rhs) : DMASTExpression(location) {
public DMASTExpression LHS = lhs;
public DMASTExpression RHS = rhs;

public override IEnumerable<DMASTExpression> Leaves() {
yield return LHS;
yield return RHS;
}
}

public sealed class DMASTAssign(Location location, DMASTExpression expression, DMASTExpression value) : DMASTBinary(location, expression, value);
public sealed class DMASTAssignInto(Location location, DMASTExpression expression, DMASTExpression value) : DMASTBinary(location, expression, value);
public sealed class DMASTAppend(Location location, DMASTExpression a, DMASTExpression b) : DMASTBinary(location, a, b);
public sealed class DMASTRemove(Location location, DMASTExpression a, DMASTExpression b) : DMASTBinary(location, a, b);
public sealed class DMASTCombine(Location location, DMASTExpression a, DMASTExpression b) : DMASTBinary(location, a, b);
public sealed class DMASTMask(Location location, DMASTExpression a, DMASTExpression b) : DMASTBinary(location, a, b);
public sealed class DMASTLogicalAndAssign(Location location, DMASTExpression a, DMASTExpression b) : DMASTBinary(location, a, b);
public sealed class DMASTLogicalOrAssign(Location location, DMASTExpression a, DMASTExpression b) : DMASTBinary(location, a, b);
public sealed class DMASTMultiplyAssign(Location location, DMASTExpression a, DMASTExpression b) : DMASTBinary(location, a, b);
public sealed class DMASTDivideAssign(Location location, DMASTExpression a, DMASTExpression b) : DMASTBinary(location, a, b);
public sealed class DMASTLeftShiftAssign(Location location, DMASTExpression a, DMASTExpression b) : DMASTBinary(location, a, b);
public sealed class DMASTRightShiftAssign(Location location, DMASTExpression a, DMASTExpression b) : DMASTBinary(location, a, b);
public sealed class DMASTXorAssign(Location location, DMASTExpression a, DMASTExpression b) : DMASTBinary(location, a, b);
public sealed class DMASTModulusAssign(Location location, DMASTExpression a, DMASTExpression b) : DMASTBinary(location, a, b);
public sealed class DMASTModulusModulusAssign(Location location, DMASTExpression a, DMASTExpression b) : DMASTBinary(location, a, b);
public sealed class DMASTOr(Location location, DMASTExpression a, DMASTExpression b) : DMASTBinary(location, a, b);
public sealed class DMASTAnd(Location location, DMASTExpression a, DMASTExpression b) : DMASTBinary(location, a, b);
public sealed class DMASTBinaryAnd(Location location, DMASTExpression a, DMASTExpression b) : DMASTBinary(location, a, b);
public sealed class DMASTBinaryXor(Location location, DMASTExpression a, DMASTExpression b) : DMASTBinary(location, a, b);
public sealed class DMASTBinaryOr(Location location, DMASTExpression a, DMASTExpression b) : DMASTBinary(location, a, b);
public sealed class DMASTLeftShift(Location location, DMASTExpression a, DMASTExpression b) : DMASTBinary(location, a, b);
public sealed class DMASTRightShift(Location location, DMASTExpression a, DMASTExpression b) : DMASTBinary(location, a, b);
public sealed class DMASTEqual(Location location, DMASTExpression a, DMASTExpression b) : DMASTBinary(location, a, b);
public sealed class DMASTNotEqual(Location location, DMASTExpression a, DMASTExpression b) : DMASTBinary(location, a, b);
public sealed class DMASTEquivalent(Location location, DMASTExpression a, DMASTExpression b) : DMASTBinary(location, a, b);
public sealed class DMASTNotEquivalent(Location location, DMASTExpression a, DMASTExpression b) : DMASTBinary(location, a, b);
public sealed class DMASTLessThan(Location location, DMASTExpression a, DMASTExpression b) : DMASTBinary(location, a, b);
public sealed class DMASTLessThanOrEqual(Location location, DMASTExpression a, DMASTExpression b) : DMASTBinary(location, a, b);
public sealed class DMASTGreaterThan(Location location, DMASTExpression a, DMASTExpression b) : DMASTBinary(location, a, b);
public sealed class DMASTGreaterThanOrEqual(Location location, DMASTExpression a, DMASTExpression b) : DMASTBinary(location, a, b);
public sealed class DMASTMultiply(Location location, DMASTExpression a, DMASTExpression b) : DMASTBinary(location, a, b);
public sealed class DMASTDivide(Location location, DMASTExpression a, DMASTExpression b) : DMASTBinary(location, a, b);
public sealed class DMASTModulus(Location location, DMASTExpression a, DMASTExpression b) : DMASTBinary(location, a, b);
public sealed class DMASTModulusModulus(Location location, DMASTExpression a, DMASTExpression b) : DMASTBinary(location, a, b);
public sealed class DMASTPower(Location location, DMASTExpression a, DMASTExpression b) : DMASTBinary(location, a, b);
public sealed class DMASTAdd(Location location, DMASTExpression a, DMASTExpression b) : DMASTBinary(location, a, b);
public sealed class DMASTSubtract(Location location, DMASTExpression a, DMASTExpression b) : DMASTBinary(location, a, b);
public sealed class DMASTArctan2(Location location, DMASTExpression xExpression, DMASTExpression yExpression) : DMASTBinary(location, xExpression, yExpression);
public sealed class DMASTIsType(Location location, DMASTExpression value, DMASTExpression type) : DMASTBinary(location, value, type);
public sealed class DMASTGetStep(Location location, DMASTExpression refValue, DMASTExpression dir) : DMASTBinary(location, refValue, dir);
public sealed class DMASTGetDir(Location location, DMASTExpression loc1, DMASTExpression loc2) : DMASTBinary(location, loc1, loc2);
public sealed class DMASTExpressionIn(Location location, DMASTExpression value, DMASTExpression list) : DMASTBinary(location, value, list);
Loading
Loading