Skip to content

Commit 81a64da

Browse files
committed
basic support luajit extension grammar
1 parent 6b2fd7a commit 81a64da

27 files changed

Lines changed: 424 additions & 83 deletions

File tree

crates/emmylua_code_analysis/resources/schema.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -828,6 +828,12 @@
828828
},
829829
"EmmyrcLuaVersion": {
830830
"oneOf": [
831+
{
832+
"type": "string",
833+
"enum": [
834+
"LuaJIT-Ext"
835+
]
836+
},
831837
{
832838
"description": "Lua 5.1",
833839
"type": "string",

crates/emmylua_code_analysis/src/compilation/analyzer/flow/bind_analyze/exprs/mod.rs

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@ mod bind_binary_expr;
22

33
use emmylua_parser::{
44
LuaAst, LuaAstNode, LuaCallExpr, LuaClosureExpr, LuaExpr, LuaIndexExpr, LuaNameExpr,
5-
LuaTableExpr, LuaUnaryExpr,
5+
LuaNilCoalescingExpr, LuaTableExpr, LuaTernaryExpr, LuaUnaryExpr,
66
};
77

88
use crate::{
99
FlowId, FlowNodeKind,
1010
compilation::analyzer::flow::{
11-
bind_analyze::{bind_each_child, exprs::bind_binary_expr::is_binary_logical},
11+
bind_analyze::{
12+
bind_each_child, exprs::bind_binary_expr::is_binary_logical, finish_flow_label,
13+
},
1214
binder::FlowBinder,
1315
},
1416
};
@@ -54,6 +56,10 @@ pub fn bind_expr(binder: &mut FlowBinder, expr: LuaExpr, current: FlowId) -> Flo
5456
LuaExpr::IndexExpr(index_expr) => bind_index_expr(binder, index_expr, current),
5557
LuaExpr::BinaryExpr(binary_expr) => bind_binary_expr(binder, binary_expr, current),
5658
LuaExpr::UnaryExpr(unary_expr) => bind_unary_expr(binder, unary_expr, current),
59+
LuaExpr::TernaryExpr(ternary_expr) => bind_ternary_expr(binder, ternary_expr, current),
60+
LuaExpr::NilCoalescingExpr(nil_coalescing_expr) => {
61+
bind_nil_coalescing_expr(binder, nil_coalescing_expr, current)
62+
}
5763
};
5864

5965
current
@@ -125,3 +131,53 @@ pub fn bind_call_expr(
125131
bind_each_child(binder, LuaAst::LuaCallExpr(call_expr.clone()), current);
126132
Some(())
127133
}
134+
135+
fn bind_ternary_expr(
136+
binder: &mut FlowBinder,
137+
ternary_expr: LuaTernaryExpr,
138+
current: FlowId,
139+
) -> Option<()> {
140+
let condition = ternary_expr.get_condition_expr()?;
141+
let (true_expr, false_expr) = ternary_expr.get_true_false_exprs()?;
142+
143+
let pre_false = binder.create_branch_label();
144+
bind_condition_expr(binder, condition, current, binder.true_target, pre_false);
145+
let current = finish_flow_label(binder, pre_false, current);
146+
bind_condition_expr(
147+
binder,
148+
true_expr,
149+
current,
150+
binder.true_target,
151+
binder.false_target,
152+
);
153+
bind_condition_expr(
154+
binder,
155+
false_expr,
156+
current,
157+
binder.true_target,
158+
binder.false_target,
159+
);
160+
161+
Some(())
162+
}
163+
164+
fn bind_nil_coalescing_expr(
165+
binder: &mut FlowBinder,
166+
nil_coalescing_expr: LuaNilCoalescingExpr,
167+
current: FlowId,
168+
) -> Option<()> {
169+
let (left, right) = nil_coalescing_expr.get_left_right_exprs()?;
170+
171+
let pre_right = binder.create_branch_label();
172+
bind_condition_expr(binder, left, current, binder.true_target, pre_right);
173+
let current = finish_flow_label(binder, pre_right, current);
174+
bind_condition_expr(
175+
binder,
176+
right,
177+
current,
178+
binder.true_target,
179+
binder.false_target,
180+
);
181+
182+
Some(())
183+
}

crates/emmylua_code_analysis/src/compilation/analyzer/lua/func_body.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,5 +426,6 @@ fn can_analyze_condition(expr: &LuaExpr) -> bool {
426426
can_analyze_condition(&left) && can_analyze_condition(&right)
427427
}),
428428
LuaExpr::NameExpr(_) | LuaExpr::IndexExpr(_) => false,
429+
_ => true, // TernaryExpr, NilCoalescingExpr
429430
}
430431
}

crates/emmylua_code_analysis/src/config/configs/runtime.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ pub enum EmmyrcLuaVersion {
4040
/// LuaJIT
4141
#[serde(rename = "LuaJIT")]
4242
LuaJIT,
43+
#[serde(rename = "LuaJIT-Ext", alias = "LuaJIT Ext")]
44+
LuaJITExt,
4345
/// Lua 5.2
4446
#[serde(rename = "Lua5.2", alias = "Lua 5.2")]
4547
Lua52,
@@ -63,6 +65,7 @@ impl EmmyrcLuaVersion {
6365
match self {
6466
EmmyrcLuaVersion::Lua51 => LuaVersionNumber::new(5, 1, 0),
6567
EmmyrcLuaVersion::LuaJIT => LuaVersionNumber::LUA_JIT,
68+
EmmyrcLuaVersion::LuaJITExt => LuaVersionNumber::LUA_JIT_EXT,
6669
EmmyrcLuaVersion::Lua52 => LuaVersionNumber::new(5, 2, 0),
6770
EmmyrcLuaVersion::Lua53 => LuaVersionNumber::new(5, 3, 0),
6871
EmmyrcLuaVersion::Lua54 => LuaVersionNumber::new(5, 4, 0),

crates/emmylua_code_analysis/src/config/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ impl Emmyrc {
100100
EmmyrcLuaVersion::Lua53 => LuaLanguageLevel::Lua53,
101101
EmmyrcLuaVersion::Lua54 => LuaLanguageLevel::Lua54,
102102
EmmyrcLuaVersion::LuaJIT => LuaLanguageLevel::LuaJIT,
103+
EmmyrcLuaVersion::LuaJITExt => LuaLanguageLevel::LuaJITExt,
103104
EmmyrcLuaVersion::Lua55 => LuaLanguageLevel::Lua55,
104105
EmmyrcLuaVersion::LuaLatest => LuaLanguageLevel::Lua55,
105106
}

crates/emmylua_code_analysis/src/semantic/infer/infer_index/mod.rs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
mod infer_array;
22

33
use emmylua_parser::{
4-
LuaExpr, LuaIndexExpr, LuaIndexKey, LuaIndexMemberExpr, NumberResult, PathTrait,
4+
LuaExpr, LuaIndexExpr, LuaIndexKey, LuaIndexMemberExpr, LuaNilCoalescingExpr, LuaTernaryExpr,
5+
NumberResult, PathTrait,
56
};
67
use hashbrown::HashSet;
78
use internment::ArcIntern;
@@ -94,6 +95,32 @@ pub fn infer_index_expr(
9495
}
9596
}
9697

98+
pub fn infer_ternary_expr(
99+
db: &DbIndex,
100+
cache: &mut LuaInferCache,
101+
ternary_expr: LuaTernaryExpr,
102+
) -> InferResult {
103+
let Some((true_expr, false_expr)) = ternary_expr.get_true_false_exprs() else {
104+
return Err(InferFailReason::None);
105+
};
106+
let true_type = infer_expr(db, cache, true_expr)?;
107+
let false_type = infer_expr(db, cache, false_expr)?;
108+
Ok(TypeOps::Union.apply(db, &true_type, &false_type))
109+
}
110+
111+
pub fn infer_nil_coalescing_expr(
112+
db: &DbIndex,
113+
cache: &mut LuaInferCache,
114+
nil_coalescing_expr: LuaNilCoalescingExpr,
115+
) -> InferResult {
116+
let Some((left_expr, right_expr)) = nil_coalescing_expr.get_left_right_exprs() else {
117+
return Err(InferFailReason::None);
118+
};
119+
let left_type = infer_expr(db, cache, left_expr)?;
120+
let right_type = infer_expr(db, cache, right_expr)?;
121+
Ok(TypeOps::Union.apply(db, &left_type, &right_type))
122+
}
123+
97124
fn infer_member_type_pass_flow(
98125
db: &DbIndex,
99126
cache: &mut LuaInferCache,

crates/emmylua_code_analysis/src/semantic/infer/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ use smol_str::SmolStr;
3636
use crate::{
3737
InFiled, InferGuard, LuaMemberKey, VariadicType,
3838
db_index::{DbIndex, LuaOperator, LuaOperatorMetaMethod, LuaSignatureId, LuaType},
39+
semantic::infer::infer_index::{infer_nil_coalescing_expr, infer_ternary_expr},
3940
};
4041

4142
use super::{CacheEntry, LuaInferCache, member::infer_raw_member_type};
@@ -132,6 +133,10 @@ pub fn infer_expr(db: &DbIndex, cache: &mut LuaInferCache, expr: LuaExpr) -> Inf
132133
),
133134
LuaExpr::NameExpr(name_expr) => infer_name_expr(db, cache, name_expr),
134135
LuaExpr::IndexExpr(index_expr) => infer_index_expr(db, cache, index_expr, !no_flow),
136+
LuaExpr::TernaryExpr(ternary_expr) => infer_ternary_expr(db, cache, ternary_expr),
137+
LuaExpr::NilCoalescingExpr(nil_coalescing_expr) => {
138+
infer_nil_coalescing_expr(db, cache, nil_coalescing_expr)
139+
}
135140
};
136141

137142
match &result_type {

crates/emmylua_code_analysis/src/semantic/infer/narrow/condition_flow/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,10 @@ pub(super) fn get_type_at_condition_flow(
659659
condition = inner_expr;
660660
continue;
661661
}
662+
// todo next version
663+
_ => {
664+
return Ok(ConditionFlowAction::Continue);
665+
}
662666
}
663667
}
664668
}

crates/emmylua_formatter/src/formatter/expr.rs

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
use emmylua_parser::{
22
BinaryOperator, LuaAssignStat, LuaAstNode, LuaAstToken, LuaBinaryExpr, LuaCallArgList,
33
LuaCallExpr, LuaClosureExpr, LuaComment, LuaExpr, LuaIndexExpr, LuaIndexKey, LuaKind,
4-
LuaLiteralExpr, LuaLiteralToken, LuaLocalStat, LuaNameExpr, LuaParamList, LuaParenExpr,
5-
LuaSingleArgExpr, LuaStat, LuaSyntaxId, LuaSyntaxKind, LuaSyntaxNode, LuaSyntaxToken,
6-
LuaTableExpr, LuaTableField, LuaTokenKind, LuaUnaryExpr,
4+
LuaLiteralExpr, LuaLiteralToken, LuaLocalStat, LuaNameExpr, LuaNilCoalescingExpr, LuaParamList,
5+
LuaParenExpr, LuaSingleArgExpr, LuaStat, LuaSyntaxId, LuaSyntaxKind, LuaSyntaxNode,
6+
LuaSyntaxToken, LuaTableExpr, LuaTableField, LuaTernaryExpr, LuaTokenKind, LuaUnaryExpr,
77
};
88
use rowan::TextRange;
99

@@ -60,6 +60,8 @@ pub fn format_expr_with_options(
6060
LuaExpr::CallExpr(expr) => format_call_expr(ctx, plan, expr),
6161
LuaExpr::TableExpr(expr) => format_table_expr(ctx, plan, expr),
6262
LuaExpr::ClosureExpr(expr) => format_closure_expr(ctx, plan, expr),
63+
LuaExpr::TernaryExpr(expr) => format_ternary_expr(ctx, plan, expr),
64+
LuaExpr::NilCoalescingExpr(expr) => format_nil_coalescing_expr(ctx, plan, expr),
6365
}
6466
}
6567

@@ -2341,6 +2343,45 @@ fn format_closure_expr(
23412343
render_closure_shell(ctx, plan, expr, shell_plan)
23422344
}
23432345

2346+
fn format_ternary_expr(
2347+
ctx: &FormatContext,
2348+
plan: &FormatPlan,
2349+
expr: &LuaTernaryExpr,
2350+
) -> Vec<DocIR> {
2351+
let Some(cond_expr) = expr.get_condition_expr() else {
2352+
return vec![ir::source_node(expr.syntax().clone())];
2353+
};
2354+
let Some((true_expr, false_expr)) = expr.get_true_false_exprs() else {
2355+
return vec![ir::source_node(expr.syntax().clone())];
2356+
};
2357+
let mut docs = format_expr(ctx, plan, &cond_expr);
2358+
docs.push(ir::space());
2359+
docs.push(ir::syntax_token(LuaTokenKind::TkTernary));
2360+
docs.push(ir::space());
2361+
docs.extend(format_expr(ctx, plan, &true_expr));
2362+
docs.push(ir::space());
2363+
docs.push(ir::syntax_token(LuaTokenKind::TkColon));
2364+
docs.push(ir::space());
2365+
docs.extend(format_expr(ctx, plan, &false_expr));
2366+
docs
2367+
}
2368+
2369+
fn format_nil_coalescing_expr(
2370+
ctx: &FormatContext,
2371+
plan: &FormatPlan,
2372+
expr: &LuaNilCoalescingExpr,
2373+
) -> Vec<DocIR> {
2374+
let Some((left_expr, right_expr)) = expr.get_left_right_exprs() else {
2375+
return vec![ir::source_node(expr.syntax().clone())];
2376+
};
2377+
let mut docs = format_expr(ctx, plan, &left_expr);
2378+
docs.push(ir::space());
2379+
docs.push(ir::syntax_token(LuaTokenKind::TkNilCoalescing));
2380+
docs.push(ir::space());
2381+
docs.extend(format_expr(ctx, plan, &right_expr));
2382+
docs
2383+
}
2384+
23442385
fn try_format_simple_inline_closure_expr(
23452386
ctx: &FormatContext,
23462387
plan: &FormatPlan,

crates/emmylua_formatter/src/formatter/spacing.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ pub(crate) fn space_around_binary_op(op: BinaryOperator, config: &LuaFormatConfi
5353
| BinaryOperator::OpShl
5454
| BinaryOperator::OpShr
5555
| BinaryOperator::OpNop
56+
| BinaryOperator::OpShrAthrimetic
5657
| BinaryOperator::OpNilCoalescing => SpaceRule::Space,
5758
BinaryOperator::OpConcat => {
5859
if config.spacing.space_around_concat_operator {

0 commit comments

Comments
 (0)