use super::*;
use crate::allocator::AstArena;
use crate::location::Position;
use std::fmt;
use std::marker::PhantomData;
use std::ptr::NonNull;
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ExpressionTag {
Boolean,
Call,
FunctionLiteral,
Grouped,
Integer,
Nil,
Number,
String,
InterpString,
Table,
If,
Varargs,
IndexExpr,
IndexName,
TypeAssertion,
Instantiate,
Unary,
Local,
Global,
Binary,
Error,
}
#[repr(C)]
#[derive(Debug, PartialEq)]
pub struct ExpressionHeader<'ast> {
pub tag: ExpressionTag,
pub location: Location,
_marker: PhantomData<&'ast ()>,
}
#[derive(Clone, Copy)]
pub struct Expression<'ast> {
ptr: NonNull<ExpressionHeader<'ast>>,
_marker: PhantomData<&'ast ExpressionHeader<'ast>>,
}
impl fmt::Debug for Expression<'_> {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter
.debug_struct("Expression")
.field("location", &self.location())
.field("kind", &self.kind())
.finish()
}
}
impl PartialEq for Expression<'_> {
fn eq(&self, other: &Self) -> bool {
self.location() == other.location() && self.kind() == other.kind()
}
}
impl<'ast> std::ops::Deref for Expression<'ast> {
type Target = ExpressionHeader<'ast>;
fn deref(&self) -> &Self::Target {
self.header()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ConstantNumberParseResult {
Ok,
Imprecise,
Malformed,
BinOverflow,
HexOverflow,
IntOverflow,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum StringQuoteStyle {
QuotedSimple,
QuotedSingle,
QuotedRaw,
Unquoted,
}
impl From<LexerQuoteStyle> for StringQuoteStyle {
fn from(_: LexerQuoteStyle) -> Self {
Self::QuotedSimple
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum ExpressionKind<'ast> {
Boolean(bool),
Call {
func: Expression<'ast>,
type_args: &'ast [TypeOrPack<'ast>],
args: &'ast [Expression<'ast>],
self_call: bool,
arg_location: Location,
},
FunctionLiteral(&'ast Function<'ast>),
Grouped(Expression<'ast>),
Integer {
value: i64,
parse_result: ConstantNumberParseResult,
},
Nil,
Number {
value: f64,
parse_result: ConstantNumberParseResult,
},
String {
value: AstString<'ast>,
quote_style: StringQuoteStyle,
},
InterpString {
strings: &'ast [AstString<'ast>],
expressions: &'ast [Expression<'ast>],
},
Table {
items: &'ast [TableItem<'ast>],
},
If {
condition: Expression<'ast>,
has_then: bool,
then_expression: Expression<'ast>,
has_else: bool,
else_expression: Expression<'ast>,
},
Varargs,
IndexExpr {
expr: Expression<'ast>,
index: Expression<'ast>,
},
IndexName {
expr: Expression<'ast>,
index: AstName<'ast>,
index_location: Location,
op_position: Position,
op: IndexNameOp,
},
TypeAssertion {
expr: Expression<'ast>,
annotation: Type<'ast>,
},
Instantiate {
expr: Expression<'ast>,
type_args: &'ast [TypeOrPack<'ast>],
},
Unary {
op: UnaryOp,
rhs: Expression<'ast>,
},
Local {
local: &'ast Local<'ast>,
upvalue: bool,
},
Global(AstName<'ast>),
Binary {
lhs: Expression<'ast>,
op: BinaryOp,
rhs: Expression<'ast>,
},
Error {
expressions: &'ast [Expression<'ast>],
message_index: usize,
},
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct ExpressionInit<'ast> {
pub location: Location,
pub kind: ExpressionKind<'ast>,
}
impl<'ast> ExpressionInit<'ast> {
pub fn new(location: Location, kind: ExpressionKind<'ast>) -> Self {
Self { location, kind }
}
pub fn location(&self) -> Location {
self.location
}
}
macro_rules! expr_node {
($name:ident { $($field:ident : $ty:ty),* $(,)? }, $tag:ident) => {
#[repr(C)]
#[derive(Debug, PartialEq)]
pub struct $name<'ast> {
pub base: ExpressionHeader<'ast>,
$(pub $field: $ty),*
}
impl<'ast> $name<'ast> {
pub fn new(location: Location, $($field: $ty),*) -> Self {
Self {
base: Expression::new_header(ExpressionTag::$tag, location),
$($field),*
}
}
}
};
}
#[repr(C)]
#[derive(Debug, PartialEq)]
pub struct ExpressionUnit<'ast> {
pub base: ExpressionHeader<'ast>,
}
impl<'ast> ExpressionUnit<'ast> {
pub fn new(tag: ExpressionTag, location: Location) -> Self {
Self {
base: Expression::new_header(tag, location),
}
}
}
expr_node!(ExpressionBoolean { value: bool }, Boolean);
expr_node!(
ExpressionCall {
func: Expression<'ast>,
type_args: &'ast [TypeOrPack<'ast>],
args: &'ast [Expression<'ast>],
self_call: bool,
arg_location: Location
},
Call
);
expr_node!(
ExpressionFunctionLiteral {
function: &'ast Function<'ast>
},
FunctionLiteral
);
expr_node!(ExpressionGrouped { expression: Expression<'ast> }, Grouped);
expr_node!(
ExpressionInteger {
value: i64,
parse_result: ConstantNumberParseResult
},
Integer
);
expr_node!(
ExpressionNumber {
value: f64,
parse_result: ConstantNumberParseResult
},
Number
);
expr_node!(
ExpressionString {
value: AstString<'ast>,
quote_style: StringQuoteStyle
},
String
);
expr_node!(
ExpressionInterpString {
strings: &'ast [AstString<'ast>],
expressions: &'ast [Expression<'ast>]
},
InterpString
);
expr_node!(ExpressionTable { items: &'ast [TableItem<'ast>] }, Table);
expr_node!(
ExpressionIf {
condition: Expression<'ast>,
has_then: bool,
then_expression: Expression<'ast>,
has_else: bool,
else_expression: Expression<'ast>
},
If
);
expr_node!(
ExpressionIndexExpr {
expr: Expression<'ast>,
index: Expression<'ast>
},
IndexExpr
);
expr_node!(
ExpressionIndexName {
expr: Expression<'ast>,
index: AstName<'ast>,
index_location: Location,
op_position: Position,
op: IndexNameOp
},
IndexName
);
expr_node!(
ExpressionTypeAssertion {
expr: Expression<'ast>,
annotation: Type<'ast>
},
TypeAssertion
);
expr_node!(
ExpressionInstantiate {
expr: Expression<'ast>,
type_args: &'ast [TypeOrPack<'ast>]
},
Instantiate
);
expr_node!(ExpressionUnary { op: UnaryOp, rhs: Expression<'ast> }, Unary);
expr_node!(
ExpressionLocal {
local: &'ast Local<'ast>,
upvalue: bool
},
Local
);
expr_node!(ExpressionGlobal { name: AstName<'ast> }, Global);
expr_node!(
ExpressionBinary {
lhs: Expression<'ast>,
op: BinaryOp,
rhs: Expression<'ast>
},
Binary
);
expr_node!(
ExpressionError {
expressions: &'ast [Expression<'ast>],
message_index: usize
},
Error
);
impl<'ast> Expression<'ast> {
pub const fn new_header(tag: ExpressionTag, location: Location) -> ExpressionHeader<'ast> {
ExpressionHeader {
tag,
location,
_marker: PhantomData,
}
}
pub(crate) fn from_node<T>(node: &'ast mut T) -> Self {
Self {
ptr: NonNull::from(node).cast(),
_marker: PhantomData,
}
}
pub fn as_ptr(self) -> *const () {
self.ptr.as_ptr().cast()
}
#[inline(always)]
fn header(&self) -> &ExpressionHeader<'ast> {
unsafe { self.ptr.as_ref() }
}
#[inline(always)]
pub fn location(self) -> Location {
self.header().location
}
#[inline(always)]
pub fn kind(&self) -> ExpressionKind<'ast> {
match self.tag {
ExpressionTag::Boolean => {
ExpressionKind::Boolean(self.cast_ref::<ExpressionBoolean>().value)
}
ExpressionTag::Call => {
let node = self.cast_ref::<ExpressionCall>();
ExpressionKind::Call {
func: node.func,
type_args: node.type_args,
args: node.args,
self_call: node.self_call,
arg_location: node.arg_location,
}
}
ExpressionTag::FunctionLiteral => ExpressionKind::FunctionLiteral(
self.cast_ref::<ExpressionFunctionLiteral>().function,
),
ExpressionTag::Grouped => {
ExpressionKind::Grouped(self.cast_ref::<ExpressionGrouped>().expression)
}
ExpressionTag::Integer => {
let node = self.cast_ref::<ExpressionInteger>();
ExpressionKind::Integer {
value: node.value,
parse_result: node.parse_result,
}
}
ExpressionTag::Nil => ExpressionKind::Nil,
ExpressionTag::Number => {
let node = self.cast_ref::<ExpressionNumber>();
ExpressionKind::Number {
value: node.value,
parse_result: node.parse_result,
}
}
ExpressionTag::String => {
let node = self.cast_ref::<ExpressionString>();
ExpressionKind::String {
value: node.value,
quote_style: node.quote_style,
}
}
ExpressionTag::InterpString => {
let node = self.cast_ref::<ExpressionInterpString>();
ExpressionKind::InterpString {
strings: node.strings,
expressions: node.expressions,
}
}
ExpressionTag::Table => ExpressionKind::Table {
items: self.cast_ref::<ExpressionTable>().items,
},
ExpressionTag::If => {
let node = self.cast_ref::<ExpressionIf>();
ExpressionKind::If {
condition: node.condition,
has_then: node.has_then,
then_expression: node.then_expression,
has_else: node.has_else,
else_expression: node.else_expression,
}
}
ExpressionTag::Varargs => ExpressionKind::Varargs,
ExpressionTag::IndexExpr => {
let node = self.cast_ref::<ExpressionIndexExpr>();
ExpressionKind::IndexExpr {
expr: node.expr,
index: node.index,
}
}
ExpressionTag::IndexName => {
let node = self.cast_ref::<ExpressionIndexName>();
ExpressionKind::IndexName {
expr: node.expr,
index: node.index,
index_location: node.index_location,
op_position: node.op_position,
op: node.op,
}
}
ExpressionTag::TypeAssertion => {
let node = self.cast_ref::<ExpressionTypeAssertion>();
ExpressionKind::TypeAssertion {
expr: node.expr,
annotation: node.annotation,
}
}
ExpressionTag::Instantiate => {
let node = self.cast_ref::<ExpressionInstantiate>();
ExpressionKind::Instantiate {
expr: node.expr,
type_args: node.type_args,
}
}
ExpressionTag::Unary => {
let node = self.cast_ref::<ExpressionUnary>();
ExpressionKind::Unary {
op: node.op,
rhs: node.rhs,
}
}
ExpressionTag::Local => {
let node = self.cast_ref::<ExpressionLocal>();
ExpressionKind::Local {
local: node.local,
upvalue: node.upvalue,
}
}
ExpressionTag::Global => {
ExpressionKind::Global(self.cast_ref::<ExpressionGlobal>().name)
}
ExpressionTag::Binary => {
let node = self.cast_ref::<ExpressionBinary>();
ExpressionKind::Binary {
lhs: node.lhs,
op: node.op,
rhs: node.rhs,
}
}
ExpressionTag::Error => {
let node = self.cast_ref::<ExpressionError>();
ExpressionKind::Error {
expressions: node.expressions,
message_index: node.message_index,
}
}
}
}
pub fn visit<V: AstVisitor>(self, visitor: &mut V) {
let should_visit = match self.kind() {
ExpressionKind::Boolean(_) => visitor.visit_boolean_expression(self),
ExpressionKind::Call { .. } => visitor.visit_call_expression(self),
ExpressionKind::FunctionLiteral(_) => visitor.visit_function_literal_expression(self),
ExpressionKind::Grouped(_) => visitor.visit_grouped_expression(self),
ExpressionKind::Integer { .. } => visitor.visit_integer_expression(self),
ExpressionKind::Nil => visitor.visit_nil_expression(self),
ExpressionKind::Number { .. } => visitor.visit_number_expression(self),
ExpressionKind::String { .. } => visitor.visit_string_expression(self),
ExpressionKind::InterpString { .. } => visitor.visit_interp_string_expression(self),
ExpressionKind::Table { .. } => visitor.visit_table_expression(self),
ExpressionKind::If { .. } => visitor.visit_if_expression(self),
ExpressionKind::Varargs => visitor.visit_varargs_expression(self),
ExpressionKind::IndexExpr { .. } => visitor.visit_index_expression(self),
ExpressionKind::IndexName { .. } => visitor.visit_index_name_expression(self),
ExpressionKind::TypeAssertion { .. } => visitor.visit_type_assertion_expression(self),
ExpressionKind::Instantiate { .. } => visitor.visit_instantiate_expression(self),
ExpressionKind::Unary { .. } => visitor.visit_unary_expression(self),
ExpressionKind::Local { .. } => visitor.visit_local_expression(self),
ExpressionKind::Global(_) => visitor.visit_global_expression(self),
ExpressionKind::Binary { .. } => visitor.visit_binary_expression(self),
ExpressionKind::Error { .. } => visitor.visit_error_expression(self),
};
if !should_visit {
return;
}
match self.kind() {
ExpressionKind::Boolean(_)
| ExpressionKind::Integer { .. }
| ExpressionKind::Nil
| ExpressionKind::Number { .. }
| ExpressionKind::String { .. }
| ExpressionKind::Varargs
| ExpressionKind::Local { .. }
| ExpressionKind::Global(_) => {}
ExpressionKind::InterpString { expressions, .. } => {
visit_expressions(expressions, visitor);
}
ExpressionKind::Call { func, args, .. } => {
func.visit(visitor);
visit_expressions(args, visitor);
}
ExpressionKind::FunctionLiteral(function) => function.visit(visitor),
ExpressionKind::Grouped(expression) => expression.visit(visitor),
ExpressionKind::Table { items, .. } => {
for item in items {
item.visit(visitor);
}
}
ExpressionKind::If {
condition,
then_expression,
else_expression,
..
} => {
condition.visit(visitor);
then_expression.visit(visitor);
else_expression.visit(visitor);
}
ExpressionKind::IndexExpr { expr, index, .. } => {
expr.visit(visitor);
index.visit(visitor);
}
ExpressionKind::IndexName { expr, .. } => expr.visit(visitor),
ExpressionKind::TypeAssertion {
expr, annotation, ..
} => {
expr.visit(visitor);
annotation.visit(visitor);
}
ExpressionKind::Instantiate {
expr, type_args, ..
} => {
expr.visit(visitor);
for argument in type_args {
match argument {
TypeOrPack::Type(annotation) => annotation.visit(visitor),
TypeOrPack::Pack(pack) => pack.visit(visitor),
}
}
}
ExpressionKind::Unary { rhs, .. } => rhs.visit(visitor),
ExpressionKind::Binary { lhs, rhs, .. } => {
lhs.visit(visitor);
rhs.visit(visitor);
}
ExpressionKind::Error { expressions, .. } => visit_expressions(expressions, visitor),
}
}
#[inline(always)]
fn cast_ref<T>(self) -> &'ast T {
unsafe { self.ptr.cast::<T>().as_ref() }
}
#[inline(always)]
fn cast_if_tag<T>(self, tag: ExpressionTag) -> Option<&'ast T> {
(self.tag == tag).then(|| self.cast_ref())
}
#[inline(always)]
pub fn as_boolean(self) -> Option<&'ast ExpressionBoolean<'ast>> {
self.cast_if_tag(ExpressionTag::Boolean)
}
#[inline(always)]
pub fn as_call(self) -> Option<&'ast ExpressionCall<'ast>> {
self.cast_if_tag(ExpressionTag::Call)
}
#[inline(always)]
pub fn as_function_literal(self) -> Option<&'ast ExpressionFunctionLiteral<'ast>> {
self.cast_if_tag(ExpressionTag::FunctionLiteral)
}
#[inline(always)]
pub fn as_grouped(self) -> Option<&'ast ExpressionGrouped<'ast>> {
self.cast_if_tag(ExpressionTag::Grouped)
}
#[inline(always)]
pub fn as_integer(self) -> Option<&'ast ExpressionInteger<'ast>> {
self.cast_if_tag(ExpressionTag::Integer)
}
#[inline(always)]
pub fn as_number(self) -> Option<&'ast ExpressionNumber<'ast>> {
self.cast_if_tag(ExpressionTag::Number)
}
#[inline(always)]
pub fn as_string(self) -> Option<&'ast ExpressionString<'ast>> {
self.cast_if_tag(ExpressionTag::String)
}
#[inline(always)]
pub fn as_interp_string(self) -> Option<&'ast ExpressionInterpString<'ast>> {
self.cast_if_tag(ExpressionTag::InterpString)
}
#[inline(always)]
pub fn as_table(self) -> Option<&'ast ExpressionTable<'ast>> {
self.cast_if_tag(ExpressionTag::Table)
}
#[inline(always)]
pub fn as_if(self) -> Option<&'ast ExpressionIf<'ast>> {
self.cast_if_tag(ExpressionTag::If)
}
#[inline(always)]
pub fn as_index_expr(self) -> Option<&'ast ExpressionIndexExpr<'ast>> {
self.cast_if_tag(ExpressionTag::IndexExpr)
}
#[inline(always)]
pub fn as_index_name(self) -> Option<&'ast ExpressionIndexName<'ast>> {
self.cast_if_tag(ExpressionTag::IndexName)
}
#[inline(always)]
pub fn as_type_assertion(self) -> Option<&'ast ExpressionTypeAssertion<'ast>> {
self.cast_if_tag(ExpressionTag::TypeAssertion)
}
#[inline(always)]
pub fn as_instantiate(self) -> Option<&'ast ExpressionInstantiate<'ast>> {
self.cast_if_tag(ExpressionTag::Instantiate)
}
#[inline(always)]
pub fn as_unary(self) -> Option<&'ast ExpressionUnary<'ast>> {
self.cast_if_tag(ExpressionTag::Unary)
}
#[inline(always)]
pub fn as_local(self) -> Option<&'ast ExpressionLocal<'ast>> {
self.cast_if_tag(ExpressionTag::Local)
}
#[inline(always)]
pub fn as_global(self) -> Option<&'ast ExpressionGlobal<'ast>> {
self.cast_if_tag(ExpressionTag::Global)
}
#[inline(always)]
pub fn as_binary(self) -> Option<&'ast ExpressionBinary<'ast>> {
self.cast_if_tag(ExpressionTag::Binary)
}
#[inline(always)]
pub fn as_error(self) -> Option<&'ast ExpressionError<'ast>> {
self.cast_if_tag(ExpressionTag::Error)
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum TableItem<'ast> {
List {
value: Expression<'ast>,
},
Record {
key: Expression<'ast>,
value: Expression<'ast>,
},
General {
key: Expression<'ast>,
value: Expression<'ast>,
},
}
impl TableItem<'_> {
pub fn visit<V: AstVisitor>(&self, visitor: &mut V) {
match self {
Self::List { value } => value.visit(visitor),
Self::Record { key, value } | Self::General { key, value } => {
key.visit(visitor);
value.visit(visitor);
}
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum IndexNameOp {
Dot,
Colon,
}
impl IndexNameOp {
pub fn symbol(self) -> &'static str {
match self {
Self::Dot => ".",
Self::Colon => ":",
}
}
}
#[derive(Debug, PartialEq)]
pub struct Function<'ast> {
pub location: Location,
pub attributes: &'ast [&'ast Attribute<'ast>],
pub generics: &'ast [&'ast GenericType<'ast>],
pub generic_packs: &'ast [&'ast GenericTypePack<'ast>],
pub self_parameter: Option<&'ast Local<'ast>>,
pub args: &'ast [&'ast Local<'ast>],
pub vararg: bool,
pub vararg_location: Location,
pub body: Block<'ast>,
pub function_depth: usize,
pub debug_name: Option<AstName<'ast>>,
pub return_annotation: Option<TypePack<'ast>>,
pub vararg_annotation: Option<TypePack<'ast>>,
pub arg_location: Option<Location>,
}
impl<'ast> Function<'ast> {
pub fn has_native_attribute(&self) -> bool {
self.has_attribute(AttributeKind::Native)
}
pub fn has_attribute(&self, kind: AttributeKind) -> bool {
self.get_attribute(kind).is_some()
}
pub fn get_attribute(&self, kind: AttributeKind) -> Option<&'ast Attribute<'ast>> {
find_attribute(self.attributes, kind)
}
pub fn visit<V: AstVisitor>(&self, visitor: &mut V) {
for arg in self.args {
arg.visit(visitor);
}
if let Some(annotation) = &self.vararg_annotation {
annotation.visit(visitor);
}
if let Some(annotation) = &self.return_annotation {
annotation.visit(visitor);
}
self.body.visit(visitor);
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum UnaryOp {
Length,
Negate,
Not,
}
impl UnaryOp {
pub fn symbol(self) -> &'static str {
match self {
Self::Length => "#",
Self::Negate => "-",
Self::Not => "not",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BinaryOp {
Add,
And,
Concat,
Equal,
FloorDivide,
Greater,
GreaterEqual,
Less,
LessEqual,
NotEqual,
Or,
Subtract,
Multiply,
Divide,
Modulo,
Power,
}
impl BinaryOp {
pub fn symbol(self) -> &'static str {
match self {
Self::Add => "+",
Self::And => "and",
Self::Concat => "..",
Self::Equal => "==",
Self::FloorDivide => "//",
Self::Greater => ">",
Self::GreaterEqual => ">=",
Self::Less => "<",
Self::LessEqual => "<=",
Self::NotEqual => "~=",
Self::Or => "or",
Self::Subtract => "-",
Self::Multiply => "*",
Self::Divide => "/",
Self::Modulo => "%",
Self::Power => "^",
}
}
}
impl AstArena {
fn alloc_expression_node<'ast, T: 'ast>(&'ast self, node: T) -> Expression<'ast> {
Expression::from_node(self.alloc(node))
}
pub(crate) fn alloc_expression_boolean_direct<'ast>(
&'ast self,
location: Location,
value: bool,
) -> Expression<'ast> {
self.alloc_expression_node(ExpressionBoolean::new(location, value))
}
pub(crate) fn alloc_expression_grouped_direct<'ast>(
&'ast self,
location: Location,
expression: Expression<'ast>,
) -> Expression<'ast> {
self.alloc_expression_node(ExpressionGrouped::new(location, expression))
}
pub(crate) fn alloc_expression_integer_direct<'ast>(
&'ast self,
location: Location,
value: i64,
parse_result: ConstantNumberParseResult,
) -> Expression<'ast> {
self.alloc_expression_node(ExpressionInteger::new(location, value, parse_result))
}
pub(crate) fn alloc_expression_number_direct<'ast>(
&'ast self,
location: Location,
value: f64,
parse_result: ConstantNumberParseResult,
) -> Expression<'ast> {
self.alloc_expression_node(ExpressionNumber::new(location, value, parse_result))
}
pub(crate) fn alloc_expression_string_direct<'ast>(
&'ast self,
location: Location,
value: AstString<'ast>,
quote_style: StringQuoteStyle,
) -> Expression<'ast> {
self.alloc_expression_node(ExpressionString::new(location, value, quote_style))
}
pub(crate) fn alloc_expression_unary_direct<'ast>(
&'ast self,
location: Location,
op: UnaryOp,
rhs: Expression<'ast>,
) -> Expression<'ast> {
self.alloc_expression_node(ExpressionUnary::new(location, op, rhs))
}
pub(crate) fn alloc_expression_local_direct<'ast>(
&'ast self,
location: Location,
local: &'ast Local<'ast>,
upvalue: bool,
) -> Expression<'ast> {
self.alloc_expression_node(ExpressionLocal::new(location, local, upvalue))
}
pub(crate) fn alloc_expression_global_direct<'ast>(
&'ast self,
location: Location,
name: AstName<'ast>,
) -> Expression<'ast> {
self.alloc_expression_node(ExpressionGlobal::new(location, name))
}
pub(crate) fn alloc_expression_function_literal_direct<'ast>(
&'ast self,
location: Location,
function: &'ast mut Function<'ast>,
) -> Expression<'ast> {
self.alloc_expression_node(ExpressionFunctionLiteral::new(location, function))
}
pub(crate) fn alloc_expression_binary_direct<'ast>(
&'ast self,
location: Location,
lhs: Expression<'ast>,
op: BinaryOp,
rhs: Expression<'ast>,
) -> Expression<'ast> {
self.alloc_expression_node(ExpressionBinary::new(location, lhs, op, rhs))
}
pub(crate) fn alloc_expression_nil_direct<'ast>(
&'ast self,
location: Location,
) -> Expression<'ast> {
self.alloc_expression_node(ExpressionUnit::new(ExpressionTag::Nil, location))
}
pub(crate) fn alloc_expression_index_name_direct<'ast>(
&'ast self,
location: Location,
expr: Expression<'ast>,
index: AstName<'ast>,
index_location: Location,
op_position: Position,
op: IndexNameOp,
) -> Expression<'ast> {
self.alloc_expression_node(ExpressionIndexName::new(
location,
expr,
index,
index_location,
op_position,
op,
))
}
pub(crate) fn alloc_expression_error_direct<'ast>(
&'ast self,
location: Location,
expressions: &'ast [Expression<'ast>],
message_index: usize,
) -> Expression<'ast> {
self.alloc_expression_node(ExpressionError::new(location, expressions, message_index))
}
pub(crate) fn alloc_expression_kind<'ast>(
&'ast self,
location: Location,
kind: ExpressionKind<'ast>,
) -> Expression<'ast> {
match kind {
ExpressionKind::Boolean(value) => {
self.alloc_expression_node(ExpressionBoolean::new(location, value))
}
ExpressionKind::Call {
func,
type_args,
args,
self_call,
arg_location,
} => self.alloc_expression_node(ExpressionCall::new(
location,
func,
type_args,
args,
self_call,
arg_location,
)),
ExpressionKind::FunctionLiteral(function) => {
self.alloc_expression_node(ExpressionFunctionLiteral::new(location, function))
}
ExpressionKind::Grouped(expression) => {
self.alloc_expression_node(ExpressionGrouped::new(location, expression))
}
ExpressionKind::Integer {
value,
parse_result,
} => self.alloc_expression_node(ExpressionInteger::new(location, value, parse_result)),
ExpressionKind::Nil => {
self.alloc_expression_node(ExpressionUnit::new(ExpressionTag::Nil, location))
}
ExpressionKind::Number {
value,
parse_result,
} => self.alloc_expression_node(ExpressionNumber::new(location, value, parse_result)),
ExpressionKind::String { value, quote_style } => {
self.alloc_expression_node(ExpressionString::new(location, value, quote_style))
}
ExpressionKind::InterpString {
strings,
expressions,
} => self.alloc_expression_node(ExpressionInterpString::new(
location,
strings,
expressions,
)),
ExpressionKind::Table { items } => {
self.alloc_expression_node(ExpressionTable::new(location, items))
}
ExpressionKind::If {
condition,
has_then,
then_expression,
has_else,
else_expression,
} => self.alloc_expression_node(ExpressionIf::new(
location,
condition,
has_then,
then_expression,
has_else,
else_expression,
)),
ExpressionKind::Varargs => {
self.alloc_expression_node(ExpressionUnit::new(ExpressionTag::Varargs, location))
}
ExpressionKind::IndexExpr { expr, index } => {
self.alloc_expression_node(ExpressionIndexExpr::new(location, expr, index))
}
ExpressionKind::IndexName {
expr,
index,
index_location,
op_position,
op,
} => self.alloc_expression_node(ExpressionIndexName::new(
location,
expr,
index,
index_location,
op_position,
op,
)),
ExpressionKind::TypeAssertion { expr, annotation } => {
self.alloc_expression_node(ExpressionTypeAssertion::new(location, expr, annotation))
}
ExpressionKind::Instantiate { expr, type_args } => {
self.alloc_expression_node(ExpressionInstantiate::new(location, expr, type_args))
}
ExpressionKind::Unary { op, rhs } => {
self.alloc_expression_node(ExpressionUnary::new(location, op, rhs))
}
ExpressionKind::Local { local, upvalue } => {
self.alloc_expression_node(ExpressionLocal::new(location, local, upvalue))
}
ExpressionKind::Global(name) => {
self.alloc_expression_node(ExpressionGlobal::new(location, name))
}
ExpressionKind::Binary { lhs, op, rhs } => {
self.alloc_expression_node(ExpressionBinary::new(location, lhs, op, rhs))
}
ExpressionKind::Error {
expressions,
message_index,
} => self.alloc_expression_node(ExpressionError::new(
location,
expressions,
message_index,
)),
}
}
}