Files
plainleaf/client/space_lua/ast.ts
T
2026-03-11 11:35:19 +01:00

363 lines
7.6 KiB
TypeScript

type ASTContext = {
ctx: ASTCtx;
};
export type NumericType = "int" | "float";
export type ASTCtx = {
from?: number;
to?: number;
} & Record<string, any>;
export type LuaBlock = {
type: "Block";
statements: LuaStatement[];
hasLabel?: boolean;
hasGoto?: boolean;
// the first duplicated label is recorded here for later eval
dupLabelError?: { name: string; ctx: ASTCtx };
// this block declares top-level locals and therefore needs a new env
needsEnv?: boolean;
// true if this block itself (not nested ones) defines at least one label
hasLabelHere?: boolean;
// true if this block itself (not nested ones) may create to-be-closed values
hasCloseHere?: boolean;
// true if this block's subtree contains any function definition
hasFunctionDef?: boolean;
} & ASTContext;
// STATEMENTS
export type LuaReturnStatement = {
type: "Return";
expressions: LuaExpression[];
} & ASTContext;
export type LuaStatement =
| LuaSemicolonStatement
| LuaLabelStatement
| LuaBreakStatement
| LuaGotoStatement
| LuaReturnStatement
| LuaBlock
| LuaWhileStatement
| LuaRepeatStatement
| LuaIfStatement
| LuaForStatement
| LuaForInStatement
| LuaFunctionStatement
| LuaLocalFunctionStatement
| LuaAssignmentStatement
| LuaLocalStatement
| LuaFunctionCallStatement;
export type LuaSemicolonStatement = {
type: "Semicolon";
} & ASTContext;
export type LuaLabelStatement = {
type: "Label";
name: string;
} & ASTContext;
export type LuaBreakStatement = {
type: "Break";
} & ASTContext;
export type LuaGotoStatement = {
type: "Goto";
name: string;
} & ASTContext;
export type LuaWhileStatement = {
type: "While";
condition: LuaExpression;
block: LuaBlock;
} & ASTContext;
export type LuaRepeatStatement = {
type: "Repeat";
block: LuaBlock;
condition: LuaExpression;
} & ASTContext;
export type LuaIfStatement = {
type: "If";
conditions: { condition: LuaExpression; block: LuaBlock }[];
elseBlock?: LuaBlock;
} & ASTContext;
export type LuaForStatement = {
type: "For";
name: string;
start: LuaExpression;
end: LuaExpression;
step?: LuaExpression;
block: LuaBlock;
// function definition in the block captures the loop variable
capturesLoopVar?: boolean;
} & ASTContext;
export type LuaForInStatement = {
type: "ForIn";
names: string[];
expressions: LuaExpression[];
block: LuaBlock;
// function definition in the block captures any loop variable
capturesLoopVar?: boolean;
} & ASTContext;
export type LuaFunctionStatement = {
type: "Function";
name: LuaFunctionName;
body: LuaFunctionBody;
} & ASTContext;
export type LuaLocalFunctionStatement = {
type: "LocalFunction";
name: string;
body: LuaFunctionBody;
} & ASTContext;
export type LuaFunctionName = {
type: "FunctionName";
propNames: string[];
colonName?: string;
} & ASTContext;
export type LuaFunctionBody = {
type: "FunctionBody";
parameters: string[];
block: LuaBlock;
} & ASTContext;
export type LuaAssignmentStatement = {
type: "Assignment";
variables: LuaLValue[];
expressions: LuaExpression[];
} & ASTContext;
export type LuaLValue =
| LuaVariable
| LuaPropertyAccessExpression
| LuaTableAccessExpression;
export type LuaLocalStatement = {
type: "Local";
names: LuaAttName[];
expressions?: LuaExpression[];
} & ASTContext;
export enum LuaAttribute {
Const = "const",
Close = "close",
}
export type LuaAttName = {
type: "AttName";
name: string;
attribute?: string;
attributes?: LuaAttribute[];
} & ASTContext;
export type LuaFunctionCallStatement = {
type: "FunctionCallStatement";
call: LuaFunctionCallExpression;
} & ASTContext;
// EXPRESSIONS
export type LuaExpression =
| LuaNilLiteral
| LuaBooleanLiteral
| LuaNumberLiteral
| LuaStringLiteral
| LuaPrefixExpression
| LuaBinaryExpression
| LuaUnaryExpression
| LuaTableConstructor
| LuaFunctionDefinition
| LuaQueryExpression
| LuaFilteredCallExpression
| LuaAggregateCallExpression;
export type LuaNilLiteral = {
type: "Nil";
} & ASTContext;
export type LuaBooleanLiteral = {
type: "Boolean";
value: boolean;
} & ASTContext;
export type LuaNumberLiteral = {
type: "Number";
value: number;
numericType: NumericType;
} & ASTContext;
export type LuaStringLiteral = {
type: "String";
value: string;
} & ASTContext;
export type LuaPrefixExpression =
| LuaVariableExpression
| LuaParenthesizedExpression
| LuaFunctionCallExpression;
export type LuaParenthesizedExpression = {
type: "Parenthesized";
expression: LuaExpression;
} & ASTContext;
export type LuaVariableExpression =
| LuaVariable
| LuaPropertyAccessExpression
| LuaTableAccessExpression;
export type LuaVariable = {
type: "Variable";
name: string;
} & ASTContext;
export type LuaPropertyAccessExpression = {
type: "PropertyAccess";
object: LuaPrefixExpression;
property: string;
} & ASTContext;
export type LuaTableAccessExpression = {
type: "TableAccess";
object: LuaPrefixExpression;
key: LuaExpression;
} & ASTContext;
export type LuaFunctionCallExpression = {
type: "FunctionCall";
prefix: LuaPrefixExpression;
name?: string;
args: LuaExpression[];
orderBy?: LuaOrderBy[];
} & ASTContext;
export type LuaBinaryExpression = {
type: "Binary";
operator: string;
left: LuaExpression;
right: LuaExpression;
} & ASTContext;
export type LuaUnaryExpression = {
type: "Unary";
operator: string;
argument: LuaExpression;
} & ASTContext;
export type LuaTableConstructor = {
type: "TableConstructor";
fields: LuaTableField[];
} & ASTContext;
export type LuaTableField = LuaDynamicField | LuaPropField | LuaExpressionField;
export type LuaDynamicField = {
type: "DynamicField";
key: LuaExpression;
value: LuaExpression;
} & ASTContext;
export type LuaPropField = {
type: "PropField";
key: string;
value: LuaExpression;
} & ASTContext;
export type LuaExpressionField = {
type: "ExpressionField";
value: LuaExpression;
} & ASTContext;
export type LuaFunctionDefinition = {
type: "FunctionDefinition";
body: LuaFunctionBody;
} & ASTContext;
// Aggregate with per-row filter
export type LuaFilteredCallExpression = {
type: "FilteredCall";
call: LuaFunctionCallExpression;
filter: LuaExpression;
} & ASTContext;
// Aggregate call with intra-aggregate order by
export type LuaAggregateCallExpression = {
type: "AggregateCall";
call: LuaFunctionCallExpression;
orderBy: LuaOrderBy[];
} & ASTContext;
// Query stuff
export type LuaQueryExpression = {
type: "Query";
clauses: LuaQueryClause[];
} & ASTContext;
export type LuaQueryClause =
| LuaFromClause
| LuaWhereClause
| LuaLimitClause
| LuaOffsetClause
| LuaOrderByClause
| LuaSelectClause
| LuaGroupByClause
| LuaHavingClause;
export type LuaFromClause = {
type: "From";
name?: string;
expression: LuaExpression;
} & ASTContext;
export type LuaWhereClause = {
type: "Where";
expression: LuaExpression;
} & ASTContext;
export type LuaLimitClause = {
type: "Limit";
limit: LuaExpression;
offset?: LuaExpression;
} & ASTContext;
export type LuaOffsetClause = {
type: "Offset";
offset: LuaExpression;
} & ASTContext;
export type LuaOrderByClause = {
type: "OrderBy";
orderBy: LuaOrderBy[];
} & ASTContext;
export type LuaOrderBy = {
type: "Order";
expression: LuaExpression;
direction: "asc" | "desc";
nulls?: "first" | "last";
using?: string | LuaFunctionBody;
} & ASTContext;
export type LuaSelectClause = {
type: "Select";
expression: LuaExpression;
} & ASTContext;
export type LuaGroupByClause = {
type: "GroupBy";
expressions: LuaExpression[];
} & ASTContext;
export type LuaHavingClause = {
type: "Having";
expression: LuaExpression;
} & ASTContext;