mirror of
https://github.com/BorysLevytskyi/BitwiseCmd.git
synced 2026-01-26 05:34:13 +01:00
Allow to switch a number sign (#47)
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { Expression, ExpressionElement } from "./expression-interfaces";
|
||||
|
||||
export default class BitwiseOperationExpression implements Expression {
|
||||
export default class BitwiseOperation implements Expression {
|
||||
|
||||
expressionString: string;
|
||||
children: ExpressionElement[];
|
||||
@@ -1,5 +1,5 @@
|
||||
import BitwiseOperator from "./BitwiseOperator";
|
||||
import { ScalarValue } from "./expression";
|
||||
import Operator from "./Operator";
|
||||
import { Operand } from "./expression";
|
||||
import { ExpressionElement } from "./expression-interfaces";
|
||||
import { type } from "os";
|
||||
import { InputType } from "zlib";
|
||||
|
||||
12
src/expression/ListOfNumbers.test.ts
Normal file
12
src/expression/ListOfNumbers.test.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import Operand from "./Operand";
|
||||
import ListOfNumbers from "./ListOfNumbers";
|
||||
import { numberParser } from "./numberParser";
|
||||
|
||||
it('calculates max bits length', () => {
|
||||
const v1 = new Operand(numberParser.parse("10").value);
|
||||
const v2 = new Operand(numberParser.parse("0xabef").value);
|
||||
const v3 = new Operand(numberParser.parse("0b01010").value);
|
||||
|
||||
var expr = new ListOfNumbers("10 0xabef 0b01010", [v1, v2, v3])
|
||||
expect(expr.maxBitsLength).toBe(16);
|
||||
});
|
||||
@@ -1,13 +1,13 @@
|
||||
import calc from "../core/calc";
|
||||
import ScalarValue from "./ScalarValue";
|
||||
import Operand from "./Operand";
|
||||
import { Expression, ExpressionElement } from "./expression-interfaces";
|
||||
|
||||
export default class ListOfNumbersExpression implements Expression {
|
||||
children: ScalarValue[];
|
||||
export default class ListOfNumbers implements Expression {
|
||||
children: Operand[];
|
||||
expressionString: string;
|
||||
maxBitsLength: number;
|
||||
|
||||
constructor(expressionString: string, numbers: ScalarValue[]) {
|
||||
constructor(expressionString: string, numbers: Operand[]) {
|
||||
this.expressionString = expressionString;
|
||||
this.children = numbers;
|
||||
this.maxBitsLength = numbers.map(n => calc.numberOfBitsDisplayed(n.value)).reduce((n , c) => n >= c ? n : c, 0);
|
||||
@@ -1,12 +0,0 @@
|
||||
import ScalarValue from "./ScalarValue";
|
||||
import ListOfNumbersExpression from "./ListOfNumbersExpression";
|
||||
import { numberParser } from "./numberParser";
|
||||
|
||||
it('calculates max bits length', () => {
|
||||
const v1 = new ScalarValue(numberParser.parse("10").value);
|
||||
const v2 = new ScalarValue(numberParser.parse("0xabef").value);
|
||||
const v3 = new ScalarValue(numberParser.parse("0b01010").value);
|
||||
|
||||
var expr = new ListOfNumbersExpression("10 0xabef 0b01010", [v1, v2, v3])
|
||||
expect(expr.maxBitsLength).toBe(16);
|
||||
});
|
||||
@@ -1,10 +1,10 @@
|
||||
import { INT32_MAX_VALUE } from "../core/const";
|
||||
import ScalarValue from "./ScalarValue";
|
||||
import Operand from "./Operand";
|
||||
|
||||
|
||||
it('converts numbers to bigint', () => {
|
||||
const int32 = new ScalarValue(INT32_MAX_VALUE);
|
||||
const int64 = new ScalarValue(BigInt(INT32_MAX_VALUE+1));
|
||||
const int32 = new Operand(INT32_MAX_VALUE);
|
||||
const int64 = new Operand(BigInt(INT32_MAX_VALUE+1));
|
||||
|
||||
expect(int32.value.maxBitSize).toBe(32);
|
||||
expect(int64.value.maxBitSize).toBe(64);
|
||||
@@ -8,7 +8,7 @@ var globalId : number = 1;
|
||||
|
||||
|
||||
// Represents scalar numeric value
|
||||
export default class ScalarValue implements ExpressionElement {
|
||||
export default class Operand implements ExpressionElement {
|
||||
id: number;
|
||||
value: Integer;
|
||||
base: NumberBase;
|
||||
@@ -20,7 +20,7 @@ export default class ScalarValue implements ExpressionElement {
|
||||
if(!isInteger(value))
|
||||
value = asInteger(value);
|
||||
|
||||
ScalarValue.validateSupported(value);
|
||||
Operand.validateSupported(value);
|
||||
|
||||
this.id = globalId++;
|
||||
this.value = value as Integer;
|
||||
@@ -29,21 +29,21 @@ export default class ScalarValue implements ExpressionElement {
|
||||
this.label = '';
|
||||
}
|
||||
|
||||
setValue(value : Integer) : ScalarValue {
|
||||
setValue(value : Integer) : Operand {
|
||||
this.value = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
setLabel(label : string) : ScalarValue {
|
||||
setLabel(label : string) : Operand {
|
||||
this.label = label;
|
||||
return this;
|
||||
}
|
||||
|
||||
evaluate() : ScalarValue {
|
||||
evaluate() : Operand {
|
||||
return this;
|
||||
}
|
||||
|
||||
getUnderlyingScalarOperand() : ScalarValue {
|
||||
getUnderlyingOperand() : Operand {
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import ScalarValue from "./ScalarValue";
|
||||
import BitwiseOperator from './BitwiseOperator';
|
||||
import Operand from "./Operand";
|
||||
import Operator from './Operator';
|
||||
|
||||
it('can apply ~ operand', () => {
|
||||
var op = new ScalarValue(10, 'dec');
|
||||
var expr = new BitwiseOperator(op, "~");
|
||||
var op = new Operand(10, 'dec');
|
||||
var expr = new Operator(op, "~");
|
||||
|
||||
var result = expr.evaluate();
|
||||
expect(result.value.num()).toBe(-11);
|
||||
@@ -11,9 +11,9 @@ it('can apply ~ operand', () => {
|
||||
});
|
||||
|
||||
it('can apply & operand', () => {
|
||||
var op1 = new ScalarValue(3, 'dec');
|
||||
var op2 = new ScalarValue(4, 'dec');
|
||||
var expr = new BitwiseOperator(op1, "|");
|
||||
var op1 = new Operand(3, 'dec');
|
||||
var op2 = new Operand(4, 'dec');
|
||||
var expr = new Operator(op1, "|");
|
||||
var result = expr.evaluate(op2);
|
||||
expect(result.value.num()).toBe(7);
|
||||
expect(result.base).toBe('dec');
|
||||
@@ -1,8 +1,8 @@
|
||||
import calc from '../core/calc';
|
||||
import ScalarValue from './ScalarValue';
|
||||
import Operand from './Operand';
|
||||
import { ExpressionElement } from './expression-interfaces';
|
||||
|
||||
export default class BitwiseOperator implements ExpressionElement {
|
||||
export default class Operator implements ExpressionElement {
|
||||
operand: ExpressionElement;
|
||||
operator: string;
|
||||
isOperator: boolean;
|
||||
@@ -18,9 +18,9 @@ export default class BitwiseOperator implements ExpressionElement {
|
||||
this.isNotExpression = this.operator === '~';
|
||||
}
|
||||
|
||||
evaluate(operand?: ScalarValue) : ScalarValue {
|
||||
evaluate(operand?: Operand) : Operand {
|
||||
|
||||
if (operand instanceof BitwiseOperator)
|
||||
if (operand instanceof Operator)
|
||||
throw new Error('operand must be scalar value');
|
||||
|
||||
if( this.operator != "~" && operand == null)
|
||||
@@ -29,12 +29,12 @@ export default class BitwiseOperator implements ExpressionElement {
|
||||
var evaluatedOperand = this.operand.evaluate();
|
||||
|
||||
return this.operator == "~"
|
||||
? applyNotOperator(this.operand.getUnderlyingScalarOperand())
|
||||
? applyNotOperator(this.operand.getUnderlyingOperand())
|
||||
: applyOperator(operand!, this.operator, evaluatedOperand);
|
||||
}
|
||||
|
||||
getUnderlyingScalarOperand() : ScalarValue {
|
||||
return this.operand.getUnderlyingScalarOperand();
|
||||
getUnderlyingOperand() : Operand {
|
||||
return this.operand.getUnderlyingOperand();
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
@@ -42,13 +42,14 @@ export default class BitwiseOperator implements ExpressionElement {
|
||||
}
|
||||
}
|
||||
|
||||
function applyNotOperator(operand: ScalarValue) : ScalarValue {
|
||||
return new ScalarValue(calc.not(operand.value), operand.base);
|
||||
function applyNotOperator(operand: Operand) : Operand {
|
||||
return new Operand(calc.not(operand.value), operand.base);
|
||||
}
|
||||
|
||||
function applyOperator(op1 : ScalarValue, operator: string, op2 : ScalarValue) : ScalarValue {
|
||||
function applyOperator(op1 : Operand, operator: string, op2 : Operand) : Operand {
|
||||
|
||||
const isShift = /<|>/.test(operator);
|
||||
|
||||
if(!isShift)
|
||||
{
|
||||
if(op1.value.maxBitSize == op2.value.maxBitSize && op1.value.signed != op2.value.signed)
|
||||
@@ -57,11 +58,13 @@ function applyOperator(op1 : ScalarValue, operator: string, op2 : ScalarValue) :
|
||||
equalizeSize(op1, op2);
|
||||
}
|
||||
|
||||
console.log(op1.value, operator, op2.value);
|
||||
const result = calc.operation(op1.value, operator, op2.value);
|
||||
return new ScalarValue(result, op2.base);
|
||||
console.log('=', result);
|
||||
return new Operand(result, op2.base);
|
||||
}
|
||||
|
||||
function equalizeSize(op1: ScalarValue, op2: ScalarValue) {
|
||||
function equalizeSize(op1: Operand, op2: Operand) {
|
||||
|
||||
const n1 = op1.value;
|
||||
const n2 = op2.value;
|
||||
@@ -3,7 +3,7 @@ import formatter from '../../core/formatter';
|
||||
import BinaryStringView, { FlipBitEventArg } from '../../core/components/BinaryString';
|
||||
import BitwiseResultViewModel from './BitwiseResultViewModel';
|
||||
import { Expression, ExpressionElement } from '../expression-interfaces';
|
||||
import { BitwiseOperator, ScalarValue } from '../expression';
|
||||
import { Operator, Operand, ListOfNumbers } from '../expression';
|
||||
import calc from '../../core/calc';
|
||||
|
||||
type BitwiseResultViewProps = {
|
||||
@@ -27,18 +27,18 @@ export default class BitwiseResultView extends React.Component<BitwiseResultView
|
||||
render() {
|
||||
|
||||
let model : BitwiseResultViewModel | null = null
|
||||
const isListOfNumbers = this.props.expression instanceof ListOfNumbers;
|
||||
|
||||
try
|
||||
{
|
||||
{
|
||||
model = BitwiseResultViewModel.createModel(this.props.expression, this.props.emphasizeBytes);
|
||||
}
|
||||
catch(err) {
|
||||
}
|
||||
catch(err) {
|
||||
const text = (err as any).message;
|
||||
return <div className='error'>Error: {text}</div>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var rows = this.getRows(model!);
|
||||
var rows = this.getRows(model!, isListOfNumbers);
|
||||
|
||||
return <table className="expression">
|
||||
<tbody>
|
||||
@@ -47,7 +47,7 @@ export default class BitwiseResultView extends React.Component<BitwiseResultView
|
||||
</table>
|
||||
}
|
||||
|
||||
getRows(model: BitwiseResultViewModel): JSX.Element[] {
|
||||
getRows(model: BitwiseResultViewModel, allowSignChange : boolean): JSX.Element[] {
|
||||
|
||||
this.maxSeenLengthNumberOfBits = Math.max(model.maxNumberOfBits, this.maxSeenLengthNumberOfBits);
|
||||
|
||||
@@ -58,6 +58,7 @@ export default class BitwiseResultView extends React.Component<BitwiseResultView
|
||||
css={itm.css}
|
||||
bitSize={itm.maxBitSize}
|
||||
allowFlipBits={itm.allowFlipBits}
|
||||
allowSignChange={allowSignChange}
|
||||
expressionItem={itm.expression}
|
||||
emphasizeBytes={this.props.emphasizeBytes}
|
||||
maxNumberOfBits={this.maxSeenLengthNumberOfBits}
|
||||
@@ -77,15 +78,20 @@ type ExpressionRowProps = {
|
||||
maxNumberOfBits: number,
|
||||
emphasizeBytes: boolean,
|
||||
allowFlipBits: boolean,
|
||||
allowSignChange: boolean,
|
||||
expressionItem: ExpressionElement,
|
||||
onBitFlipped: any
|
||||
}
|
||||
|
||||
class ExpressionRow extends React.Component<ExpressionRowProps> {
|
||||
|
||||
infoWasShown: boolean = false;
|
||||
|
||||
constructor(props: ExpressionRowProps) {
|
||||
super(props);
|
||||
this.state = { operand: null };
|
||||
}
|
||||
|
||||
render() {
|
||||
const { sign, css, maxNumberOfBits, emphasizeBytes, allowFlipBits } = this.props;
|
||||
const scalar = this.props.expressionItem.evaluate();
|
||||
@@ -113,17 +119,17 @@ class ExpressionRow extends React.Component<ExpressionRowProps> {
|
||||
// For expressions like |~2
|
||||
// TODO: find a better way...
|
||||
if (this.props.expressionItem.isOperator) {
|
||||
const ex = this.props.expressionItem as BitwiseOperator;
|
||||
return ex.operator + this.getLabelString(ex.getUnderlyingScalarOperand());
|
||||
const ex = this.props.expressionItem as Operator;
|
||||
return ex.operator + this.getLabelString(ex.getUnderlyingOperand());
|
||||
}
|
||||
|
||||
return this.getLabelString(this.props.expressionItem.getUnderlyingScalarOperand());
|
||||
return this.getLabelString(this.props.expressionItem.getUnderlyingOperand());
|
||||
}
|
||||
|
||||
getAlternative() {
|
||||
|
||||
if (this.props.expressionItem.isOperator) {
|
||||
const ex = this.props.expressionItem as BitwiseOperator;
|
||||
const ex = this.props.expressionItem as Operator;
|
||||
const res = ex.evaluate();
|
||||
|
||||
return formatter.numberToString(res.value, res.base);
|
||||
@@ -134,13 +140,13 @@ class ExpressionRow extends React.Component<ExpressionRowProps> {
|
||||
return formatter.numberToString(v.value, altBase);
|
||||
}
|
||||
|
||||
getLabelString(op: ScalarValue): string {
|
||||
getLabelString(op: Operand): string {
|
||||
return formatter.numberToString(op.value, op.base == 'bin' ? 'dec' : op.base);
|
||||
}
|
||||
|
||||
flipBit(args: FlipBitEventArg) {
|
||||
|
||||
const op = this.props.expressionItem.getUnderlyingScalarOperand();
|
||||
const op = this.props.expressionItem.getUnderlyingOperand();
|
||||
const { bitIndex: index, binaryStringLength: totalLength } = args;
|
||||
|
||||
const maxBitSize = op.value.maxBitSize;
|
||||
@@ -155,27 +161,47 @@ class ExpressionRow extends React.Component<ExpressionRowProps> {
|
||||
this.props.onBitFlipped();
|
||||
}
|
||||
|
||||
onChangeSign () {
|
||||
var op = this.props.expressionItem.getUnderlyingOperand();
|
||||
op.setValue(op.value.signed ? op.value.toUnsigned() : op.value.toSigned());
|
||||
this.forceUpdate();
|
||||
}
|
||||
|
||||
getInfo(maxNumberOfBits:number) {
|
||||
var op = this.props.expressionItem.getUnderlyingScalarOperand();
|
||||
|
||||
const op = this.props.expressionItem.getUnderlyingOperand();
|
||||
const allBitsDisplayed = op.value.maxBitSize != 32 || op.value.maxBitSize <= maxNumberOfBits;
|
||||
const { allowSignChange } = this.props;
|
||||
const hasLabel = op.label.length > 0;
|
||||
|
||||
if((op.value.maxBitSize != 32 || op.value.maxBitSize <= maxNumberOfBits) || op.label.length > 0)
|
||||
if(!allBitsDisplayed && !hasLabel && !this.infoWasShown)
|
||||
return null;
|
||||
|
||||
this.infoWasShown = true;
|
||||
|
||||
const children = [];
|
||||
let title = `BitwiseCmd treats this number as ${op.value.maxBitSize}-bit integer`;
|
||||
let text = `${op.value.maxBitSize}-bit `;
|
||||
const signedStr = op.value.signed ? 'signed' : 'unsigned';
|
||||
const signedOther = op.value.signed ? 'usigned' : 'signed';
|
||||
const signedTitle = `Click to change to ${signedOther} preserving the same bits`;
|
||||
|
||||
if(op.label.length > 0)
|
||||
{
|
||||
let title = `BitwiseCmd treats this number as ${op.value.maxBitSize}-bit integer`;
|
||||
let text = `${op.value.maxBitSize}-bit `;
|
||||
|
||||
if(!op.value.signed)
|
||||
text += " unsigned ";
|
||||
|
||||
if(op.label.length > 0)
|
||||
{
|
||||
text += " (converted)";
|
||||
title += ". This number was converted to facilitate bitwise operation with an operand of a different type";
|
||||
}
|
||||
|
||||
return <span title={title} style={{cursor:"help"}}>{text}</span>;
|
||||
text += " (converted)";
|
||||
title += ". This number was converted to facilitate bitwise operation with an operand of a different type";
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
children.push(<span title={title} style={{cursor:"help"}}>{text.trim()}</span>);
|
||||
|
||||
if(allBitsDisplayed)
|
||||
{
|
||||
if(allowSignChange)
|
||||
children.push(<button className='accent1' title={signedTitle} onClick={() => this.onChangeSign()}>{signedStr}</button>);
|
||||
else if(!op.value.signed)
|
||||
children.push(<span className='accent1'> {signedStr}</span>)
|
||||
}
|
||||
|
||||
return <React.Fragment>{children}</React.Fragment>
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ScalarValue, ListOfNumbersExpression, BitwiseOperationExpression, BitwiseOperator } from '../expression';
|
||||
import { Operand, ListOfNumbers, BitwiseOperation, Operator } from '../expression';
|
||||
import { ExpressionElement, Expression } from '../expression-interfaces';
|
||||
import calc from '../../core/calc';
|
||||
import formatter from '../../core/formatter';
|
||||
@@ -31,30 +31,30 @@ export default class BitwiseResultViewModel {
|
||||
this.allowFlipBits = allowFlipBits === true;
|
||||
}
|
||||
|
||||
static buildListOfNumbers(expr : ListOfNumbersExpression, config : Config) {
|
||||
static buildListOfNumbers(expr : ListOfNumbers, config : Config) {
|
||||
var model = new BitwiseResultViewModel(config);
|
||||
expr.children.forEach(op => model.addScalarRow(op));
|
||||
model.maxNumberOfBits = BitwiseResultViewModel.applyEmphasizeBytes(model.maxNumberOfBits, model.emphasizeBytes);
|
||||
return model;
|
||||
}
|
||||
|
||||
static buildBitwiseOperation (expr : BitwiseOperationExpression, config : Config) {
|
||||
static buildBitwiseOperation (expr : BitwiseOperation, config : Config) {
|
||||
|
||||
var op = expr.children[0],
|
||||
i = 0, len = expr.children.length,
|
||||
ex, m = new BitwiseResultViewModel(config);
|
||||
|
||||
var prev : ScalarValue | null = null;
|
||||
var prev : Operand | null = null;
|
||||
|
||||
for (;i<len;i++) {
|
||||
ex = expr.children[i];
|
||||
if(ex instanceof ScalarValue) {
|
||||
if(ex instanceof Operand) {
|
||||
m.addScalarRow(ex);
|
||||
prev = ex;
|
||||
continue;
|
||||
}
|
||||
|
||||
var eo = ex as BitwiseOperator;
|
||||
var eo = ex as Operator;
|
||||
|
||||
// If it a single NOT expression
|
||||
if(eo.isNotExpression) {
|
||||
@@ -64,11 +64,11 @@ export default class BitwiseResultViewModel {
|
||||
prev = notResult;
|
||||
}
|
||||
else if(eo.isShiftExpression){
|
||||
prev = eo.evaluate(prev as ScalarValue);
|
||||
prev = eo.evaluate(prev as Operand);
|
||||
m.addShiftExpressionResultRow(eo, prev);
|
||||
} else {
|
||||
|
||||
prev = eo.evaluate(prev as ScalarValue);
|
||||
prev = eo.evaluate(prev as Operand);
|
||||
m.addOperatorRow(eo);
|
||||
m.addExpressionResultRow(prev);
|
||||
}
|
||||
@@ -78,7 +78,7 @@ export default class BitwiseResultViewModel {
|
||||
return m;
|
||||
};
|
||||
|
||||
addScalarRow(expr: ScalarValue) {
|
||||
addScalarRow(expr: Operand) {
|
||||
const bits = calc.numberOfBitsDisplayed(expr.value);
|
||||
this.maxNumberOfBits = Math.max(bits, this.maxNumberOfBits);
|
||||
this.items.push({
|
||||
@@ -91,9 +91,9 @@ export default class BitwiseResultViewModel {
|
||||
});
|
||||
};
|
||||
|
||||
addOperatorRow(expr: BitwiseOperator) {
|
||||
addOperatorRow(expr: Operator) {
|
||||
|
||||
const resultNumber = expr.isNotExpression ? expr.evaluate() : expr.getUnderlyingScalarOperand();
|
||||
const resultNumber = expr.isNotExpression ? expr.evaluate() : expr.getUnderlyingOperand();
|
||||
const bits = calc.numberOfBitsDisplayed(resultNumber.value);
|
||||
|
||||
this.maxNumberOfBits = Math.max(bits, this.maxNumberOfBits);
|
||||
@@ -108,10 +108,10 @@ export default class BitwiseResultViewModel {
|
||||
});
|
||||
};
|
||||
|
||||
addShiftExpressionResultRow(expr : BitwiseOperator, resultExpr : ScalarValue) {
|
||||
addShiftExpressionResultRow(expr : Operator, resultExpr : Operand) {
|
||||
const bits = calc.numberOfBitsDisplayed(resultExpr.value);
|
||||
this.maxNumberOfBits = Math.max(bits, this.maxNumberOfBits);
|
||||
const child = expr.operand.getUnderlyingScalarOperand();
|
||||
const child = expr.operand.getUnderlyingOperand();
|
||||
this.items.push({
|
||||
sign: expr.operator + formatter.numberToString(child.value, child.base),
|
||||
css: 'expression-result',
|
||||
@@ -122,7 +122,7 @@ export default class BitwiseResultViewModel {
|
||||
});
|
||||
};
|
||||
|
||||
addExpressionResultRow(expr : ScalarValue) {
|
||||
addExpressionResultRow(expr : Operand) {
|
||||
const bits = calc.numberOfBitsDisplayed(expr.value);
|
||||
this.maxNumberOfBits = Math.max(bits, this.maxNumberOfBits);
|
||||
this.items.push({
|
||||
@@ -135,7 +135,7 @@ export default class BitwiseResultViewModel {
|
||||
});
|
||||
};
|
||||
|
||||
getLabel (op: ScalarValue) : string {
|
||||
getLabel (op: Operand) : string {
|
||||
|
||||
return formatter.numberToString(op.value, op.base === 'bin' ? 'dec' : op.base)
|
||||
}
|
||||
@@ -155,14 +155,15 @@ export default class BitwiseResultViewModel {
|
||||
};
|
||||
|
||||
static createModel(expr : Expression, emphasizeBytes: boolean) : BitwiseResultViewModel {
|
||||
if(expr instanceof ListOfNumbersExpression) {
|
||||
|
||||
if(expr instanceof ListOfNumbers) {
|
||||
return BitwiseResultViewModel.buildListOfNumbers(expr, {
|
||||
emphasizeBytes: emphasizeBytes,
|
||||
allowFlipBits: true
|
||||
});
|
||||
}
|
||||
|
||||
if(expr instanceof BitwiseOperationExpression) {
|
||||
if(expr instanceof BitwiseOperation) {
|
||||
return BitwiseResultViewModel.buildBitwiseOperation(expr, {
|
||||
emphasizeBytes: emphasizeBytes,
|
||||
allowFlipBits: true
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ScalarValue } from "./expression";
|
||||
import { Operand } from "./expression";
|
||||
|
||||
export interface Expression
|
||||
{
|
||||
@@ -8,7 +8,7 @@ export interface Expression
|
||||
export interface ExpressionElement
|
||||
{
|
||||
isOperator: boolean;
|
||||
getUnderlyingScalarOperand: () => ScalarValue;
|
||||
evaluate(operand? : ScalarValue): ScalarValue;
|
||||
getUnderlyingOperand: () => Operand;
|
||||
evaluate(operand? : Operand): Operand;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { parser, ListOfNumbersExpression, BitwiseOperationExpression, ScalarValue, BitwiseOperator } from "./expression";
|
||||
import { parser, ListOfNumbers, BitwiseOperation, Operand, Operator } from "./expression";
|
||||
import { random } from "../core/utils";
|
||||
import { INT32_MAX_VALUE } from "../core/const";
|
||||
|
||||
@@ -6,7 +6,7 @@ describe("expression parser", () => {
|
||||
|
||||
it("parses list of number expression", () => {
|
||||
var result = parser.parse("1 2 3");
|
||||
expect(result).toBeInstanceOf(ListOfNumbersExpression);
|
||||
expect(result).toBeInstanceOf(ListOfNumbers);
|
||||
});
|
||||
|
||||
it("doesn't list of numbers in case of bad numbers", () => {
|
||||
@@ -15,43 +15,43 @@ describe("expression parser", () => {
|
||||
});
|
||||
|
||||
it("pares different operations expressions", () => {
|
||||
expect(parser.parse("~1")).toBeInstanceOf(BitwiseOperationExpression);
|
||||
expect(parser.parse("1^2")).toBeInstanceOf(BitwiseOperationExpression);
|
||||
expect(parser.parse("1|2")).toBeInstanceOf(BitwiseOperationExpression);
|
||||
expect(parser.parse("~1")).toBeInstanceOf(BitwiseOperation);
|
||||
expect(parser.parse("1^2")).toBeInstanceOf(BitwiseOperation);
|
||||
expect(parser.parse("1|2")).toBeInstanceOf(BitwiseOperation);
|
||||
});
|
||||
|
||||
it("parses big binary bitwise expression", () => {
|
||||
const input = "0b00010010001101000101011001111000 0b10101010101010101010101000000000";
|
||||
const actual = parser.parse(input);
|
||||
expect(actual).toBeInstanceOf(ListOfNumbersExpression);
|
||||
expect(actual).toBeInstanceOf(ListOfNumbers);
|
||||
|
||||
const expr = actual as ListOfNumbersExpression;
|
||||
expect(expr.children[0].getUnderlyingScalarOperand().value.toString()).toBe('305419896');
|
||||
expect(expr.children[1].getUnderlyingScalarOperand().value.toString()).toBe('2863311360');
|
||||
const expr = actual as ListOfNumbers;
|
||||
expect(expr.children[0].getUnderlyingOperand().value.toString()).toBe('305419896');
|
||||
expect(expr.children[1].getUnderlyingOperand().value.toString()).toBe('2863311360');
|
||||
})
|
||||
|
||||
it("pares multiple operand expression", () => {
|
||||
const result = parser.parse("1^2") as BitwiseOperationExpression;
|
||||
const result = parser.parse("1^2") as BitwiseOperation;
|
||||
expect(result.children.length).toBe(2);
|
||||
|
||||
const first = result.children[0];
|
||||
const second = result.children[1];
|
||||
|
||||
expect(first).toBeInstanceOf(ScalarValue);
|
||||
expect(first).toBeInstanceOf(Operand);
|
||||
|
||||
expect((first as ScalarValue).value.toString()).toBe("1");
|
||||
expect((first as Operand).value.toString()).toBe("1");
|
||||
|
||||
expect(second).toBeInstanceOf(BitwiseOperator);
|
||||
var secondOp = second as BitwiseOperator;
|
||||
expect(second).toBeInstanceOf(Operator);
|
||||
var secondOp = second as Operator;
|
||||
expect(secondOp.operator).toBe("^");
|
||||
|
||||
expect(secondOp.operand).toBeInstanceOf(ScalarValue);
|
||||
var childOp = secondOp.operand as ScalarValue;
|
||||
expect(secondOp.operand).toBeInstanceOf(Operand);
|
||||
var childOp = secondOp.operand as Operand;
|
||||
expect(childOp.value.toString()).toBe('2');
|
||||
});
|
||||
|
||||
it("bug", () => {
|
||||
var result = parser.parse("1|~2") as BitwiseOperationExpression;
|
||||
var result = parser.parse("1|~2") as BitwiseOperation;
|
||||
expect(result.children.length).toBe(2);
|
||||
});
|
||||
});
|
||||
@@ -104,13 +104,13 @@ describe("comparison with nodejs engine", () => {
|
||||
|
||||
try
|
||||
{
|
||||
const expr = parser.parse(actualInput) as BitwiseOperationExpression;
|
||||
const bo = (expr.children[0] as BitwiseOperator);
|
||||
const expr = parser.parse(actualInput) as BitwiseOperation;
|
||||
const bo = (expr.children[0] as Operator);
|
||||
const res = bo.evaluate();
|
||||
actual = res.value.toString();
|
||||
|
||||
if(actual != expected) {
|
||||
const uop = bo.getUnderlyingScalarOperand();
|
||||
const uop = bo.getUnderlyingOperand();
|
||||
console.log(`Expected:${expectedInput}\nActual:${actualInput}\n${uop.value} ${uop.value.maxBitSize}\n${res.value} ${typeof res.value} ${res.value.maxBitSize}`)
|
||||
}
|
||||
}
|
||||
@@ -151,17 +151,17 @@ describe("comparison with nodejs engine", () => {
|
||||
|
||||
try
|
||||
{
|
||||
var expr = parser.parse(actualInput) as BitwiseOperationExpression;
|
||||
var expr = parser.parse(actualInput) as BitwiseOperation;
|
||||
|
||||
var op1 = expr.children[0] as ScalarValue;
|
||||
var op2 = expr.children[1] as BitwiseOperator;
|
||||
var op1 = expr.children[0] as Operand;
|
||||
var op2 = expr.children[1] as Operator;
|
||||
|
||||
actual = op2.evaluate(op1).value.toString();
|
||||
const equals = actual === expected;
|
||||
|
||||
if(!equals)
|
||||
{
|
||||
console.log(`Expected:${expectedInput}\n$Actual:${actualInput}\nop1:${typeof op1.value}\nop2:${typeof op2.getUnderlyingScalarOperand().value}`);
|
||||
console.log(`Expected:${expectedInput}\n$Actual:${actualInput}\nop1:${typeof op1.value}\nop2:${typeof op2.getUnderlyingOperand().value}`);
|
||||
}
|
||||
}
|
||||
catch(err)
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
import ScalarValue from './ScalarValue';
|
||||
import BitwiseOperator from './BitwiseOperator'
|
||||
import ListOfNumbersExpression from './ListOfNumbersExpression';
|
||||
import BitwiseOperationExpression from './BitwiseOperationExpression';
|
||||
import Operand from './Operand';
|
||||
import Operator from './Operator'
|
||||
import ListOfNumbers from './ListOfNumbers';
|
||||
import BitwiseOperation from './BitwiseOperation';
|
||||
import { Expression, ExpressionElement } from './expression-interfaces';
|
||||
import { numberParser, numberRegexString } from './numberParser';
|
||||
import { parse } from 'path';
|
||||
|
||||
export { default as ScalarValue } from './ScalarValue';
|
||||
export { default as BitwiseOperator } from './BitwiseOperator';
|
||||
export { default as ListOfNumbersExpression } from './ListOfNumbersExpression';
|
||||
export { default as BitwiseOperationExpression } from './BitwiseOperationExpression';
|
||||
export { default as Operand } from './Operand';
|
||||
export { default as Operator } from './Operator';
|
||||
export { default as ListOfNumbers } from './ListOfNumbers';
|
||||
export { default as BitwiseOperation } from './BitwiseOperation';
|
||||
|
||||
interface IExpressionParserFactory {
|
||||
canCreate: (input: string) => boolean;
|
||||
@@ -76,7 +75,7 @@ class ListOfNumbersExpressionFactory implements IExpressionParserFactory
|
||||
.filter(p => p.length > 0)
|
||||
.map(m => parseScalarValue(m));
|
||||
|
||||
return new ListOfNumbersExpression(input, numbers);
|
||||
return new ListOfNumbers(input, numbers);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,7 +104,7 @@ class BitwiseOperationExpressionFactory implements IExpressionParserFactory {
|
||||
operands.push(this.parseMatch(m));
|
||||
}
|
||||
|
||||
return new BitwiseOperationExpression(normalizedString, operands)
|
||||
return new BitwiseOperation(normalizedString, operands)
|
||||
};
|
||||
|
||||
parseMatch (m:RegExpExecArray): ExpressionElement {
|
||||
@@ -117,16 +116,16 @@ class BitwiseOperationExpressionFactory implements IExpressionParserFactory {
|
||||
var parsed = null;
|
||||
|
||||
if(num.indexOf('~') == 0) {
|
||||
parsed = new BitwiseOperator(parseScalarValue(num.substring(1)), '~');
|
||||
parsed = new Operator(parseScalarValue(num.substring(1)), '~');
|
||||
}
|
||||
else {
|
||||
parsed = parseScalarValue(num);
|
||||
}
|
||||
|
||||
if(operator == null) {
|
||||
return parsed as BitwiseOperator;
|
||||
return parsed as Operator;
|
||||
} else {
|
||||
return new BitwiseOperator(parsed as ScalarValue, operator);
|
||||
return new Operator(parsed as Operand, operator);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -135,9 +134,9 @@ class BitwiseOperationExpressionFactory implements IExpressionParserFactory {
|
||||
};
|
||||
}
|
||||
|
||||
function parseScalarValue(input : string) : ScalarValue {
|
||||
function parseScalarValue(input : string) : Operand {
|
||||
const n = numberParser.parse(input);
|
||||
var sv = new ScalarValue(n.value, n.base);
|
||||
var sv = new Operand(n.value, n.base);
|
||||
if(sv.value.maxBitSize != n.value.maxBitSize) throw new Error("Gotcha!");
|
||||
return sv;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user