Skip to content

Commit

Permalink
Decompiler uses now the new statement/function meta data to improve o…
Browse files Browse the repository at this point in the history
…utput.

It should now be better to determine boolean & flag parameters. Flags already worked to some degree - removed the old solution.
  • Loading branch information
mkrueger committed Jan 26, 2025
1 parent 09de1ad commit 6244af8
Show file tree
Hide file tree
Showing 12 changed files with 189 additions and 497 deletions.
385 changes: 52 additions & 333 deletions crates/icy_board_engine/src/ast/constant.rs

Large diffs are not rendered by default.

149 changes: 0 additions & 149 deletions crates/icy_board_engine/src/decompiler/constant_scan_visitor.rs

This file was deleted.

38 changes: 33 additions & 5 deletions crates/icy_board_engine/src/decompiler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ use crate::{

use self::evaluation_visitor::OptimizationVisitor;

pub mod constant_scan_visitor;
pub mod evaluation_visitor;
pub mod reconstruct;
pub mod relabel_visitor;
Expand Down Expand Up @@ -292,7 +291,21 @@ impl Decompiler {
}
PPEExpr::PredefinedFunctionCall(f, args) => FunctionCallExpression::create_empty_expression(
IdentifierExpression::create_empty_expression(unicase::Ascii::new(f.name.to_string())),
args.iter().map(|e| self.decompile_expression(e)).collect(),
args.iter()
.enumerate()
.map(|(i, e)| {
let expr = self.decompile_expression(e);
if let Some(args) = &f.args {
if let Some(arg) = args.get(i) {
if arg.arg_type == VariableType::Boolean {
return Statement::try_boolean_conversion(&expr);
}
return arg.flags.convert_expr(expr);
}
}
expr
})
.collect(),
),
PPEExpr::FunctionCall(f, args) => FunctionCallExpression::create_empty_expression(
IdentifierExpression::create_empty_expression(self.get_variable_name(*f)),
Expand All @@ -319,9 +332,24 @@ impl Decompiler {
PPECommand::ProcedureCall(p, args) => {
ProcedureCallStatement::create_empty_statement(self.get_variable_name(*p), args.iter().map(|e| self.decompile_expression(e)).collect())
}
PPECommand::PredefinedCall(p, args) => {
PredefinedCallStatement::create_empty_statement(p, args.iter().map(|e| self.decompile_expression(e)).collect())
}
PPECommand::PredefinedCall(p, args) => PredefinedCallStatement::create_empty_statement(
p,
args.iter()
.enumerate()
.map(|(i, e)| {
let expr = self.decompile_expression(e);
if let Some(args) = &p.args {
if let Some(arg) = args.get(i) {
if arg.arg_type == VariableType::Boolean {
return Statement::try_boolean_conversion(&expr);
}
return arg.flags.convert_expr(expr);
}
}
expr
})
.collect(),
),
PPECommand::Let(left, expr) => {
let (identifier, arguments) = match self.decompile_expression(left) {
Expression::FunctionCall(f) => (unicase::Ascii::new(f.get_expression().to_string()), f.get_arguments().clone()),
Expand Down
3 changes: 1 addition & 2 deletions crates/icy_board_engine/src/decompiler/reconstruct/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::{

use self::while_do::scan_do_while;

use super::{constant_scan_visitor::ConstantScanVisitor, rename_visitor::RenameScanVisitor, Ast, Expression, Statement};
use super::{rename_visitor::RenameScanVisitor, Ast, Expression, Statement};

pub mod for_next;
mod if_else;
Expand Down Expand Up @@ -205,7 +205,6 @@ pub fn strip_unused_labels(ast: &mut Ast) -> Ast {
pub fn finish_ast(prg: &mut Ast) -> Ast {
let mut scanner = RenameScanVisitor::default();
prg.visit(&mut scanner);
let prg = prg.visit_mut(&mut ConstantScanVisitor::default());
let mut renamer = RenameVisitor::new(scanner.rename_map);
prg.visit_mut(&mut renamer)
}
Expand Down
98 changes: 96 additions & 2 deletions crates/icy_board_engine/src/executable/smt_op_codes.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
use std::fmt::Display;

use crate::ast::{
constant::{BuiltinConst, BUILTIN_CONSTS},
BinOp, BinaryExpression, Constant, ConstantExpression, Expression,
};

use super::VariableType;

#[derive(Debug, Clone, Copy, PartialEq)]
Expand Down Expand Up @@ -306,6 +311,95 @@ pub enum ArgumentDefinitionFlags {

/// CRC_FILE = true, CRC_FALSE = false
Crc32,

/// F_MW, F_SYS, F_SEL, F_EXP, F_REG
ConfFlags,
}
lazy_static::lazy_static! {
pub static ref DISPLAY_FLAGS_CONST: Vec<BuiltinConst> = BUILTIN_CONSTS.iter().cloned().filter(|c| c.name == "GRAPH" || c.name == "SEC" || c.name == "LANG").collect();

pub static ref START_DISPLAY_FLAGS_CONST: Vec<BuiltinConst> = BUILTIN_CONSTS.iter().cloned().filter(|c| c.name == "NC" || c.name == "FNS" || c.name == "FCL").collect();

pub static ref FILE_ACCESS_MODE_CONST: Vec<BuiltinConst> = BUILTIN_CONSTS.iter().cloned().filter(|c| c.name == "O_RD" || c.name == "O_WR" || c.name == "O_RW").collect();

pub static ref FILE_SHARE_MODE_CONST: Vec<BuiltinConst> = BUILTIN_CONSTS.iter().cloned().filter(|c| c.name == "S_DN" || c.name == "S_DR" || c.name == "S_DW" || c.name == "S_DB").collect();

pub static ref INPUT_FLAGS_CONST: Vec<BuiltinConst> = BUILTIN_CONSTS.iter().cloned().filter(|c| c.name == "ECHODOTS" || c.name == "FIELDLEN" || c.name == "GUIDE" || c.name == "UPCASE" || c.name == "STACKED" || c.name == "ERASELINE" || c.name == "NEWLINE" || c.name == "LFBEFORE" || c.name == "LFAFTER" || c.name == "WORDWRAP" || c.name == "NOCLEAR" || c.name == "HIGHASCII" || c.name == "AUTO" || c.name == "YESNO").collect();

pub static ref DISPLAY_TEXT_FLAGS_CONST: Vec<BuiltinConst> = BUILTIN_CONSTS.iter().cloned().filter(|c| c.name == "NEWLINE" || c.name == "LFBEFORE" || c.name == "LFAFTER" || c.name == "BELL" || c.name == "LOGIT" || c.name == "LOGITLEFT").collect();

pub static ref SEEK_POSITION_CONST: Vec<BuiltinConst> = BUILTIN_CONSTS.iter().cloned().filter(|c| c.name == "SEEK_SET" || c.name == "SEEK_CUR" || c.name == "SEEK_END").collect();

pub static ref FIDO_FLAGS_CONST: Vec<BuiltinConst> = BUILTIN_CONSTS.iter().cloned().filter(|c| c.name == "NORMAL" || c.name == "CRASH" || c.name == "HOLD").collect();

pub static ref CRC32_CONST: Vec<BuiltinConst> = BUILTIN_CONSTS.iter().cloned().filter(|c| c.name == "CRC_FILE" || c.name == "CRC_STR").collect();

pub static ref CONFFLAG_CONST: Vec<BuiltinConst> = BUILTIN_CONSTS.iter().cloned().filter(|c| c.name == "F_MW" || c.name == "F_SYS" || c.name == "F_SEL" || c.name == "F_EXP" || c.name == "F_REG").collect();

}

impl ArgumentDefinitionFlags {
pub fn convert_expr(&self, expr: crate::ast::Expression) -> crate::ast::Expression {
match self {
ArgumentDefinitionFlags::None => expr,
ArgumentDefinitionFlags::DisplayFileFlags => replace_constants(expr, &DISPLAY_FLAGS_CONST),
ArgumentDefinitionFlags::StartDisplayFlags => replace_constants(expr, &START_DISPLAY_FLAGS_CONST),
ArgumentDefinitionFlags::FileAccessMode => replace_constants(expr, &FILE_ACCESS_MODE_CONST),
ArgumentDefinitionFlags::FileShareMode => replace_constants(expr, &FILE_SHARE_MODE_CONST),
ArgumentDefinitionFlags::InputFlags => replace_constants(expr, &INPUT_FLAGS_CONST),
ArgumentDefinitionFlags::DisplayTextFlags => replace_constants(expr, &DISPLAY_TEXT_FLAGS_CONST),
ArgumentDefinitionFlags::SeekPosition => replace_constants(expr, &SEEK_POSITION_CONST),
ArgumentDefinitionFlags::FidoFlags => replace_constants(expr, &FIDO_FLAGS_CONST),
ArgumentDefinitionFlags::Crc32 => replace_constants(expr, &CRC32_CONST),
ArgumentDefinitionFlags::ConfFlags => replace_constants(expr, &CONFFLAG_CONST),
}
}
}

fn replace_constants(expr: crate::ast::Expression, consts: &'static [BuiltinConst]) -> crate::ast::Expression {
match &expr {
Expression::Const(c) => {
match c.get_constant_value() {
&Constant::Integer(value) => {
for c in consts {
if c.value == value {
return ConstantExpression::create_empty_expression(Constant::Builtin(c));
}
}
let mut used_consts = Vec::new();
let mut cur_val = value;
for c in consts {
if c.value & cur_val == c.value {
used_consts.push(ConstantExpression::create_empty_expression(Constant::Builtin(c)));
cur_val &= !c.value;
}
}
if used_consts.is_empty() {
if value == 0 {
// DEFS
return ConstantExpression::create_empty_expression(Constant::Builtin(&BUILTIN_CONSTS[15]));
}
return expr;
}
let mut last = used_consts.pop().unwrap();
while !used_consts.is_empty() {
last = BinaryExpression::create_empty_expression(BinOp::Add, used_consts.pop().unwrap(), last);
}
return last;
}
_ => {}
}
}
Expression::Binary(bin_op) => {
return BinaryExpression::create_empty_expression(
bin_op.get_op(),
replace_constants(bin_op.get_left_expression().clone(), consts),
replace_constants(bin_op.get_right_expression().clone(), consts),
);
}
_ => {}
}
expr
}

#[derive(Debug, PartialEq)]
Expand Down Expand Up @@ -503,7 +597,7 @@ lazy_static::lazy_static! {
opcode: OpCode::CONFFLAG,
args: Some(vec![
ArgumentDefinition::new("conf", VariableType::Integer),
ArgumentDefinition::new("flags", VariableType::Integer)
ArgumentDefinition::new_flags("flags", ArgumentDefinitionFlags::ConfFlags)
]),
sig: StatementSignature::ArgumentsWithVariable(0, 2),
},
Expand All @@ -513,7 +607,7 @@ lazy_static::lazy_static! {
opcode: OpCode::CONFUNFLAG,
args: Some(vec![
ArgumentDefinition::new("conf", VariableType::Integer),
ArgumentDefinition::new("flags", VariableType::Integer)
ArgumentDefinition::new_flags("flags", ArgumentDefinitionFlags::ConfFlags)
]),
sig: StatementSignature::ArgumentsWithVariable(0, 2),
},
Expand Down
4 changes: 2 additions & 2 deletions crates/ppld/test_data/ansigal.pps
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ BOOLEAN BOOL001
CLS
ANSIPOS 1, 1
PRINT "@POFF@"
DISPFILE PPEPATH() + "ansigal.pcb", 0
DISPFILE PPEPATH() + "ansigal.pcb", DEFS
PROC002(1, 1)
PROC004(1)
END
Expand Down Expand Up @@ -268,7 +268,7 @@ PROCEDURE PROC004(INTEGER PAR004)
PROC006(STR006 + STR002[LOC008])
PRINT "@X07"
CLS
DISPFILE PPEPATH() + "ansigal.pcb", 0
DISPFILE PPEPATH() + "ansigal.pcb", DEFS
PROC002(PAR004, 1)
PROC004(PAR004)
ENDIF
Expand Down
Binary file added crates/ppld/test_data/crc32.ppe
Binary file not shown.
1 change: 1 addition & 0 deletions crates/ppld/test_data/crc32.pps
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
PRINTLN CRC32(CRC_STR, "FOO_BAR")
2 changes: 1 addition & 1 deletion crates/ppld/test_data/log.pps
Original file line number Diff line number Diff line change
@@ -1 +1 @@
LOG "FooBar", 0
LOG "FooBar", FALSE
2 changes: 1 addition & 1 deletion crates/ppld/test_data/message.pps
Original file line number Diff line number Diff line change
@@ -1 +1 @@
MESSAGE 1, "to", "from", "subject", "N", 0, 1, 1, "MESSAGE_TEXT_FILE"
MESSAGE 1, "to", "from", "subject", "N", 0, TRUE, TRUE, "MESSAGE_TEXT_FILE"
2 changes: 1 addition & 1 deletion crates/ppld/test_data/scrtext.pps
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
STRING STR001
STR001=SCRTEXT(1, 2, 5, 1)
STR001=SCRTEXT(1, 2, 5, TRUE)
2 changes: 1 addition & 1 deletion crates/ppld/test_data/shell.pps
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
INTEGER INT001
SHELL 1, INT001, "file.exe", "args"
SHELL TRUE, INT001, "file.exe", "args"

0 comments on commit 6244af8

Please sign in to comment.