Skip to content

Commit f8f1f3c

Browse files
committed
Initial attempt at implementing switch support
1 parent 778bb79 commit f8f1f3c

File tree

4 files changed

+344
-139
lines changed

4 files changed

+344
-139
lines changed

data/Switch.hx

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
class Switch {
2+
static function main() {
3+
var a = 3;
4+
var b = switch (a) {
5+
case 0: a * 2;
6+
case 3: a - 1;
7+
default: a << 2;
8+
}
9+
switch (b) {
10+
case 0: b += 1;
11+
case 1: b += 1;
12+
case 2: b += 1;
13+
//case 4: b += 1;
14+
}
15+
/*
16+
switch (a) {
17+
case -1: b += 1;
18+
case -5: b += 1;
19+
}
20+
var c = "hello";
21+
switch (c) {
22+
case "hello": a += 1;
23+
case "world": a += 1;
24+
}*/
25+
}
26+
}

src/decompiler/ast.rs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -258,12 +258,10 @@ pub enum Statement {
258258
variable: Expr,
259259
assign: Expr,
260260
},
261-
// Call a void function (no assignment)
262-
Call(Call),
263-
/// Return an expression
264-
Return(Expr),
265-
/// Return nothing / early return
266-
ReturnVoid,
261+
/// Expression statement
262+
ExprStatement(Expr),
263+
/// Return an expression or nothing (void)
264+
Return(Option<Expr>),
267265
/// If statement
268266
If {
269267
cond: Expr,
@@ -273,6 +271,11 @@ pub enum Statement {
273271
Else {
274272
stmts: Vec<Statement>,
275273
},
274+
Switch {
275+
arg: Expr,
276+
default: Vec<Statement>,
277+
cases: Vec<(Expr, Vec<Statement>)>,
278+
},
276279
/// While statement
277280
While {
278281
cond: Expr,
@@ -282,3 +285,8 @@ pub enum Statement {
282285
Continue,
283286
Throw(Expr),
284287
}
288+
289+
/// Create an expression statement
290+
pub fn stmt(e: Expr) -> Statement {
291+
Statement::ExprStatement(e)
292+
}

src/decompiler/fmt.rs

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::fmt;
22
use std::fmt::{Display, Formatter};
33

44
use crate::decompiler::ast::{
5-
Call, Class, Constant, ConstructorCall, Expr, Method, Operation, Statement,
5+
Class, Constant, ConstructorCall, Expr, Method, Operation, Statement,
66
};
77
use crate::types::{Function, RefField, Type};
88
use crate::Bytecode;
@@ -245,13 +245,12 @@ impl Statement {
245245
} => {
246246
if *declaration { "var " } else { "" }{disp!(variable)}" = "{disp!(assign)}";"
247247
}
248-
Statement::Call(Call { fun, args }) => {
249-
{disp!(fun)}"("{fmtools::join(", ", args.iter().map(|e| disp!(e)))}");"
248+
Statement::ExprStatement(expr) => {
249+
{disp!(expr)}";"
250250
}
251251
Statement::Return(expr) => {
252-
"return "{disp!(expr)}";"
252+
"return" if let Some(e) = expr { " "{disp!(e)} } ";"
253253
}
254-
Statement::ReturnVoid => "return;",
255254
Statement::If { cond, stmts } => {
256255
"if ("{disp!(cond)}") {\n"
257256
let indent2 = indent.inc_nesting();
@@ -268,6 +267,24 @@ impl Statement {
268267
}
269268
{indent}"}"
270269
}
270+
Statement::Switch {arg, default, cases} => {
271+
"switch ("{disp!(arg)}") {\n"
272+
let indent2 = indent.inc_nesting();
273+
let indent3 = indent2.inc_nesting();
274+
if !default.is_empty() {
275+
{indent2}"default:\n"
276+
for stmt in default {
277+
{indent3}{stmt.display(&indent3, code, f)}"\n"
278+
}
279+
}
280+
for (pattern, stmts) in cases {
281+
{indent2}"case "{disp!(pattern)}":\n"
282+
for stmt in stmts {
283+
{indent3}{stmt.display(&indent3, code, f)}"\n"
284+
}
285+
}
286+
{indent}"}"
287+
}
271288
Statement::While { cond, stmts } => {
272289
"while ("{disp!(cond)}") {\n"
273290
let indent2 = indent.inc_nesting();

0 commit comments

Comments
 (0)