From ba8c7d4966167f56dfafc5a24330be2a0a8f5b61 Mon Sep 17 00:00:00 2001 From: BorysLevytskyi Date: Fri, 12 May 2023 14:30:44 +0200 Subject: [PATCH] Allow to input of negative unsigned numbers --- src/core/Integer.ts | 2 +- src/core/components/BinaryString.tsx | 7 +++++- src/core/const.ts | 5 ++-- .../components/BitwiseResultView.tsx | 1 + src/expression/numberParser.test.ts | 24 +++++++++++++++---- src/expression/numberParser.ts | 14 +++++++---- src/index.css | 2 +- 7 files changed, 42 insertions(+), 13 deletions(-) diff --git a/src/core/Integer.ts b/src/core/Integer.ts index b9dfe62..4448d72 100644 --- a/src/core/Integer.ts +++ b/src/core/Integer.ts @@ -14,7 +14,7 @@ export class Integer { readonly signed: boolean; constructor(value: IntegerInput, maxBitSize?: number, signed? : boolean) { - + this.value = typeof value == "bigint" ? value : BigInt(value); this.signed = signed == null ? true : signed == true; this.maxBitSize = maxBitSize != null ? maxBitSize : detectSize(this.value, this.signed); diff --git a/src/core/components/BinaryString.tsx b/src/core/components/BinaryString.tsx index 6882795..ac44358 100644 --- a/src/core/components/BinaryString.tsx +++ b/src/core/components/BinaryString.tsx @@ -9,6 +9,7 @@ export type BinaryStringViewProps = { className?: string; disableHighlight?: boolean, signBitIndex?: number, + integerBitSize?: number }; export type FlipBitEventArg = { @@ -57,13 +58,17 @@ export default class BinaryStringView extends React.Component { var className = c == '1' ? `one${css}` : `zero${css}`; var tooltip = ''; - const isExtra = i < (this.props.signBitIndex || 0); + + const isExtra = i < firstBitIndex; if (isExtra) className += ' extra-bit'; diff --git a/src/core/const.ts b/src/core/const.ts index 19a4b96..2ae8410 100644 --- a/src/core/const.ts +++ b/src/core/const.ts @@ -1,8 +1,9 @@ - +const UINT8_MAX_VALUE = 255; +const UINT16_MAX_VALUE = 65535 const INT32_MAX_VALUE = 2147483647; const INT32_MIN_VALUE = -2147483648; const UINT32_MAX_VALUE = 4294967295; const INT64_MAX_VALUE = BigInt("9223372036854775807"); const INT64_MIN_VALUE = BigInt("-9223372036854775808"); const UINT64_MAX_VALUE = BigInt("18446744073709551615"); -export {INT32_MAX_VALUE, INT32_MIN_VALUE, INT64_MAX_VALUE, INT64_MIN_VALUE, UINT32_MAX_VALUE, UINT64_MAX_VALUE}; +export {INT32_MAX_VALUE, INT32_MIN_VALUE, INT64_MAX_VALUE, INT64_MIN_VALUE, UINT32_MAX_VALUE, UINT64_MAX_VALUE, UINT8_MAX_VALUE, UINT16_MAX_VALUE }; diff --git a/src/expression/components/BitwiseResultView.tsx b/src/expression/components/BitwiseResultView.tsx index d20e5ac..4f44ff6 100644 --- a/src/expression/components/BitwiseResultView.tsx +++ b/src/expression/components/BitwiseResultView.tsx @@ -126,6 +126,7 @@ class ExpressionElementTableRow extends React.Component this.onBitClicked(args)} /> {this.getAlternative()} diff --git a/src/expression/numberParser.test.ts b/src/expression/numberParser.test.ts index 5ccb9e6..623750e 100644 --- a/src/expression/numberParser.test.ts +++ b/src/expression/numberParser.test.ts @@ -1,6 +1,7 @@ import exp from 'constants'; import { asIntN } from '../core/utils'; import {numberParser, ParsedNumber} from './numberParser'; +import { UINT16_MAX_VALUE, UINT32_MAX_VALUE, UINT64_MAX_VALUE, UINT8_MAX_VALUE } from '../core/const'; describe("parser", () => { @@ -124,10 +125,6 @@ describe("parser", () => { //expect(v2).toEqual(v); }); - it('cannot parse negative usigned', () => { - expect(() => numberParser.parse('-1u')).toThrowError("-1u unsigned integer cannot be negative"); - }); - it('parses usigned single', () => { var v = numberParser.parse('1us')?.value expect(v?.maxBitSize).toBe(16); @@ -164,4 +161,23 @@ describe("parser", () => { //var v2 = numberParser.parse('1i16')?.value //expect(v2?.num()).toEqual(v?.num()); }); + + it('allows negative unsigned for the sake of cimplicity', () => { + + const ubyte = numberParser.parse("-1ub").value; + expect(ubyte.num()).toBe(UINT8_MAX_VALUE); + expect(ubyte.maxBitSize).toBe(8); + + const ushort = numberParser.parse("-1us").value; + expect(ushort.num()).toBe(UINT16_MAX_VALUE); + expect(ushort.maxBitSize).toBe(16); + + const uint = numberParser.parse("-1u").value; + expect(uint.num()).toBe(UINT32_MAX_VALUE); + expect(uint.maxBitSize).toBe(32); + + const ulong = numberParser.parse("-1ul").value; + expect(ulong.value).toBe(UINT64_MAX_VALUE); + expect(ulong.maxBitSize).toBe(64); + }); }); \ No newline at end of file diff --git a/src/expression/numberParser.ts b/src/expression/numberParser.ts index 10053e9..d4d6db6 100644 --- a/src/expression/numberParser.ts +++ b/src/expression/numberParser.ts @@ -52,11 +52,17 @@ function parseInteger(input : string, numberPart: string, suffix: string) : Int let num = BigInt(numberPart); const signed = !suffix.startsWith('u'); - if(!signed && isNegative) - throw new Error(input + " unsigned integer cannot be negative"); + const bitSize = getSizeBySuffix(suffix, num, signed); + const newValue = isNegative ? -num : num; - const size = getSizeBySuffix(suffix, num, signed); - return new Integer(isNegative ? -num : num, size, signed); + if(!signed && isNegative) + { + const signed = new Integer(newValue, bitSize, true); + const bin = "0b" + signed.toString(2); + return Integer.unsigned(BigInt(bin), bitSize); + } + + return new Integer(newValue, bitSize, signed); } function getSizeBySuffix(suffix: string, value : bigint, signed: boolean) { diff --git a/src/index.css b/src/index.css index 202a1d9..ae6a50f 100644 --- a/src/index.css +++ b/src/index.css @@ -71,7 +71,7 @@ a.hashLink { font-size: 1.1em;} .cur { color: lightgray; } -.extra-bit { opacity: 0.2;} +.extra-bit { opacity: 0.3;} button { border: none; text-decoration: underline;}