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