From 83193bb8ba922aeb5a6485fcc9e33ab46c6b638a Mon Sep 17 00:00:00 2001 From: Jeff Date: Wed, 7 Feb 2024 23:29:29 -0500 Subject: [PATCH] Initial commit --- .gitignore | 1 + bit.ts | 22 +++++++++++ index.ts | 3 ++ memory.ts | 12 ++++++ package-lock.json | 67 ++++++++++++++++++++++++++++++++ package.json | 19 ++++++++++ types.ts | 0 word.ts | 97 +++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 221 insertions(+) create mode 100644 .gitignore create mode 100644 bit.ts create mode 100644 index.ts create mode 100644 memory.ts create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 types.ts create mode 100644 word.ts diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c2658d7 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules/ diff --git a/bit.ts b/bit.ts new file mode 100644 index 0000000..04dd6ef --- /dev/null +++ b/bit.ts @@ -0,0 +1,22 @@ +type BinaryDigit = 0 | 1 + +export interface Bit { + value: BinaryDigit + add: (other: Bit) => { ones: Bit, carry: Bit } +} + +export default function bit(value: BinaryDigit): Bit { + + function add(other: Bit) { + const result = (value + other.value) + const ones = result % 2 as BinaryDigit + const carry = result === 2 ? 1 : 0 + + return { bit: bit(ones), carry: bit(carry) } + } + + return { + add, + value + } +} \ No newline at end of file diff --git a/index.ts b/index.ts new file mode 100644 index 0000000..18b013a --- /dev/null +++ b/index.ts @@ -0,0 +1,3 @@ +function memory(bits: number) { + +} \ No newline at end of file diff --git a/memory.ts b/memory.ts new file mode 100644 index 0000000..8db4270 --- /dev/null +++ b/memory.ts @@ -0,0 +1,12 @@ +import { Bit } from "./bit"; +import { emptyWord, wordFromBits } from "./word"; + +function memory(initialValue: Bit[]) +function memory(width: number) +function memory(valueOrWidth: number | Bit[]) { + let word = typeof valueOrWidth === 'number' ? emptyWord(valueOrWidth) : wordFromBits(valueOrWidth) + + function set(word: Word) { + + } +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..8301709 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,67 @@ +{ + "name": "grit", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "grit", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@types/lodash": "^4.14.202", + "lodash": "^4.17.21" + }, + "devDependencies": { + "@rimbu/typical": "^0.8.0", + "@types/node": "^20.11.16" + } + }, + "node_modules/@rimbu/typical": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@rimbu/typical/-/typical-0.8.0.tgz", + "integrity": "sha512-quQ3OFICxy4ZEU+BRFibi8TkxdML3+RrjK2CNh8lkF02mLifSLn41/RMFQKCgV/CofhX2d/53kZE9V1ptCNRmw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/vitoke" + } + ], + "dependencies": { + "tslib": "^2.6.2" + } + }, + "node_modules/@types/lodash": { + "version": "4.14.202", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.202.tgz", + "integrity": "sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ==" + }, + "node_modules/@types/node": { + "version": "20.11.16", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.16.tgz", + "integrity": "sha512-gKb0enTmRCzXSSUJDq6/sPcqrfCv2mkkG6Jt/clpn5eiCbKTY+SgZUxo+p8ZKMof5dCp9vHQUAB7wOUTod22wQ==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..d8bf352 --- /dev/null +++ b/package.json @@ -0,0 +1,19 @@ +{ + "name": "grit", + "version": "1.0.0", + "description": "Tiny computer", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "@types/lodash": "^4.14.202", + "lodash": "^4.17.21" + }, + "devDependencies": { + "@rimbu/typical": "^0.8.0", + "@types/node": "^20.11.16" + } +} diff --git a/types.ts b/types.ts new file mode 100644 index 0000000..e69de29 diff --git a/word.ts b/word.ts new file mode 100644 index 0000000..8772ac8 --- /dev/null +++ b/word.ts @@ -0,0 +1,97 @@ +import bit, { Bit } from "./bit" +import { range, zip } from "lodash" + +type GreaterThan = number +type LessOrEqual = number + +export interface Word { + + plus: (other: Word) => Word> + bits: Bit[] + length: Width +} + +// function greaterOf(value: Value, other: Other){ +// return value > other ? value as Value : other as Other +// } + +type LessThan = number +type GreaterOrEqual = number + +function isLessThan(value: number, other: number): value is LessThan { + return value < other +} + +function isGreaterThanOrEqual(value: number, other: number): value is GreaterOrEqual { + return value >= other +} + +function greaterOf(value: LessThan, other: B): LessThan +function greaterOf(value: GreaterOrEqual, other: B): GreaterOrEqual +function greaterOf(value: A, other: B): LessThan | GreaterOrEqual { + const result = Math.max(value, other) + return isLessThan(value, other) ? value as GreaterThan : other as LessThan +} + +const duh = wordFromBits([bit(0)] as const).plus(wordFromBits([bit(0), bit(0)])) + +type FixedLengthArray = Readonly & { length: Length}> + +export function wordFromBits>(bits: readonly FixedLengthArray) { + + function plus>(other: Word): Word + function plus>(other: Word): Word { + const newBits = addBits(bits, other.bits) + + return wordFromBits(newBits.bits) + } + + function subword(start: number, length?: number) { + return wordFromBits(bits.slice(start, length !== undefined ? start + length : undefined)) + } + + return { + plus, + subword, + bits, + length: bits.length + } +} + +function addBits(bits: Bit[], otherBits: Bit[]) { + const bigEndianBits = [...bits].reverse() + const bigEndianOtherBits = [...otherBits].reverse() + + const pairedBits = zip(bigEndianBits, bigEndianOtherBits).reverse() + const denulledBits = pairedBits.map(([a, b]) => [a ?? bit(0), b ?? bit(0)] as const) + + const sumResults = denulledBits.reduce(({bits, carry}, [a, b]) => { + const aPlusB = a.add(b) + const aPlusBPlusCarry = aPlusB.ones.add(carry) + const thisCarry = aPlusB.carry.add(aPlusBPlusCarry.carry).ones + + bits.push(aPlusBPlusCarry.ones) + + return sumResult(bits, thisCarry) + }, sumResult([], bit(0))) + + + return sumResults +} + +interface SumResult { + bits: Bit[] + carry: Bit +} + +function sumResult(bits: Bit[], carry: Bit) { + return { + bits, + carry} + } +} + +export function emptyWord(width: Width): Word { + const bits = range(0, width).map(() => bit(0)) + return wordFromBits(bits) +} \ No newline at end of file