Initial commit
This commit is contained in:
commit
83193bb8ba
|
|
@ -0,0 +1 @@
|
||||||
|
node_modules/
|
||||||
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,97 @@
|
||||||
|
import bit, { Bit } from "./bit"
|
||||||
|
import { range, zip } from "lodash"
|
||||||
|
|
||||||
|
type GreaterThan<Threshold extends number> = number
|
||||||
|
type LessOrEqual<Threshold extends number> = number
|
||||||
|
|
||||||
|
export interface Word<Width extends number> {
|
||||||
|
|
||||||
|
plus: <OtherWidth extends number, ResultWidth = >(other: Word<OtherWidth>) => Word<GreaterOf<Width, OtherWidth>>
|
||||||
|
bits: Bit[]
|
||||||
|
length: Width
|
||||||
|
}
|
||||||
|
|
||||||
|
// function greaterOf<Value extends number, Other extends number>(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<A extends LessThan, B>(value: LessThan, other: B): LessThan
|
||||||
|
function greaterOf<A extends GreaterOrEqual, B>(value: GreaterOrEqual, other: B): GreaterOrEqual
|
||||||
|
function greaterOf<A extends number, B extends number>(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<T, Length extends number> = Readonly<Array<T> & { length: Length}>
|
||||||
|
|
||||||
|
export function wordFromBits<Width extends Readonly<number>>(bits: readonly FixedLengthArray<Bit, Width>) {
|
||||||
|
|
||||||
|
function plus<OtherWidth extends GreaterThan<Width>>(other: Word<OtherWidth>): Word<OtherWidth>
|
||||||
|
function plus<OtherWidth extends LessOrEqual<Width>>(other: Word<OtherWidth>): Word<Width> {
|
||||||
|
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<SumResult>(({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 extends number>(width: Width): Word<Width> {
|
||||||
|
const bits = range(0, width).map(() => bit(0))
|
||||||
|
return wordFromBits(bits)
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue