Skip to content

Commit 86963a3

Browse files
committed
fix(lsp): type check fix, no_fold fix.
1 parent e15493a commit 86963a3

5 files changed

Lines changed: 43 additions & 3 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
- **`Opaque` hovers with its own docs** - It showed the Rerouter gate's blurb, which says nothing about the fold-hiding and type-erasing behaviour it exists for.
1111
- **Fixed `.Value` on a multi-output result** - `a.pop().Value` typed as the whole record, so every use of it mismatched.
1212
- **Fixed a type alias not resolving through a namespace import** - `import * as T` with `mod f() -> MyType` failed with "unknown type". Aliases now inline as they do for a named import, and `T.MyType` parses as a qualified type.
13+
- **`GetLeaderboard` returns `int`** - It was typed `any`, so arithmetic on its result had no operator overload.
14+
- **`bool` arithmetic with two bools** - `bool + bool` (and `- * / %`) now promotes to `int`, matching `bool`/`int` mixes and the bitwise ops; `(a && b) + (c && d)` compiles.
1315

1416
## 0.17.0
1517

crates/lsp/src/main.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,6 @@ impl Backend {
300300
source: &src_owned,
301301
file: &file_owned,
302302
module_name: None,
303-
no_fold: false,
304303
})
305304
})
306305
.await;
@@ -846,7 +845,6 @@ impl LanguageServer for Backend {
846845
source: &src_owned,
847846
file: &file_owned,
848847
module_name: None,
849-
no_fold: false,
850848
},
851849
wirescript::EmitOptions::default(),
852850
progress_cb,

crates/wirescript/src/catalog/calls.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1315,7 +1315,7 @@ fn build_calls() -> HashMap<&'static str, CallSpec> {
13151315
vec![CallOutput {
13161316
field: None,
13171317
port: WirePort::Value,
1318-
ty: Type::Any,
1318+
ty: Type::Int,
13191319
}],
13201320
),
13211321
);
@@ -2648,6 +2648,21 @@ mod tests {
26482648
assert!(find_call("doesNotExist").is_none());
26492649
}
26502650

2651+
#[test]
2652+
fn leaderboard_getters_return_int() {
2653+
// The inventory dump types both leaderboard `Value` outputs as `int`;
2654+
// `GetLeaderboard` was declared `Any`, so arithmetic on its result had
2655+
// no operator overload.
2656+
for name in ["GetLeaderboard", "GetTeamLeaderboardValue"] {
2657+
let c = find_call(name).unwrap();
2658+
assert!(
2659+
matches!(c.outputs[0].ty, Type::Int),
2660+
"{name} should return int, got {:?}",
2661+
c.outputs[0].ty
2662+
);
2663+
}
2664+
}
2665+
26512666
/// Params that name a settable field the gate does not expose as a wire
26522667
/// input. These only ever work as constants — lowering writes them into the
26532668
/// component's data and drops the wire; a computed value has nowhere to go.

crates/wirescript/src/catalog/operators.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ fn math_binary(op: &'static str, class_math: &'static str, vec: bool) -> OpSpec
8383
ports: BINARY_PORTS,
8484
},
8585
// bool → int promotion (engine coerces bool wires to 0/1 on int ports).
86+
// Both operands promote, so bool⊕bool is int-valued too — matching the
87+
// mixed forms below and the bitwise ops, which already allow it.
8688
OpRule {
8789
operands: &[Type::Int, Type::Bool],
8890
result: Type::Int,
@@ -95,6 +97,12 @@ fn math_binary(op: &'static str, class_math: &'static str, vec: bool) -> OpSpec
9597
gate_class: class_math,
9698
ports: BINARY_PORTS,
9799
},
100+
OpRule {
101+
operands: &[Type::Bool, Type::Bool],
102+
result: Type::Int,
103+
gate_class: class_math,
104+
ports: BINARY_PORTS,
105+
},
98106
];
99107
if vec {
100108
// Vector math runs on the same gate: MathAdd/Subtract/Multiply/Divide/
@@ -583,6 +591,17 @@ mod tests {
583591
assert_eq!(r.gate_class, "BrickComponentType_WireGraph_Expr_MathAdd");
584592
}
585593

594+
#[test]
595+
fn add_bool_bool_promotes_to_int() {
596+
// bool coerces to 0/1 on int ports, so bool⊕bool is int-valued -- same
597+
// as bool⊕int and the bitwise ops. Covers `(a && b) + (c && d)`.
598+
for op in ["+", "-", "*", "/", "%"] {
599+
let r = resolve_op(op, &[Type::Bool, Type::Bool])
600+
.unwrap_or_else(|| panic!("no rule for bool {op} bool"));
601+
assert!(matches!(r.result, Type::Int), "{op} bool/bool should be int");
602+
}
603+
}
604+
586605
#[test]
587606
fn add_mixed_promotes_to_float() {
588607
let r = resolve_op("+", &[Type::Int, Type::Float]).unwrap();

crates/wirescript/src/typecheck.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1916,6 +1916,12 @@ fn infer_expr_inner(
19161916
(Type::Vector, "x" | "X" | "y" | "Y" | "z" | "Z") => Type::Float,
19171917
(Type::Color, "r" | "R" | "g" | "G" | "b" | "B" | "a" | "A") => Type::Float,
19181918
(Type::Rotator, "pitch" | "yaw" | "roll") => Type::Float,
1919+
// An array read yields the element plus a bounds flag, but it is
1920+
// typed as the bare element (see IndexAccess), so by the time the
1921+
// flag is projected - directly or through a `let` - the object is
1922+
// the element type and this would fall through to Any. Lowering
1923+
// already maps these names to the gate's bOutOfBounds port.
1924+
(_, "OutOfBounds" | "bOutOfBounds") => Type::Bool,
19191925
_ => Type::Any,
19201926
}
19211927
}

0 commit comments

Comments
 (0)