Skip to content

Commit b763d1c

Browse files
authored
Merge pull request #72 from ExpHP/signed-int
Signed integers but only in AST. This lays some of the foundation necessary to have more general int formats in LLIR signatures.
2 parents fb970a2 + 5a9eb91 commit b763d1c

File tree

7 files changed

+90
-23
lines changed

7 files changed

+90
-23
lines changed

src/ast/meta.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,10 @@ impl ToMeta for f32 {
576576
fn to_meta(&self) -> Meta { Meta::Scalar(sp!((*self).into())) }
577577
}
578578
impl ToMeta for bool {
579-
fn to_meta(&self) -> Meta { Meta::Scalar(sp!(ast::Expr::LitInt { value: *self as i32, radix: ast::IntRadix::Bool })) }
579+
fn to_meta(&self) -> Meta { Meta::Scalar(sp!(ast::Expr::LitInt {
580+
value: *self as i32,
581+
format: ast::IntFormat::BOOL,
582+
}))}
580583
}
581584
impl ToMeta for String {
582585
fn to_meta(&self) -> Meta { Meta::Scalar(sp!(self.to_owned().into())) }

src/ast/mod.rs

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -454,8 +454,8 @@ pub enum Expr {
454454
LitInt {
455455
value: raw::LangInt,
456456
/// A hint to the formatter on how it should write the integer.
457-
/// (may not necessarily represent the original radix of a parsed token)
458-
radix: IntRadix,
457+
/// (not meaningful when parsing)
458+
format: IntFormat,
459459
},
460460
LitFloat { value: raw::LangFloat },
461461
LitString(LitString),
@@ -469,14 +469,29 @@ pub enum Expr {
469469
},
470470
}
471471

472+
473+
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
474+
pub struct IntFormat {
475+
pub signed: bool,
476+
pub radix: IntRadix,
477+
}
478+
479+
impl IntFormat {
480+
pub const UNSIGNED: IntFormat = IntFormat { signed: false, radix: IntRadix::Dec };
481+
pub const SIGNED: IntFormat = IntFormat { signed: true, radix: IntRadix::Dec };
482+
pub const HEX: IntFormat = IntFormat { signed: false, radix: IntRadix::Hex };
483+
pub const BIN: IntFormat = IntFormat { signed: false, radix: IntRadix::Bin };
484+
pub const BOOL: IntFormat = IntFormat { signed: true, radix: IntRadix::Bool };
485+
/// Used to decompile `jmp` in function syntax.
486+
pub const SIGNED_HEX: IntFormat = IntFormat { signed: true, radix: IntRadix::Hex };
487+
}
488+
472489
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
473490
pub enum IntRadix {
474491
/// Display as decimal.
475492
Dec,
476493
/// Display as hexadecimal, with an `0x` prefix.
477494
Hex,
478-
/// Display as potentially negative hexadecimal, with an `0x` prefix.
479-
SignedHex,
480495
/// Display as binary, with an `0b` prefix.
481496
Bin,
482497
/// Use `true` and `false` if the value is `1` or `0`. Otherwise, fall back to decimal.
@@ -850,7 +865,7 @@ string_enum! {
850865
}
851866

852867
impl From<raw::LangInt> for Expr {
853-
fn from(value: raw::LangInt) -> Expr { Expr::LitInt { value, radix: IntRadix::Dec } }
868+
fn from(value: raw::LangInt) -> Expr { Expr::LitInt { value, format: IntFormat::SIGNED } }
854869
}
855870
impl From<raw::LangFloat> for Expr {
856871
fn from(value: raw::LangFloat) -> Expr { Expr::LitFloat { value } }
@@ -1269,7 +1284,7 @@ macro_rules! generate_visitor_stuff {
12691284
Expr::XcrementOp { op: _, order: _, var } => {
12701285
v.visit_var(var);
12711286
},
1272-
Expr::LitInt { value: _, radix: _ } => {},
1287+
Expr::LitInt { value: _, format: _ } => {},
12731288
Expr::LitFloat { value: _ } => {},
12741289
Expr::LitString(_s) => {},
12751290
Expr::LabelProperty { .. } => {},

src/fmt.rs

Lines changed: 58 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -899,13 +899,36 @@ impl Format for ast::Expr {
899899
ast::Expr::XcrementOp { order: ast::XcrementOpOrder::Pre, op, var } => out.fmt((op, var)),
900900
ast::Expr::XcrementOp { order: ast::XcrementOpOrder::Post, op, var } => out.fmt((var, op)),
901901
ast::Expr::EnumConst { enum_name, ident } => out.fmt((enum_name, ".", ident)),
902-
ast::Expr::LitInt { value: 0, radix: ast::IntRadix::Bool } => out.fmt("false"),
903-
ast::Expr::LitInt { value: 1, radix: ast::IntRadix::Bool } => out.fmt("true"),
904-
ast::Expr::LitInt { value, radix: ast::IntRadix::Bool } => out.fmt(value),
905-
ast::Expr::LitInt { value, radix: ast::IntRadix::Dec } => out.fmt(value),
906-
ast::Expr::LitInt { value, radix: ast::IntRadix::Hex } => out.fmt(format_args!("{:#x}", value)),
907-
ast::Expr::LitInt { value, radix: ast::IntRadix::SignedHex } => out.fmt(format_args!("{:#x}", SignedRadix(*value))),
908-
ast::Expr::LitInt { value, radix: ast::IntRadix::Bin } => out.fmt(format_args!("{:#b}", value)),
902+
ast::Expr::LitInt { value, format } => match format {
903+
// These are the decimal formats
904+
&ast::IntFormat::SIGNED => out.fmt(value),
905+
&ast::IntFormat::UNSIGNED => {
906+
out.fmt(format_args!("{}", *value as u32))
907+
},
908+
909+
&ast::IntFormat { radix: ast::IntRadix::Hex, signed } => {
910+
match signed {
911+
false => out.fmt(format_args!("{:#x}", value)),
912+
true => out.fmt(format_args!("{:#x}", SignedRadix(*value))),
913+
}
914+
},
915+
916+
&ast::IntFormat { radix: ast::IntRadix::Bin, signed } => {
917+
match signed {
918+
false => out.fmt(format_args!("{:#b}", value)),
919+
true => out.fmt(format_args!("{:#b}", SignedRadix(*value))),
920+
}
921+
},
922+
923+
&ast::IntFormat { radix: ast::IntRadix::Bool, signed } => {
924+
match (value, signed) {
925+
(0, _) => out.fmt("false"),
926+
(1, _) => out.fmt("true"),
927+
(_, true) => out.fmt(value),
928+
(_, false) => out.fmt(format_args!("{:#x}", *value as u32)),
929+
}
930+
},
931+
},
909932
ast::Expr::LitFloat { value } => out.fmt(value),
910933
ast::Expr::LitString(x) => out.fmt(x),
911934
ast::Expr::LabelProperty { label, keyword } => out.fmt((keyword, "(", label, ")")),
@@ -1136,4 +1159,32 @@ mod tests {
11361159
assert!(reformat::<ast::ScriptFile>(3, r#"meta { x: 25 }"#).ends_with("\n"));
11371160
assert!(reformat::<ast::ScriptFile>(9999, r#" script lol { nop(); }"#).ends_with("\n"));
11381161
}
1162+
1163+
#[test]
1164+
fn integer_formats() {
1165+
use ast::IntRadix as R;
1166+
1167+
fn fmt_int(value: i32, signed: bool, radix: R) -> String {
1168+
stringify(&ast::Expr::LitInt {
1169+
value,
1170+
format: ast::IntFormat { signed, radix }
1171+
})
1172+
}
1173+
1174+
assert_eq!(fmt_int(20, true, R::Dec), "20");
1175+
assert_eq!(fmt_int(-20, true, R::Dec), "-20");
1176+
assert_eq!(fmt_int(-0x30, true, R::Hex), "-0x30");
1177+
assert_eq!(fmt_int(-0x30, false, R::Hex), "0xffffffd0");
1178+
assert_eq!(fmt_int(-0b100, true, R::Bin), "-0b100");
1179+
1180+
assert_eq!(fmt_int(0, true, R::Bool), "false");
1181+
assert_eq!(fmt_int(0, false, R::Bool), "false");
1182+
assert_eq!(fmt_int(1, true, R::Bool), "true");
1183+
assert_eq!(fmt_int(1, false, R::Bool), "true");
1184+
assert_eq!(fmt_int(2, true, R::Bool), "2");
1185+
assert_eq!(fmt_int(2, false, R::Bool), "0x2");
1186+
assert_eq!(fmt_int(-2, true, R::Bool), "-2");
1187+
assert_eq!(fmt_int(-2, false, R::Bool), "0xfffffffe");
1188+
}
11391189
}
1190+

src/formats/anm/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -686,7 +686,7 @@ fn format_to_meta(format_num: u32) -> Meta {
686686
}
687687

688688
fn colorkey_to_meta(colorkey: u32) -> impl ToMeta {
689-
ast::Expr::LitInt { value: colorkey as i32, radix: ast::IntRadix::Hex }
689+
ast::Expr::LitInt { value: colorkey as i32, format: ast::IntFormat::HEX }
690690
}
691691

692692
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]

src/llir/raise/early.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ fn early_raise_intrinsics(
181181
fn raise_mask(value: raw::ParamMask) -> ast::Expr {
182182
ast::Expr::LitInt {
183183
value: value.into(),
184-
radix: ast::IntRadix::Bin,
184+
format: ast::IntFormat::BIN,
185185
}
186186
}
187187

@@ -192,7 +192,7 @@ fn raise_nargs(value: raw::ArgCount) -> ast::Expr {
192192
fn raise_pop(value: raw::StackPop) -> ast::Expr {
193193
ast::Expr::LitInt {
194194
value: value.into(),
195-
radix: ast::IntRadix::Hex,
195+
format: ast::IntFormat::HEX,
196196
}
197197
}
198198

@@ -698,7 +698,7 @@ impl AtomRaiser<'_, '_> {
698698
},
699699

700700
| ArgEncoding::Color
701-
=> Ok(ast::Expr::LitInt { value: raw.expect_int(), radix: ast::IntRadix::Hex }),
701+
=> Ok(ast::Expr::LitInt { value: raw.expect_int(), format: ast::IntFormat::HEX }),
702702

703703
| ArgEncoding::Float
704704
=> Ok(ast::Expr::from(raw.expect_float())),
@@ -721,7 +721,7 @@ impl AtomRaiser<'_, '_> {
721721

722722
| Err(IllegalOffset) => {
723723
emitter.emit(warning!("invalid offset in a jump instruction")).ignore();
724-
Ok(ast::Expr::LitInt { value: raw.expect_int(), radix: ast::IntRadix::SignedHex })
724+
Ok(ast::Expr::LitInt { value: raw.expect_int(), format: ast::IntFormat::SIGNED_HEX })
725725
},
726726
},
727727
}

src/parse/lalrparser.lalrpop

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -612,7 +612,7 @@ ExprTerm: ast::Expr = {
612612
<var:Sp<Var>> <op:Sp<OpXcrement>>
613613
=> ast::Expr::XcrementOp { var, op, order: ast::XcrementOpOrder::Post },
614614

615-
<value:LitIntUnsigned> => ast::Expr::LitInt { value, radix: ast::IntRadix::Dec },
615+
<value:LitIntUnsigned> => ast::Expr::LitInt { value, format: ast::IntFormat::SIGNED },
616616

617617
<value:LitFloatUnsigned> => ast::Expr::LitFloat { value },
618618

tests/compile-fail/integration__integration__type_check__diffswitch__missing_first.snap

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,4 @@ error: unexpected token `:`
99
│ ^ unexpected token
1010
1111
=
12-
Expected one of "!", "$", "%", "(", "++", "-", "--", "REG", "_S", "_f", "anim", "case", "cos", "default", "ecli", "entry", "float", "int", "mapfile", "offsetof", "script", "sin", "sqrt", "timeof", "~", FLOAT, FLOAT_RAD, IDENT, INSTR, INT or STRING
13-
14-
12+
Expected one of "!", "$", "%", "(", "++", "-", "--", "REG", "_S", "_f", "acos", "anim", "asin", "atan", "case", "cos", "default", "ecli", "entry", "float", "int", "mapfile", "offsetof", "script", "sin", "sqrt", "tan", "timeof", "~", FLOAT, FLOAT_RAD, IDENT, INSTR, INT or STRING

0 commit comments

Comments
 (0)