Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/ast/meta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,10 @@ impl ToMeta for f32 {
fn to_meta(&self) -> Meta { Meta::Scalar(sp!((*self).into())) }
}
impl ToMeta for bool {
fn to_meta(&self) -> Meta { Meta::Scalar(sp!(ast::Expr::LitInt { value: *self as i32, radix: ast::IntRadix::Bool })) }
fn to_meta(&self) -> Meta { Meta::Scalar(sp!(ast::Expr::LitInt {
value: *self as i32,
format: ast::IntFormat::BOOL,
}))}
}
impl ToMeta for String {
fn to_meta(&self) -> Meta { Meta::Scalar(sp!(self.to_owned().into())) }
Expand Down
27 changes: 21 additions & 6 deletions src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -454,8 +454,8 @@ pub enum Expr {
LitInt {
value: raw::LangInt,
/// A hint to the formatter on how it should write the integer.
/// (may not necessarily represent the original radix of a parsed token)
radix: IntRadix,
/// (not meaningful when parsing)
format: IntFormat,
},
LitFloat { value: raw::LangFloat },
LitString(LitString),
Expand All @@ -469,14 +469,29 @@ pub enum Expr {
},
}


#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct IntFormat {
pub signed: bool,
pub radix: IntRadix,
}

impl IntFormat {
pub const UNSIGNED: IntFormat = IntFormat { signed: false, radix: IntRadix::Dec };
pub const SIGNED: IntFormat = IntFormat { signed: true, radix: IntRadix::Dec };
pub const HEX: IntFormat = IntFormat { signed: false, radix: IntRadix::Hex };
pub const BIN: IntFormat = IntFormat { signed: false, radix: IntRadix::Bin };
pub const BOOL: IntFormat = IntFormat { signed: true, radix: IntRadix::Bool };
/// Used to decompile `jmp` in function syntax.
pub const SIGNED_HEX: IntFormat = IntFormat { signed: true, radix: IntRadix::Hex };
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum IntRadix {
/// Display as decimal.
Dec,
/// Display as hexadecimal, with an `0x` prefix.
Hex,
/// Display as potentially negative hexadecimal, with an `0x` prefix.
SignedHex,
/// Display as binary, with an `0b` prefix.
Bin,
/// Use `true` and `false` if the value is `1` or `0`. Otherwise, fall back to decimal.
Expand Down Expand Up @@ -850,7 +865,7 @@ string_enum! {
}

impl From<raw::LangInt> for Expr {
fn from(value: raw::LangInt) -> Expr { Expr::LitInt { value, radix: IntRadix::Dec } }
fn from(value: raw::LangInt) -> Expr { Expr::LitInt { value, format: IntFormat::SIGNED } }
}
impl From<raw::LangFloat> for Expr {
fn from(value: raw::LangFloat) -> Expr { Expr::LitFloat { value } }
Expand Down Expand Up @@ -1269,7 +1284,7 @@ macro_rules! generate_visitor_stuff {
Expr::XcrementOp { op: _, order: _, var } => {
v.visit_var(var);
},
Expr::LitInt { value: _, radix: _ } => {},
Expr::LitInt { value: _, format: _ } => {},
Expr::LitFloat { value: _ } => {},
Expr::LitString(_s) => {},
Expr::LabelProperty { .. } => {},
Expand Down
65 changes: 58 additions & 7 deletions src/fmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -899,13 +899,36 @@ impl Format for ast::Expr {
ast::Expr::XcrementOp { order: ast::XcrementOpOrder::Pre, op, var } => out.fmt((op, var)),
ast::Expr::XcrementOp { order: ast::XcrementOpOrder::Post, op, var } => out.fmt((var, op)),
ast::Expr::EnumConst { enum_name, ident } => out.fmt((enum_name, ".", ident)),
ast::Expr::LitInt { value: 0, radix: ast::IntRadix::Bool } => out.fmt("false"),
ast::Expr::LitInt { value: 1, radix: ast::IntRadix::Bool } => out.fmt("true"),
ast::Expr::LitInt { value, radix: ast::IntRadix::Bool } => out.fmt(value),
ast::Expr::LitInt { value, radix: ast::IntRadix::Dec } => out.fmt(value),
ast::Expr::LitInt { value, radix: ast::IntRadix::Hex } => out.fmt(format_args!("{:#x}", value)),
ast::Expr::LitInt { value, radix: ast::IntRadix::SignedHex } => out.fmt(format_args!("{:#x}", SignedRadix(*value))),
ast::Expr::LitInt { value, radix: ast::IntRadix::Bin } => out.fmt(format_args!("{:#b}", value)),
ast::Expr::LitInt { value, format } => match format {
// These are the decimal formats
&ast::IntFormat::SIGNED => out.fmt(value),
&ast::IntFormat::UNSIGNED => {
out.fmt(format_args!("{}", *value as u32))
},

&ast::IntFormat { radix: ast::IntRadix::Hex, signed } => {
match signed {
false => out.fmt(format_args!("{:#x}", value)),
true => out.fmt(format_args!("{:#x}", SignedRadix(*value))),
}
},

&ast::IntFormat { radix: ast::IntRadix::Bin, signed } => {
match signed {
false => out.fmt(format_args!("{:#b}", value)),
true => out.fmt(format_args!("{:#b}", SignedRadix(*value))),
}
},

&ast::IntFormat { radix: ast::IntRadix::Bool, signed } => {
match (value, signed) {
(0, _) => out.fmt("false"),
(1, _) => out.fmt("true"),
(_, true) => out.fmt(value),
(_, false) => out.fmt(format_args!("{:#x}", *value as u32)),
}
},
},
ast::Expr::LitFloat { value } => out.fmt(value),
ast::Expr::LitString(x) => out.fmt(x),
ast::Expr::LabelProperty { label, keyword } => out.fmt((keyword, "(", label, ")")),
Expand Down Expand Up @@ -1136,4 +1159,32 @@ mod tests {
assert!(reformat::<ast::ScriptFile>(3, r#"meta { x: 25 }"#).ends_with("\n"));
assert!(reformat::<ast::ScriptFile>(9999, r#" script lol { nop(); }"#).ends_with("\n"));
}

#[test]
fn integer_formats() {
use ast::IntRadix as R;

fn fmt_int(value: i32, signed: bool, radix: R) -> String {
stringify(&ast::Expr::LitInt {
value,
format: ast::IntFormat { signed, radix }
})
}

assert_eq!(fmt_int(20, true, R::Dec), "20");
assert_eq!(fmt_int(-20, true, R::Dec), "-20");
assert_eq!(fmt_int(-0x30, true, R::Hex), "-0x30");
assert_eq!(fmt_int(-0x30, false, R::Hex), "0xffffffd0");
assert_eq!(fmt_int(-0b100, true, R::Bin), "-0b100");

assert_eq!(fmt_int(0, true, R::Bool), "false");
assert_eq!(fmt_int(0, false, R::Bool), "false");
assert_eq!(fmt_int(1, true, R::Bool), "true");
assert_eq!(fmt_int(1, false, R::Bool), "true");
assert_eq!(fmt_int(2, true, R::Bool), "2");
assert_eq!(fmt_int(2, false, R::Bool), "0x2");
assert_eq!(fmt_int(-2, true, R::Bool), "-2");
assert_eq!(fmt_int(-2, false, R::Bool), "0xfffffffe");
}
}

2 changes: 1 addition & 1 deletion src/formats/anm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -686,7 +686,7 @@ fn format_to_meta(format_num: u32) -> Meta {
}

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

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
Expand Down
8 changes: 4 additions & 4 deletions src/llir/raise/early.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ fn early_raise_intrinsics(
fn raise_mask(value: raw::ParamMask) -> ast::Expr {
ast::Expr::LitInt {
value: value.into(),
radix: ast::IntRadix::Bin,
format: ast::IntFormat::BIN,
}
}

Expand All @@ -192,7 +192,7 @@ fn raise_nargs(value: raw::ArgCount) -> ast::Expr {
fn raise_pop(value: raw::StackPop) -> ast::Expr {
ast::Expr::LitInt {
value: value.into(),
radix: ast::IntRadix::Hex,
format: ast::IntFormat::HEX,
}
}

Expand Down Expand Up @@ -698,7 +698,7 @@ impl AtomRaiser<'_, '_> {
},

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

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

| Err(IllegalOffset) => {
emitter.emit(warning!("invalid offset in a jump instruction")).ignore();
Ok(ast::Expr::LitInt { value: raw.expect_int(), radix: ast::IntRadix::SignedHex })
Ok(ast::Expr::LitInt { value: raw.expect_int(), format: ast::IntFormat::SIGNED_HEX })
},
},
}
Expand Down
2 changes: 1 addition & 1 deletion src/parse/lalrparser.lalrpop
Original file line number Diff line number Diff line change
Expand Up @@ -612,7 +612,7 @@ ExprTerm: ast::Expr = {
<var:Sp<Var>> <op:Sp<OpXcrement>>
=> ast::Expr::XcrementOp { var, op, order: ast::XcrementOpOrder::Post },

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

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,4 @@ error: unexpected token `:`
│ ^ unexpected token
=
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


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