Better support for 64 bit numbers (#44)

This commit is contained in:
Borys Levytskyi
2023-05-06 14:31:07 +03:00
committed by GitHub
parent 4806025618
commit bd5b748a64
25 changed files with 336 additions and 345 deletions

View File

@@ -1,5 +1,7 @@
import { ScalarOperand, ListOfNumbersExpression, BitwiseOperationExpression, ExpressionOperand } from '../expression';
import { ExpressionInputItem, ExpressionInput } from '../expression-interfaces';
import { ScalarExpression, ListOfNumbersExpression, BitwiseOperationExpression, OperatorExpression } from '../expression';
import { Expression, ExpressionInput } from '../expression-interfaces';
import calc from '../../core/calc';
import formatter from '../../core/formatter';
type Config = {
emphasizeBytes: boolean;
@@ -9,7 +11,7 @@ type Config = {
type ExpressionItemModel = {
sign: string;
css: string;
expressionItem: ExpressionInputItem;
expression: Expression;
allowFlipBits: boolean;
label: string;
}
@@ -30,28 +32,28 @@ export default class BitwiseExpressionViewModel {
static buildListOfNumbers(expr : ListOfNumbersExpression, config : Config) {
var model = new BitwiseExpressionViewModel(config);
expr.numbers.forEach(op => model.addOperandRow(op));
model.maxNumberOfBits = BitwiseExpressionViewModel.getNumberOfBits(model.maxNumberOfBits, model.emphasizeBytes);
expr.numbers.forEach(op => model.addScalarRow(op));
model.maxNumberOfBits = BitwiseExpressionViewModel.applyEmphasizeBytes(model.maxNumberOfBits, model.emphasizeBytes);
return model;
}
static buildMultiple (expr : BitwiseOperationExpression, config : Config) {
var op = expr.expressionItems[0],
i = 0, len = expr.expressionItems.length,
var op = expr.children[0],
i = 0, len = expr.children.length,
ex, m = new BitwiseExpressionViewModel(config);
var prev : ScalarOperand | null = null;
var prev : ScalarExpression | null = null;
for (;i<len;i++) {
ex = expr.expressionItems[i];
if(ex instanceof ScalarOperand) {
m.addOperandRow(ex);
ex = expr.children[i];
if(ex instanceof ScalarExpression) {
m.addScalarRow(ex);
prev = ex;
continue;
}
var eo = ex as ExpressionOperand;
var eo = ex as OperatorExpression;
// If it a single NOT expression
if(eo.isNotExpression) {
@@ -61,86 +63,88 @@ export default class BitwiseExpressionViewModel {
prev = notResult;
}
else if(eo.isShiftExpression){
prev = eo.evaluate(prev as ScalarOperand);
prev = eo.evaluate(prev as ScalarExpression);
m.addShiftExpressionResultRow(eo, prev);
} else {
prev = eo.evaluate(prev as ScalarOperand);
prev = eo.evaluate(prev as ScalarExpression);
m.addExpressionOperandRow(eo);
m.addExpressionResultRow(prev);
}
}
m.maxNumberOfBits = BitwiseExpressionViewModel.getNumberOfBits(m.maxNumberOfBits, m.emphasizeBytes);
m.maxNumberOfBits = BitwiseExpressionViewModel.applyEmphasizeBytes(m.maxNumberOfBits, m.emphasizeBytes);
return m;
};
static buildNot (expression: ExpressionOperand, config : Config) {
static buildNot (expression: OperatorExpression, config : Config) {
var m = new BitwiseExpressionViewModel(config);
m.addExpressionOperandRow(expression);
m.addExpressionResultRow(expression.evaluate());
m.maxNumberOfBits = BitwiseExpressionViewModel.getNumberOfBits(m.maxNumberOfBits, m.emphasizeBytes);
m.maxNumberOfBits = BitwiseExpressionViewModel.applyEmphasizeBytes(m.maxNumberOfBits, m.emphasizeBytes);
return m;
};
addOperandRow(operand: ScalarOperand) {
this.maxNumberOfBits = Math.max(operand.getLengthInBits(), this.maxNumberOfBits);
addScalarRow(expr: ScalarExpression) {
const bits = calc.numberOfBitsDisplayed(expr.value);
this.maxNumberOfBits = Math.max(bits, this.maxNumberOfBits);
this.items.push({
sign:'',
css: '',
expressionItem: operand,
expression: expr,
allowFlipBits: this.allowFlipBits,
label: ''
});
};
addExpressionOperandRow(expression: ExpressionOperand) {
const resultNumber = expression.isNotExpression ? expression.evaluate() : expression.getUnderlyingOperand();
this.maxNumberOfBits = Math.max(resultNumber.getLengthInBits(), this.maxNumberOfBits);
addExpressionOperandRow(expr: OperatorExpression) {
const resultNumber = expr.isNotExpression ? expr.evaluate() : expr.getUnderlyingScalarOperand();
const bits = calc.numberOfBitsDisplayed(resultNumber.value);
this.maxNumberOfBits = Math.max(bits, this.maxNumberOfBits);
this.items.push({
sign: expression.sign,
sign: expr.sign,
css: '',
label: this.getLabel(resultNumber),
expressionItem: expression.operand,
expression: expr.operand,
allowFlipBits: this.allowFlipBits
});
};
addShiftExpressionResultRow(expression : ExpressionOperand, resultOperand : ScalarOperand) {
this.maxNumberOfBits = Math.max(resultOperand.getLengthInBits(), this.maxNumberOfBits);
addShiftExpressionResultRow(expr : OperatorExpression, resultExpr : ScalarExpression) {
const bits = calc.numberOfBitsDisplayed(resultExpr.value);
this.maxNumberOfBits = Math.max(bits, this.maxNumberOfBits);
const child = expr.operand.getUnderlyingScalarOperand();
this.items.push({
sign: expression.sign + expression.operand.toString(),
sign: expr.sign + formatter.numberToString(child.value, child.base),
css: 'expression-result',
expressionItem: resultOperand,
expression: resultExpr,
allowFlipBits: false,
label: ''
});
};
addExpressionResultRow(operand : ScalarOperand) {
this.maxNumberOfBits = Math.max(operand.getLengthInBits(), this.maxNumberOfBits);
addExpressionResultRow(expr : ScalarExpression) {
const bits = calc.numberOfBitsDisplayed(expr.value);
this.maxNumberOfBits = Math.max(bits, this.maxNumberOfBits);
this.items.push({
sign:'=',
css: 'expression-result',
expressionItem: operand,
expression: expr,
allowFlipBits: false,
label: '',
});
};
getLabel (op: ScalarOperand) : string {
if(op.base == 'bin') {
return op.toString("dec");
}
getLabel (op: ScalarExpression) : string {
return op.toString();
return formatter.numberToString(op.value, op.base === 'bin' ? 'dec' : op.base)
}
// TODO: move this method elsewhere. It is also used in LisOfNumbersExpressionView.js
static getNumberOfBits = function (bits : number, emphasizeBytes : boolean) : number {
static applyEmphasizeBytes (bits : number, emphasizeBytes : boolean) : number {
if(emphasizeBytes && bits % 8 != 0) {
if(bits < 8) {
return 8;

View File

@@ -2,8 +2,8 @@ import React from 'react';
import formatter from '../../core/formatter';
import BinaryStringView, { FlipBitEventArg } from '../../core/components/BinaryString';
import BitwiseExpressionViewModel from './BitwiseExpressionModel';
import { ExpressionInput, ExpressionInputItem } from '../expression-interfaces';
import { ExpressionOperand, ScalarOperand } from '../expression';
import { ExpressionInput, Expression } from '../expression-interfaces';
import { OperatorExpression, ScalarExpression } from '../expression';
type BitwiseOperationExpressionViewProps = {
expression: ExpressionInput;
@@ -41,7 +41,7 @@ export default class BitwiseOperationExpressionView extends React.Component<Bitw
sign={itm.sign}
css={itm.css}
allowFlipBits={itm.allowFlipBits}
expressionItem={itm.expressionItem}
expressionItem={itm.expression}
emphasizeBytes={this.props.emphasizeBytes}
maxNumberOfBits={model.maxNumberOfBits}
onBitFlipped={() => this.onBitFlipped()} />);
@@ -59,7 +59,7 @@ type ExpressionRowProps = {
maxNumberOfBits: number,
emphasizeBytes: boolean,
allowFlipBits: boolean,
expressionItem: ExpressionInputItem,
expressionItem: Expression,
onBitFlipped: any
}
@@ -81,46 +81,48 @@ class ExpressionRow extends React.Component<ExpressionRowProps> {
allowFlipBits={allowFlipBits}
onFlipBit={args => this.flipBit(args)}/>
</td>
<td className="other">{this.getOther()}</td>
<td className="other">{this.getAlternative()}</td>
</tr>;;
}
getBinaryString() : string {
var binary = this.props.expressionItem.evaluate().toBinaryString();
return binary;
var v = this.props.expressionItem.evaluate();
return formatter.numberToString(v.value, 'bin');
}
getLabel(): string {
// For expressions like |~2
// TODO: find a better way...
if(this.props.expressionItem.isExpression) {
const ex = this.props.expressionItem as ExpressionOperand;
return ex.sign + this.getLabelString(ex.getUnderlyingOperand());
if(this.props.expressionItem.isOperator) {
const ex = this.props.expressionItem as OperatorExpression;
return ex.sign + this.getLabelString(ex.getUnderlyingScalarOperand());
}
return this.getLabelString(this.props.expressionItem.getUnderlyingOperand());
return this.getLabelString(this.props.expressionItem.getUnderlyingScalarOperand());
}
getOther() {
getAlternative() {
if(this.props.expressionItem.isExpression) {
const ex = this.props.expressionItem as ExpressionOperand;
const op = ex.evaluate();
if(this.props.expressionItem.isOperator) {
const ex = this.props.expressionItem as OperatorExpression;
const res = ex.evaluate();
return op.toString();
return formatter.numberToString(res.value, res.base);
}
return this.props.expressionItem.evaluate().toOtherKindString();
const v = this.props.expressionItem.evaluate();
const altBase = formatter.getAlternativeBase(v.base);
return formatter.numberToString(v.value, altBase);
}
getLabelString (op: ScalarOperand) : string {
return op.toString(op.base == 'bin' ? 'dec' : op.base);
getLabelString (op: ScalarExpression) : string {
return formatter.numberToString(op.value, op.base == 'bin' ? 'dec' : op.base);
}
flipBit(args: FlipBitEventArg) {
const op = this.props.expressionItem.getUnderlyingOperand();
const op = this.props.expressionItem.getUnderlyingScalarOperand();
const { index, binaryString } = args;
var arr = binaryString.split('');