Compare commits

..

No commits in common. "master" and "master" have entirely different histories.

187 changed files with 1714 additions and 5951 deletions

View file

@ -1,3 +1,3 @@
[alias] [alias]
repbuild = "run --manifest-path ./repbuild/Cargo.toml -- " repbuild = "run --manifest-path ./repbuild/Cargo.toml -r --"
dev = "run --manifest-path ./dev/Cargo.toml -r --" dev = "run --manifest-path ./dev/Cargo.toml -r --"

View file

@ -1,6 +1,4 @@
{ {
"editor.insertSpaces": false,
"editor.detectIndentation": false,
"rust-analyzer.checkOnSave.allTargets": false, "rust-analyzer.checkOnSave.allTargets": false,
"rust-analyzer.showUnlinkedFileNotification": false, "rust-analyzer.showUnlinkedFileNotification": false,
"C_Cpp.errorSquiggles": "disabled" "C_Cpp.errorSquiggles": "disabled"

591
Cargo.lock generated
View file

@ -1,6 +1,6 @@
# This file is automatically @generated by Cargo. # This file is automatically @generated by Cargo.
# It is not intended for manual editing. # It is not intended for manual editing.
version = 4 version = 3
[[package]] [[package]]
name = "aarch64-cpu" name = "aarch64-cpu"
@ -13,15 +13,30 @@ dependencies = [
[[package]] [[package]]
name = "allocator-api2" name = "allocator-api2"
version = "0.2.21" version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
[[package]]
name = "android-tzdata"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
[[package]]
name = "android_system_properties"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "anyhow" name = "anyhow"
version = "1.0.95" version = "1.0.91"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" checksum = "c042108f3ed77fd83760a5fd79b53be043192bb3b9dba91d8c574c0ada7850c8"
[[package]] [[package]]
name = "autocfg" name = "autocfg"
@ -65,6 +80,15 @@ version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
[[package]]
name = "bumpalo"
version = "3.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
dependencies = [
"allocator-api2",
]
[[package]] [[package]]
name = "byteorder" name = "byteorder"
version = "1.5.0" version = "1.5.0"
@ -73,9 +97,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.2.6" version = "1.1.31"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d6dbb628b8f8555f86d0323c2eb39e3ec81901f4b83e091db8a6a76d316a333" checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f"
dependencies = [ dependencies = [
"shlex", "shlex",
] ]
@ -87,19 +111,39 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]] [[package]]
name = "crossbeam-queue" name = "chrono"
version = "0.3.12" version = "0.4.38"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"
dependencies = [
"android-tzdata",
"iana-time-zone",
"js-sys",
"num-traits",
"wasm-bindgen",
"windows-targets",
]
[[package]]
name = "core-foundation-sys"
version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
[[package]]
name = "crossbeam-queue"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35"
dependencies = [ dependencies = [
"crossbeam-utils", "crossbeam-utils",
] ]
[[package]] [[package]]
name = "crossbeam-utils" name = "crossbeam-utils"
version = "0.8.21" version = "0.8.20"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
[[package]] [[package]]
name = "derive_more" name = "derive_more"
@ -129,17 +173,6 @@ dependencies = [
"logos", "logos",
] ]
[[package]]
name = "displaydoc"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "equivalent" name = "equivalent"
version = "1.0.1" version = "1.0.1"
@ -164,6 +197,7 @@ checksum = "05669f8e7e2d7badc545c513710f0eba09c2fbef683eb859fd79c46c355048e0"
dependencies = [ dependencies = [
"bitflags 1.3.2", "bitflags 1.3.2",
"byteorder", "byteorder",
"chrono",
"log", "log",
] ]
@ -175,9 +209,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]] [[package]]
name = "foldhash" name = "foldhash"
version = "0.1.4" version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2"
[[package]] [[package]]
name = "form_urlencoded" name = "form_urlencoded"
@ -201,9 +235,15 @@ dependencies = [
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.15.2" version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
[[package]]
name = "hashbrown"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb"
dependencies = [ dependencies = [
"allocator-api2", "allocator-api2",
"equivalent", "equivalent",
@ -213,174 +253,78 @@ dependencies = [
[[package]] [[package]]
name = "hbbytecode" name = "hbbytecode"
version = "0.1.0" version = "0.1.0"
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#d1bc70892b442376138e854450b0f423302962ef" source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#faa8dd2e6fabe2e0e4a375e677171856da491c61"
[[package]] [[package]]
name = "hblang" name = "hblang"
version = "0.1.0" version = "0.1.0"
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#d1bc70892b442376138e854450b0f423302962ef" source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#faa8dd2e6fabe2e0e4a375e677171856da491c61"
dependencies = [ dependencies = [
"hashbrown", "hashbrown 0.15.0",
"hbbytecode", "hbbytecode",
"hbvm", "hbvm",
"log", "log",
"regalloc2",
] ]
[[package]] [[package]]
name = "hbvm" name = "hbvm"
version = "0.1.0" version = "0.1.0"
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#d1bc70892b442376138e854450b0f423302962ef" source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#faa8dd2e6fabe2e0e4a375e677171856da491c61"
dependencies = [ dependencies = [
"hbbytecode", "hbbytecode",
] ]
[[package]] [[package]]
name = "icu_collections" name = "iana-time-zone"
version = "1.5.0" version = "0.1.61"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220"
dependencies = [ dependencies = [
"displaydoc", "android_system_properties",
"yoke", "core-foundation-sys",
"zerofrom", "iana-time-zone-haiku",
"zerovec", "js-sys",
"wasm-bindgen",
"windows-core",
] ]
[[package]] [[package]]
name = "icu_locid" name = "iana-time-zone-haiku"
version = "1.5.0" version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
dependencies = [ dependencies = [
"displaydoc", "cc",
"litemap",
"tinystr",
"writeable",
"zerovec",
]
[[package]]
name = "icu_locid_transform"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e"
dependencies = [
"displaydoc",
"icu_locid",
"icu_locid_transform_data",
"icu_provider",
"tinystr",
"zerovec",
]
[[package]]
name = "icu_locid_transform_data"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e"
[[package]]
name = "icu_normalizer"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f"
dependencies = [
"displaydoc",
"icu_collections",
"icu_normalizer_data",
"icu_properties",
"icu_provider",
"smallvec",
"utf16_iter",
"utf8_iter",
"write16",
"zerovec",
]
[[package]]
name = "icu_normalizer_data"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516"
[[package]]
name = "icu_properties"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5"
dependencies = [
"displaydoc",
"icu_collections",
"icu_locid_transform",
"icu_properties_data",
"icu_provider",
"tinystr",
"zerovec",
]
[[package]]
name = "icu_properties_data"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569"
[[package]]
name = "icu_provider"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9"
dependencies = [
"displaydoc",
"icu_locid",
"icu_provider_macros",
"stable_deref_trait",
"tinystr",
"writeable",
"yoke",
"zerofrom",
"zerovec",
]
[[package]]
name = "icu_provider_macros"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
dependencies = [
"proc-macro2",
"quote",
"syn",
] ]
[[package]] [[package]]
name = "idna" name = "idna"
version = "1.0.3" version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
dependencies = [ dependencies = [
"idna_adapter", "unicode-bidi",
"smallvec", "unicode-normalization",
"utf8_iter",
]
[[package]]
name = "idna_adapter"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71"
dependencies = [
"icu_normalizer",
"icu_properties",
] ]
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "2.7.0" version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da"
dependencies = [ dependencies = [
"equivalent", "equivalent",
"hashbrown", "hashbrown 0.15.0",
]
[[package]]
name = "js-sys"
version = "0.3.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9"
dependencies = [
"wasm-bindgen",
] ]
[[package]] [[package]]
@ -390,9 +334,8 @@ dependencies = [
"aarch64-cpu", "aarch64-cpu",
"crossbeam-queue", "crossbeam-queue",
"derive_more", "derive_more",
"hashbrown", "hashbrown 0.15.0",
"hbvm", "hbvm",
"ktest_macro",
"limine", "limine",
"log", "log",
"sbi", "sbi",
@ -401,18 +344,10 @@ dependencies = [
"uart_16550", "uart_16550",
"versioning", "versioning",
"x2apic", "x2apic",
"x86_64 0.15.2", "x86_64 0.15.1",
"xml", "xml",
] ]
[[package]]
name = "ktest_macro"
version = "0.1.0"
dependencies = [
"quote",
"syn",
]
[[package]] [[package]]
name = "lazy_static" name = "lazy_static"
version = "1.5.0" version = "1.5.0"
@ -421,9 +356,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.169" version = "0.2.161"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1"
[[package]] [[package]]
name = "limine" name = "limine"
@ -431,12 +366,6 @@ version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02034f8f6b3e7bf050f310fbaf6db0018b8e54b75598d0a4c97172054752fede" checksum = "02034f8f6b3e7bf050f310fbaf6db0018b8e54b75598d0a4c97172054752fede"
[[package]]
name = "litemap"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104"
[[package]] [[package]]
name = "lock_api" name = "lock_api"
version = "0.4.12" version = "0.4.12"
@ -455,18 +384,18 @@ checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]] [[package]]
name = "logos" name = "logos"
version = "0.14.4" version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7251356ef8cb7aec833ddf598c6cb24d17b689d20b993f9d11a3d764e34e6458" checksum = "1c6b6e02facda28ca5fb8dbe4b152496ba3b1bd5a4b40bb2b1b2d8ad74e0f39b"
dependencies = [ dependencies = [
"logos-derive", "logos-derive",
] ]
[[package]] [[package]]
name = "logos-codegen" name = "logos-codegen"
version = "0.14.4" version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59f80069600c0d66734f5ff52cc42f2dabd6b29d205f333d61fd7832e9e9963f" checksum = "b32eb6b5f26efacd015b000bfc562186472cd9b34bdba3f6b264e2a052676d10"
dependencies = [ dependencies = [
"beef", "beef",
"fnv", "fnv",
@ -479,9 +408,9 @@ dependencies = [
[[package]] [[package]]
name = "logos-derive" name = "logos-derive"
version = "0.14.4" version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24fb722b06a9dc12adb0963ed585f19fc61dc5413e6a9be9422ef92c091e731d" checksum = "3e5d0c5463c911ef55624739fc353238b4e310f0144be1f875dc42fec6bfd5ec"
dependencies = [ dependencies = [
"logos-codegen", "logos-codegen",
] ]
@ -492,6 +421,15 @@ version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "num-traits"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
]
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.20.2" version = "1.20.2"
@ -512,18 +450,18 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.92" version = "1.0.89"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.38" version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@ -546,6 +484,19 @@ dependencies = [
"bitflags 2.6.0", "bitflags 2.6.0",
] ]
[[package]]
name = "regalloc2"
version = "0.10.2"
source = "git+https://github.com/jakubDoka/regalloc2?branch=reuse-allocations#21c43e3ee182824e92e2b25f1d3c03ed47f9c02b"
dependencies = [
"allocator-api2",
"bumpalo",
"hashbrown 0.14.5",
"log",
"rustc-hash",
"smallvec",
]
[[package]] [[package]]
name = "regex-syntax" name = "regex-syntax"
version = "0.8.5" version = "0.8.5"
@ -582,6 +533,12 @@ dependencies = [
"windows-sys", "windows-sys",
] ]
[[package]]
name = "rustc-hash"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152"
[[package]] [[package]]
name = "rustc_version" name = "rustc_version"
version = "0.4.1" version = "0.4.1"
@ -593,9 +550,9 @@ dependencies = [
[[package]] [[package]]
name = "rustls" name = "rustls"
version = "0.23.20" version = "0.23.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5065c3f250cbd332cd894be57c40fa52387247659b14a2d6041d121547903b1b" checksum = "5fbb44d7acc4e873d613422379f69f237a1b141928c02f6bc6ccfddddc2d7993"
dependencies = [ dependencies = [
"log", "log",
"once_cell", "once_cell",
@ -608,9 +565,9 @@ dependencies = [
[[package]] [[package]]
name = "rustls-pki-types" name = "rustls-pki-types"
version = "1.10.1" version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2bf47e6ff922db3825eb750c4e2ff784c6ff8fb9e13046ef6a1d1c5401b0b37" checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b"
[[package]] [[package]]
name = "rustls-webpki" name = "rustls-webpki"
@ -625,9 +582,9 @@ dependencies = [
[[package]] [[package]]
name = "rustversion" name = "rustversion"
version = "1.0.19" version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248"
[[package]] [[package]]
name = "sbi" name = "sbi"
@ -643,24 +600,24 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]] [[package]]
name = "semver" name = "semver"
version = "1.0.24" version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.217" version = "1.0.213"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" checksum = "3ea7893ff5e2466df8d720bb615088341b295f849602c6956047f8f80f0e9bc1"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.217" version = "1.0.213"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" checksum = "7e85ad2009c50b58e87caa8cd6dac16bdf511bbfb7af6c33df902396aa480fa5"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -706,12 +663,6 @@ dependencies = [
"lock_api", "lock_api",
] ]
[[package]]
name = "stable_deref_trait"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]] [[package]]
name = "str-reader" name = "str-reader"
version = "0.1.2" version = "0.1.2"
@ -726,9 +677,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.93" version = "2.0.85"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c786062daee0d6db1132800e623df74274a0a87322d8e183338e01b3d98d058" checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -736,25 +687,19 @@ dependencies = [
] ]
[[package]] [[package]]
name = "synstructure" name = "tinyvec"
version = "0.13.1" version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938"
dependencies = [ dependencies = [
"proc-macro2", "tinyvec_macros",
"quote",
"syn",
] ]
[[package]] [[package]]
name = "tinystr" name = "tinyvec_macros"
version = "0.7.6" version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
dependencies = [
"displaydoc",
"zerovec",
]
[[package]] [[package]]
name = "tock-registers" name = "tock-registers"
@ -798,9 +743,9 @@ dependencies = [
[[package]] [[package]]
name = "uart_16550" name = "uart_16550"
version = "0.3.2" version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e492212ac378a5e00da953718dafb1340d9fbaf4f27d6f3c5cab03d931d1c049" checksum = "4922792855b1bce30997fbaa5418597902c278a92d20dfe348e6f062c3bd861d"
dependencies = [ dependencies = [
"bitflags 2.6.0", "bitflags 2.6.0",
"rustversion", "rustversion",
@ -808,10 +753,25 @@ dependencies = [
] ]
[[package]] [[package]]
name = "unicode-ident" name = "unicode-bidi"
version = "1.0.14" version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893"
[[package]]
name = "unicode-ident"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
[[package]]
name = "unicode-normalization"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956"
dependencies = [
"tinyvec",
]
[[package]] [[package]]
name = "unicode-xid" name = "unicode-xid"
@ -827,9 +787,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
[[package]] [[package]]
name = "ureq" name = "ureq"
version = "2.12.1" version = "2.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02d1a66277ed75f640d608235660df48c8e3c19f3b4edb6a263315626cc3c01d" checksum = "b74fc6b57825be3373f7054754755f03ac3a8f5d70015ccad699ba2029956f4a"
dependencies = [ dependencies = [
"base64", "base64",
"log", "log",
@ -842,27 +802,15 @@ dependencies = [
[[package]] [[package]]
name = "url" name = "url"
version = "2.5.4" version = "2.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c"
dependencies = [ dependencies = [
"form_urlencoded", "form_urlencoded",
"idna", "idna",
"percent-encoding", "percent-encoding",
] ]
[[package]]
name = "utf16_iter"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246"
[[package]]
name = "utf8_iter"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
[[package]] [[package]]
name = "versioning" name = "versioning"
version = "0.1.3" version = "0.1.3"
@ -884,14 +832,78 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]] [[package]]
name = "webpki-roots" name = "wasm-bindgen"
version = "0.26.7" version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d642ff16b7e79272ae451b7322067cdc17cadf68c23264be9d94a32319efe7e" checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e"
dependencies = [
"cfg-if",
"once_cell",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68"
dependencies = [
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d"
[[package]]
name = "webpki-roots"
version = "0.26.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958"
dependencies = [ dependencies = [
"rustls-pki-types", "rustls-pki-types",
] ]
[[package]]
name = "windows-core"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
dependencies = [
"windows-targets",
]
[[package]] [[package]]
name = "windows-sys" name = "windows-sys"
version = "0.52.0" version = "0.52.0"
@ -967,25 +979,13 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]] [[package]]
name = "winnow" name = "winnow"
version = "0.6.21" version = "0.6.20"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6f5bb5257f2407a5425c6e749bfd9692192a73e70a6060516ac04f889087d68" checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b"
dependencies = [ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "write16"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936"
[[package]]
name = "writeable"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
[[package]] [[package]]
name = "x2apic" name = "x2apic"
version = "0.4.3" version = "0.4.3"
@ -996,7 +996,7 @@ dependencies = [
"bitflags 1.3.2", "bitflags 1.3.2",
"paste", "paste",
"raw-cpuid 10.7.0", "raw-cpuid 10.7.0",
"x86_64 0.14.13", "x86_64 0.14.12",
] ]
[[package]] [[package]]
@ -1012,9 +1012,9 @@ dependencies = [
[[package]] [[package]]
name = "x86_64" name = "x86_64"
version = "0.14.13" version = "0.14.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c101112411baafbb4bf8d33e4c4a80ab5b02d74d2612331c61e8192fc9710491" checksum = "96cb6fd45bfeab6a5055c5bffdb08768bd0c069f1d946debe585bbb380a7c062"
dependencies = [ dependencies = [
"bit_field", "bit_field",
"bitflags 2.6.0", "bitflags 2.6.0",
@ -1024,9 +1024,9 @@ dependencies = [
[[package]] [[package]]
name = "x86_64" name = "x86_64"
version = "0.15.2" version = "0.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f042214de98141e9c8706e8192b73f56494087cc55ebec28ce10f26c5c364ae" checksum = "4bc79523af8abf92fb1a970c3e086c5a343f6bcc1a0eb890f575cbb3b45743df"
dependencies = [ dependencies = [
"bit_field", "bit_field",
"bitflags 2.6.0", "bitflags 2.6.0",
@ -1042,75 +1042,8 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "yoke"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40"
dependencies = [
"serde",
"stable_deref_trait",
"yoke-derive",
"zerofrom",
]
[[package]]
name = "yoke-derive"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
dependencies = [
"proc-macro2",
"quote",
"syn",
"synstructure",
]
[[package]]
name = "zerofrom"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e"
dependencies = [
"zerofrom-derive",
]
[[package]]
name = "zerofrom-derive"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808"
dependencies = [
"proc-macro2",
"quote",
"syn",
"synstructure",
]
[[package]] [[package]]
name = "zeroize" name = "zeroize"
version = "1.8.1" version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
[[package]]
name = "zerovec"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079"
dependencies = [
"yoke",
"zerofrom",
"zerovec-derive",
]
[[package]]
name = "zerovec-derive"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
dependencies = [
"proc-macro2",
"quote",
"syn",
]

View file

@ -1,77 +0,0 @@
# Style Guide
This style guide has two modes that a guideline may be.
`strict` means that prs will be rejected if they do not follow the guideline.
`loose` means that a pr would be accepted but should later be fixed.
## Empty Functions | loose
Empty functions are typically a sign of an unfinished program or driver.
In cases where there is a clear reason to have an empty function it will be allowed.
For example FakeAlloc is only empty functions because it is a example of an the allocator api.
### Allowed
```rust
/// in example.hb
a := fn(): void {}
```
### Not Allowed
```rust
/// in fat32.hb
a := fn(): void {}
```
## Magic Functions | loose
'Magic functions' are what I am calling small helper functions that do one or two things.
### Example
```rust
a := null
magic_a := fn(){
a = 10
}
```
The exact policy I want to have here is a bit fuzzy. I think that functions like this are nice in certain situations and not in others.
Regardless of if you use them or not, put a comment above the function explaining rational.
## Magic Numbers | loose
The policy on magic numbers is make them const and have a comment above them. Typically linking to a source of information about the magic number.
This helps cut down on magic numbers while making acceptable names and atleast half assed documentation.
Constants are inlined anyways, so its the same thing in the binary.
```rust
// The standard vga port is mapped at 0xB8000
$VGA_PTR := 0xB8000
```
## Tabs Vs Spaces | strict
I prefer for hblang code to use hard tabs.
The rational behind this is that a tab is `1 Indent` which some developers might want to be various different sizes when displayed
Soft tabs do not allow this user/editor specific as soft tabs always become spaces.
Bottom line is this is an accessibility feature.
There are some samples below.
```
\t means hard tab
\n means new line
\0x20 means space
```
### Allowed
```rust
if x == y {\n
\tlog(z)\n
}\n
```
### Not Allowed
```rust
if x == y {\n
\0x20\0x20\0x20\0x20log(z)\n
}\n
```

View file

@ -1,96 +0,0 @@
{
"nodes": {
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1732014248,
"narHash": "sha256-y/MEyuJ5oBWrWAic/14LaIr/u5E0wRVzyYsouYY3W6w=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "23e89b7da85c3640bbc2173fe04f4bd114342367",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1728538411,
"narHash": "sha256-f0SBJz1eZ2yOuKUr5CA9BHULGXVSn6miBuUWdTyhUhU=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b69de56fac8c2b6f8fd27f2eca01dcda8e0a4221",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs",
"rust-overlay": "rust-overlay"
}
},
"rust-overlay": {
"inputs": {
"nixpkgs": "nixpkgs_2"
},
"locked": {
"lastModified": 1732328983,
"narHash": "sha256-RHt12f/slrzDpSL7SSkydh8wUE4Nr4r23HlpWywed9E=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "ed8aa5b64f7d36d9338eb1d0a3bb60cf52069a72",
"type": "github"
},
"original": {
"owner": "oxalica",
"repo": "rust-overlay",
"type": "github"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

View file

@ -1,30 +0,0 @@
{
description = "A devShell example";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
rust-overlay.url = "github:oxalica/rust-overlay";
flake-utils.url = "github:numtide/flake-utils";
};
outputs = { self, nixpkgs, rust-overlay, flake-utils }:
flake-utils.lib.eachDefaultSystem (system:
let
overlays = [ (import rust-overlay) ];
pkgs = import nixpkgs {
inherit system overlays;
};
rustToolchain = pkgs.pkgsBuildHost.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml;
in
with pkgs;
{
devShells.default = mkShell {
buildInputs = [
rustToolchain
qemu_full
];
};
}
);
}

View file

@ -3,15 +3,12 @@ edition = "2021"
name = "kernel" name = "kernel"
version = "0.2.0" version = "0.2.0"
[features]
ktest = []
[dependencies] [dependencies]
# embedded-graphics = "0.8" # embedded-graphics = "0.8"
hbvm = { git = "https://git.ablecorp.us/AbleOS/holey-bytes.git", features = [ hbvm = { git = "https://git.ablecorp.us/AbleOS/holey-bytes.git", features = [
"nightly", "alloc", "disasm" "nightly",
] } ] }
ktest_macro = { path = "ktest_macro" }
log = "0.4" log = "0.4"
spin = "0.9" spin = "0.9"
slab = { version = "0.4", default-features = false } slab = { version = "0.4", default-features = false }
@ -27,6 +24,10 @@ version = "0.3"
default-features = false default-features = false
features = ["alloc", "nightly"] features = ["alloc", "nightly"]
# [dependencies.clparse]
# git = "https://git.ablecorp.us/ableos/ableos_userland"
# default-features = false
[dependencies.derive_more] [dependencies.derive_more]
version = "1" version = "1"
default-features = false default-features = false

View file

@ -1,11 +0,0 @@
[package]
edition = "2021"
name = "ktest_macro"
version = "0.1.0"
[lib]
proc-macro = true
[dependencies]
quote = "1.0.37"
syn = { version = "2.0.89", features = ["full"] }

View file

@ -1,86 +0,0 @@
extern crate proc_macro;
extern crate quote;
extern crate syn;
use {
proc_macro::TokenStream,
quote::quote,
syn::{parse::Parse, parse_macro_input, Expr, ItemFn, Token}
};
struct KtestInput {
lhs: Expr,
_comma: Token![,],
rhs: Expr,
}
impl Parse for KtestInput {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
Ok(Self {
lhs: input.parse()?,
_comma: input.parse()?,
rhs: input.parse()?,
})
}
}
#[proc_macro]
pub fn ktest_eq(item: TokenStream) -> TokenStream {
let input = parse_macro_input!(item as KtestInput);
let lhs = input.lhs;
let rhs = input.rhs;
let out = quote! {
if #lhs != #rhs {
return Err(name);
}
};
TokenStream::from(out)
}
#[proc_macro]
pub fn ktest_neq(item: TokenStream) -> TokenStream {
let input = parse_macro_input!(item as KtestInput);
let lhs = input.lhs;
let rhs = input.rhs;
let out = quote! {
if #lhs == #rhs {
return Err(name);
}
};
TokenStream::from(out)
}
#[proc_macro_attribute]
pub fn ktest(_attr: TokenStream, item: TokenStream) -> TokenStream {
let input = parse_macro_input!(item as ItemFn);
let test_name = &input.sig.ident;
let test_string = test_name.to_string();
let static_var_name = syn::Ident::new(
&format!("__ktest_{}", test_name).to_uppercase(),
test_name.span(),
);
let block = &input.block;
let out = quote! {
#[cfg(feature = "ktest")]
fn #test_name() -> Result<String, String> {
use crate::alloc::string::ToString;
let name = #test_string.to_string();
#block
return Ok(name);
}
#[cfg(feature = "ktest")]
#[unsafe(link_section = ".note.ktest")]
#[used]
pub static #static_var_name: fn() -> Result<String, String> = #test_name;
};
TokenStream::from(out)
}

View file

@ -6,11 +6,6 @@ SECTIONS
.text.boot : { *(.text.boot) } .text.boot : { *(.text.boot) }
.text : { *(.text) } .text : { *(.text) }
.data : { *(.data) } .data : { *(.data) }
.note.ktest : {
__ktest_start = .;
*(.note.ktest)
__ktest_end = .;
}
.rodata : { *(.rodata) } .rodata : { *(.rodata) }
.bss : { .bss : {
*(COMMON) *(COMMON)

View file

@ -38,15 +38,7 @@ SECTIONS
.data : { .data : {
*(.data .data.*) *(.data .data.*)
*(.got .got.*)
} :data } :data
/* Add the .ktest section for test functions */
.note.ktest : {
__ktest_start = .; /* Mark the beginning of the section */
*(.note.ktest) /* Include all items in the .ktest section */
__ktest_end = .; /* Mark the end of the section */
}
.bss : { .bss : {
*(COMMON) *(COMMON)

View file

@ -14,29 +14,3 @@ arch_cond!(
riscv64: "riscv64", riscv64: "riscv64",
x86_64: "x86_64", x86_64: "x86_64",
); );
#[cfg(target_arch = "x86_64")]
use {crate::arch::interrupts::Interrupt, alloc::string::String};
#[cfg(target_arch = "x86_64")]
pub struct InterruptList {
list: HashMap<Interrupt, String>,
}
#[cfg(target_arch = "x86_64")]
use hashbrown::HashMap;
#[cfg(target_arch = "x86_64")]
impl InterruptList {
pub fn new() -> Self {
Self {
list: HashMap::new(),
}
}
}
#[cfg(target_arch = "x86_64")]
use spin::{Lazy, Mutex};
#[cfg(target_arch = "x86_64")]
pub static INTERRUPT_LIST: Lazy<Mutex<InterruptList>> = Lazy::new(|| {
let mut il = InterruptList::new();
use crate::alloc::string::ToString;
il.list.insert(Interrupt::Timer, "PS/2 Mouse".to_string());
Mutex::new(il)
});

View file

@ -11,9 +11,7 @@ static mut LAPIC: LocalApic = unsafe { MaybeUninit::zeroed().assume_init() };
static mut IDT: InterruptDescriptorTable = unsafe { MaybeUninit::zeroed().assume_init() }; static mut IDT: InterruptDescriptorTable = unsafe { MaybeUninit::zeroed().assume_init() };
#[repr(u8)] #[repr(u8)]
#[derive(Debug, Eq, Hash, PartialEq)] enum Interrupt {
pub enum Interrupt {
Timer = 32, Timer = 32,
ApicErr = u8::MAX - 1, ApicErr = u8::MAX - 1,
Spurious = u8::MAX, Spurious = u8::MAX,
@ -62,52 +60,17 @@ extern "x86-interrupt" fn page_fault(
} }
extern "x86-interrupt" fn timer(_isf: InterruptStackFrame) { extern "x86-interrupt" fn timer(_isf: InterruptStackFrame) {
interrupt(Interrupt::Timer);
unsafe { unsafe {
LAPIC.end_of_interrupt(); LAPIC.end_of_interrupt();
} }
} }
extern "x86-interrupt" fn apic_err(_: InterruptStackFrame) { extern "x86-interrupt" fn apic_err(_: InterruptStackFrame) {
interrupt(Interrupt::ApicErr);
panic!("Internal APIC error"); panic!("Internal APIC error");
} }
extern "x86-interrupt" fn spurious(_: InterruptStackFrame) { extern "x86-interrupt" fn spurious(_: InterruptStackFrame) {
interrupt(Interrupt::Spurious);
unsafe { unsafe {
LAPIC.end_of_interrupt(); LAPIC.end_of_interrupt();
} }
} }
#[allow(unused_imports)]
fn interrupt(interrupt_type: Interrupt) {
use crate::{arch::INTERRUPT_LIST, kmain::EXECUTOR};
// let il = INTERRUPT_LIST.lock();
// let val = il.list.get(&interrupt_type).unwrap();
// use crate::holeybytes::kernel_services::service_definition_service::sds_search_service;
// let buffer = sds_search_service(val);
// if buffer != 0 {
// use {crate::kmain::IPC_BUFFERS, alloc::vec::Vec};
// let mut buffs = IPC_BUFFERS.lock();
// match buffs.get_mut(&buffer) {
// Some(buff) => {
// let mut msg_vec = Vec::new();
// msg_vec.push(0xFF);
// buff.push(msg_vec.to_vec());
// log::debug!("Sent Message {:?} to Buffer({})", msg_vec, buffer);
// }
// None => {
// log::error!("Access of non-existent buffer {}", buffer)
// }
// }
// }
unsafe {
EXECUTOR.send_interrupt(interrupt_type as u8);
}
}

View file

@ -33,7 +33,7 @@ const INITIAL_KERNEL_HEAP_SIZE: *const () = _initial_kernel_heap_size as _;
#[cfg(not(target_feature = "avx2"))] #[cfg(not(target_feature = "avx2"))]
unsafe extern "C" fn _kernel_start() -> ! { unsafe extern "C" fn _kernel_start() -> ! {
// Initialise SSE, then jump to kernel entrypoint // Initialise SSE, then jump to kernel entrypoint
core::arch::naked_asm!( core::arch::asm!(
// Initialise SSE // Initialise SSE
"mov rax, cr0", "mov rax, cr0",
"and ax, 0xfffb", "and ax, 0xfffb",
@ -46,6 +46,7 @@ unsafe extern "C" fn _kernel_start() -> ! {
// Jump to the kernel entry point // Jump to the kernel entry point
"jmp {}", "jmp {}",
sym start, sym start,
options(noreturn),
) )
} }
@ -53,7 +54,7 @@ unsafe extern "C" fn _kernel_start() -> ! {
#[naked] #[naked]
#[cfg(target_feature = "avx2")] #[cfg(target_feature = "avx2")]
unsafe extern "C" fn _kernel_start() -> ! { unsafe extern "C" fn _kernel_start() -> ! {
core::arch::naked_asm!( core::arch::asm!(
// Enable protected mode and configure control registers // Enable protected mode and configure control registers
"mov rax, cr0", "mov rax, cr0",
"and ax, 0xFFFB", // Clear CR0.EM (bit 2) for coprocessor emulation "and ax, 0xFFFB", // Clear CR0.EM (bit 2) for coprocessor emulation
@ -99,6 +100,7 @@ unsafe extern "C" fn _kernel_start() -> ! {
"jmp {0}", "jmp {0}",
sym start, sym start,
sym oops, sym oops,
options(noreturn),
) )
} }
@ -109,7 +111,7 @@ unsafe extern "C" fn oops() -> ! {
unsafe extern "C" fn start() -> ! { unsafe extern "C" fn start() -> ! {
logging::init(); logging::init();
crate::logger::init().expect("failed to set logger"); crate::logger::init().expect("failed to set logger");
log::debug!("Initialising AKern {}", crate::VERSION); log::info!("Initialising AKern {}", crate::VERSION);
static HDHM_REQ: HhdmRequest = HhdmRequest::new(0); static HDHM_REQ: HhdmRequest = HhdmRequest::new(0);
memory::init_pt(VirtAddr::new( memory::init_pt(VirtAddr::new(
@ -188,7 +190,7 @@ unsafe extern "C" fn start() -> ! {
// TODO: Add in rdseed and rdrand as sources for randomness // TODO: Add in rdseed and rdrand as sources for randomness
let _rand = xml::XMLElement::new("Random"); let _rand = xml::XMLElement::new("Random");
log::debug!("Getting boot modules"); log::trace!("Getting boot modules");
let bm = MOD_REQ.get_response().get(); let bm = MOD_REQ.get_response().get();
let mut bootmodules = alloc::vec::Vec::new(); let mut bootmodules = alloc::vec::Vec::new();
@ -226,7 +228,7 @@ unsafe extern "C" fn start() -> ! {
break; break;
} }
} }
log::debug!("Boot module count: {:?}", bootmodules.len()); log::info!("Boot module count: {:?}", bootmodules.len());
assert_eq!(bm.module_count, bootmodules.len() as u64); assert_eq!(bm.module_count, bootmodules.len() as u64);
} }

View file

@ -69,7 +69,7 @@ pub fn check_device(bus: u8, device: u8) -> Option<PciDeviceInfo> {
} }
let (reg2, addr) = unsafe { pci_config_read_2(bus, device, 0, 0x8) }; let (reg2, addr) = unsafe { pci_config_read_2(bus, device, 0, 0x8) };
log::debug!("pci device-({}) addr {} is {}", device, addr, reg2); log::info!("pci device-({}) addr {} is {}", device, addr, reg2);
let class = ((reg2 >> 16) & 0x0000_FFFF) as u16; let class = ((reg2 >> 16) & 0x0000_FFFF) as u16;
let pci_class = PciFullClass::from_u16(class); let pci_class = PciFullClass::from_u16(class);
let header_type = get_header_type(bus, device, 0); let header_type = get_header_type(bus, device, 0);

View file

@ -1,17 +1,8 @@
//! Environment call handling routines //! Environment call handling routines
use {alloc::boxed::Box, core::cell::LazyCell, hbvm::mem::Address}; use crate::holeybytes::kernel_services::{
block_read, dt_msg_handler::dt_msg_handler, logging_service::log_msg_handler,
use crate::{ service_definition_service::sds_msg_handler,
holeybytes::{
kernel_services::{
block_read, dt_msg_handler::dt_msg_handler, logging_service::log_msg_handler,
service_definition_service::sds_msg_handler,
},
ExecThread,
},
kmain::EXECUTOR,
task::Executor,
}; };
use { use {
@ -33,7 +24,7 @@ unsafe fn x86_in<T: x86_64::instructions::port::PortRead>(address: u16) -> T {
} }
#[inline(always)] #[inline(always)]
pub fn handler(vm: &mut Vm, pid: &usize) { pub fn handler(vm: &mut Vm) {
let ecall_number = vm.registers[2].cast::<u64>(); let ecall_number = vm.registers[2].cast::<u64>();
match ecall_number { match ecall_number {
@ -67,10 +58,10 @@ pub fn handler(vm: &mut Vm, pid: &usize) {
true => IpcBuffer::new(true, length), true => IpcBuffer::new(true, length),
}, },
); );
info!("Buffer ID: {}", buff_id);
vm.registers[1] = hbvm::value::Value(buff_id); vm.registers[1] = hbvm::value::Value(buff_id);
} }
2 => { 2 => {
log::error!("Oops, deleting buffers is not implemented.")
// Delete buffer // Delete buffer
} }
3 => { 3 => {
@ -80,10 +71,6 @@ pub fn handler(vm: &mut Vm, pid: &usize) {
let length = vm.registers[5].cast::<u64>() as usize; let length = vm.registers[5].cast::<u64>() as usize;
trace!("IPC address: {:?}", mem_addr); trace!("IPC address: {:?}", mem_addr);
unsafe { LazyCell::<Executor>::get_mut(&mut EXECUTOR) }
.unwrap()
.send_buffer(buffer_id as usize);
match buffer_id { match buffer_id {
0 => match sds_msg_handler(vm, mem_addr, length) { 0 => match sds_msg_handler(vm, mem_addr, length) {
Ok(()) => {} Ok(()) => {}
@ -156,43 +143,6 @@ pub fn handler(vm: &mut Vm, pid: &usize) {
Ok(()) => {} Ok(()) => {}
Err(_) => log::error!("Improper dt query"), Err(_) => log::error!("Improper dt query"),
}, },
6 => unsafe {
let program = block_read(mem_addr, length);
// decode AbleOS Executable format
let header = &program[0..46];
let magic_slice = &header[0..3];
if magic_slice != [0x15, 0x91, 0xD2] {
log::error!("Invalid magic number at the start of executable.");
return;
}
let executable_format_version =
u32::from_le_bytes(header[3..7].try_into().unwrap());
let offset = if executable_format_version == 0 {
47
} else {
error!("Invalid executable format.");
return;
};
let code_length = u64::from_le_bytes(header[7..15].try_into().unwrap());
let data_length = u64::from_le_bytes(header[15..23].try_into().unwrap());
let end = (code_length + data_length) as usize;
log::debug!("{code_length} + {data_length} = {end}");
let thr = ExecThread::new(&program[offset..end], Address::new(0));
vm.registers[1] = Value(
LazyCell::<Executor>::get_mut(&mut EXECUTOR)
.unwrap()
.spawn(Box::pin(async move {
if let Err(e) = thr.await {
log::error!("{e:?}");
}
})) as u64,
);
log::debug!("spawned a process");
},
buffer_id => { buffer_id => {
let mut buffs = IPC_BUFFERS.lock(); let mut buffs = IPC_BUFFERS.lock();
@ -213,6 +163,7 @@ pub fn handler(vm: &mut Vm, pid: &usize) {
let buffer_id = vm.registers[3].cast::<u64>(); let buffer_id = vm.registers[3].cast::<u64>();
let map_ptr = vm.registers[4].cast::<u64>(); let map_ptr = vm.registers[4].cast::<u64>();
let max_length = vm.registers[5].cast::<u64>(); let max_length = vm.registers[5].cast::<u64>();
let mut buffs = IPC_BUFFERS.lock(); let mut buffs = IPC_BUFFERS.lock();
let buff: &mut IpcBuffer = match buffs.get_mut(&buffer_id) { let buff: &mut IpcBuffer = match buffs.get_mut(&buffer_id) {
Some(buff) => buff, Some(buff) => buff,
@ -231,7 +182,7 @@ pub fn handler(vm: &mut Vm, pid: &usize) {
} else { } else {
unsafe { unsafe {
let ptr = map_ptr as *mut u8; let ptr = map_ptr as *mut u8;
ptr.copy_from_nonoverlapping(msg.as_ptr(), msg.len()); ptr.copy_from(msg.as_ptr(), msg.len());
} }
debug!("Recieve {:?} from Buffer({})", msg, buffer_id); debug!("Recieve {:?} from Buffer({})", msg, buffer_id);
@ -246,28 +197,6 @@ pub fn handler(vm: &mut Vm, pid: &usize) {
vm.registers[3] = x vm.registers[3] = x
} }
} }
6 => {
// Wait till interrupt
use crate::kmain::EXECUTOR;
let interrupt_type = vm.registers[3].cast::<u8>();
debug!("Interrupt subscribed: {}", interrupt_type);
unsafe {
LazyCell::<Executor>::get_mut(&mut EXECUTOR)
.unwrap()
.interrupt_subscribe(*pid, interrupt_type);
}
}
7 => {
// Wait till buffer
use crate::kmain::EXECUTOR;
let buffer_id = vm.registers[3].cast::<u64>() as usize;
debug!("Buffer subscribed: {}", buffer_id);
unsafe {
LazyCell::<Executor>::get_mut(&mut EXECUTOR)
.unwrap()
.buffer_subscribe(*pid, buffer_id);
}
}
_ => { _ => {
log::error!("Syscall unknown {:?}{:?}", ecall_number, vm.registers); log::error!("Syscall unknown {:?}{:?}", ecall_number, vm.registers);
} }

View file

@ -9,20 +9,7 @@ use log::Record;
pub fn log_msg_handler(_vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(), LogError> { pub fn log_msg_handler(_vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(), LogError> {
let msg_vec = block_read(mem_addr, length); let msg_vec = block_read(mem_addr, length);
use log::Level::*; let log_level = msg_vec[0];
let log_level = match msg_vec[0] {
0 | 48 => Error,
1 | 49 => Warn,
2 | 50 => Info,
3 | 51 => Debug,
4 | 52 => Trace,
_ => {
return Err(LogError::InvalidLogFormat);
}
};
if log_level > log::max_level() {
return Ok(());
}
let strptr = u64::from_le_bytes(msg_vec[1..9].try_into().unwrap()); let strptr = u64::from_le_bytes(msg_vec[1..9].try_into().unwrap());
let strlen = u64::from_le_bytes(msg_vec[9..17].try_into().unwrap()) as usize; let strlen = u64::from_le_bytes(msg_vec[9..17].try_into().unwrap()) as usize;
@ -33,6 +20,18 @@ pub fn log_msg_handler(_vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(),
match core::str::from_utf8(&str) { match core::str::from_utf8(&str) {
Ok(strr) => { Ok(strr) => {
use log::Level::*;
let log_level = match log_level {
0 | 48 => Error,
1 | 49 => Warn,
2 | 50 => Info,
3 | 51 => Debug,
4 | 52 => Trace,
_ => {
return Err(LogError::InvalidLogFormat);
}
};
log::logger().log( log::logger().log(
&Record::builder() &Record::builder()
.args(format_args!("{}", strr)) .args(format_args!("{}", strr))

View file

@ -25,16 +25,42 @@ fn alloc_page(vm: &mut Vm, _mem_addr: u64, _length: usize) -> Result<(), MemoryS
} }
#[inline(always)] #[inline(always)]
unsafe fn memset(dest: *mut u8, src: *const u8, count: usize, size: usize) { unsafe fn memset(mut dest: *mut u8, src: *const u8, count: usize, size: usize) {
let total_size = count * size; const BLOCK_SIZE: usize = 64;
src.copy_to_nonoverlapping(dest, size); let mut remaining = count * size;
let mut copied = size; if remaining < 16 {
src.copy_to_nonoverlapping(dest, remaining);
return;
}
while copied < total_size { let mut buffer = [0u8; BLOCK_SIZE];
let copy_size = copied.min(total_size - copied); let mut buffer_size = size;
dest.add(copied).copy_from_nonoverlapping(dest, copy_size); src.copy_to_nonoverlapping(buffer.as_mut_ptr(), size);
copied += copy_size;
while core::intrinsics::likely(buffer_size * 2 <= BLOCK_SIZE) {
buffer
.as_mut_ptr()
.copy_to_nonoverlapping(buffer.as_mut_ptr().add(buffer_size), buffer_size);
buffer_size *= 2;
}
let buffer_ptr = buffer.as_ptr() as *const u64;
while (dest as usize) & 7 != 0 && remaining >= 8 {
buffer.as_ptr().copy_to_nonoverlapping(dest, 1);
dest = dest.add(1);
remaining -= 1;
}
while core::intrinsics::likely(remaining >= 8) {
*(dest as *mut u64) = *buffer_ptr;
dest = dest.add(8);
remaining -= 8;
}
if remaining > 0 {
buffer.as_ptr().copy_to_nonoverlapping(dest, remaining);
} }
} }
@ -48,24 +74,29 @@ pub fn memory_msg_handler(
let msg_type = msg_vec[0]; let msg_type = msg_vec[0];
match msg_type { match msg_type {
0 => unsafe { 0 => unsafe {
let page_count = u64::from_le_bytes(msg_vec[1..9].try_into().unwrap()) as usize; let page_count = msg_vec[1];
let ptr = alloc(Layout::from_size_align_unchecked(page_count * 4096, 1)); let ptr = alloc(Layout::from_size_align_unchecked(
page_count as usize * 4096,
8,
));
log::debug!("Allocating {} pages @ {:?}", page_count, ptr); log::debug!("Allocating {} pages @ {:x}", page_count, ptr as u64);
vm.registers[1] = hbvm::value::Value(ptr as u64); vm.registers[1] = hbvm::value::Value(ptr as u64);
log::debug!("Kernel ptr: {:x}", ptr as u64);
}, },
1 => unsafe { 1 => unsafe {
let page_count = u64::from_le_bytes(msg_vec[1..9].try_into().unwrap()) as usize; let page_count = msg_vec[1];
let mptr = u64::from_le_bytes(msg_vec[9..17].try_into().unwrap()) as *mut u8; let mptr_raw: [u8; 8] = msg_vec[2..10].try_into().unwrap();
log::debug!("Deallocating {} pages @ {:?}", page_count, mptr); let mptr: u64 = u64::from_le_bytes(mptr_raw);
log::debug!("Deallocating {} pages @ {:x}", page_count, mptr);
dealloc( dealloc(
mptr, mptr as *mut u8,
Layout::from_size_align_unchecked(page_count * 4096, 1), Layout::from_size_align_unchecked(page_count as usize * 4096, 8),
) )
}, },
2 => { 2 => {
@ -91,21 +122,18 @@ pub fn memory_msg_handler(
log::debug!(" {} pages", page_count); log::debug!(" {} pages", page_count);
} }
4 => unsafe { 4 => unsafe {
let count = u64::from_le_bytes(msg_vec[1..9].try_into().unwrap_unchecked()) as usize; let count = u32::from_le_bytes(msg_vec[1..5].try_into().unwrap_unchecked()) as usize;
let src = u64::from_le_bytes(msg_vec[9..17].try_into().unwrap_unchecked()) as *const u8; let src = u64::from_le_bytes(msg_vec[5..13].try_into().unwrap_unchecked()) as *const u8;
let dest = u64::from_le_bytes(msg_vec[17..25].try_into().unwrap_unchecked()) as *mut u8; let dest = u64::from_le_bytes(msg_vec[13..21].try_into().unwrap_unchecked()) as *mut u8;
debug_assert!(src.addr() & 0xFFFF000000000000 != 0);
debug_assert!(dest.addr() & 0xFFFF000000000000 != 0);
src.copy_to_nonoverlapping(dest, count); src.copy_to_nonoverlapping(dest, count);
}, },
5 => unsafe { 5 => unsafe {
let count = u64::from_le_bytes(msg_vec[1..9].try_into().unwrap_unchecked()) as usize; let count = u32::from_le_bytes(msg_vec[1..5].try_into().unwrap_unchecked()) as usize;
let size = u64::from_le_bytes(msg_vec[9..17].try_into().unwrap_unchecked()) as usize; let size = u32::from_le_bytes(msg_vec[5..9].try_into().unwrap_unchecked()) as usize;
let src = let src = u64::from_le_bytes(msg_vec[9..17].try_into().unwrap_unchecked()) as *const u8;
u64::from_le_bytes(msg_vec[17..25].try_into().unwrap_unchecked()) as *const u8; let dest = u64::from_le_bytes(msg_vec[17..25].try_into().unwrap_unchecked()) as *mut u8;
let dest = u64::from_le_bytes(msg_vec[25..33].try_into().unwrap_unchecked()) as *mut u8;
debug_assert!(src.addr() & 0xFFFF000000000000 != 0);
debug_assert!(dest.addr() & 0xFFFF000000000000 != 0);
memset(dest, src, count, size); memset(dest, src, count, size);
}, },
_ => { _ => {

View file

@ -92,7 +92,8 @@ fn sds_create_service(protocol: &'static str) -> u64 {
// let a: protocol::Protocol = protocol.into(); // let a: protocol::Protocol = protocol.into();
buff_id buff_id
} }
pub fn sds_search_service(protocol: &str) -> u64 {
fn sds_search_service(protocol: &str) -> u64 {
let services = SERVICES.lock(); let services = SERVICES.lock();
let compare = Protocol::from(protocol); let compare = Protocol::from(protocol);
for (bid, protocol_canidate) in &services.0 { for (bid, protocol_canidate) in &services.0 {

View file

@ -15,10 +15,8 @@ fn calc_start_of_page(ptr: u64) -> u64 {
panic!("unaligned"); panic!("unaligned");
} }
#[derive(Default)]
pub struct Memory { pub struct Memory {
// TODO: map page aligned segments of memory into a table or some sort here // TODO: map page aligned segments of memory into a table or some sort here
logger: hbvm::mem::InstrLogger,
} }
impl Memory { impl Memory {
@ -58,11 +56,4 @@ impl hbvm::mem::Memory for Memory {
unsafe fn prog_read<T: Copy>(&mut self, addr: Address) -> T { unsafe fn prog_read<T: Copy>(&mut self, addr: Address) -> T {
(addr.get() as *const T).read() (addr.get() as *const T).read()
} }
#[inline(always)]
fn log_instr(&mut self, _at: Address, _regs: &[hbvm::value::Value]) {
// log::debug!("exec: [{:02x}] {}", at.get(), unsafe {
// self.logger.display_instr(at, regs)
// });
}
} }

View file

@ -1,5 +1,5 @@
mod ecah; mod ecah;
pub mod kernel_services; mod kernel_services;
mod mem; mod mem;
use { use {
@ -36,7 +36,7 @@ impl ExecThread {
pub unsafe fn new(program: &[u8], entrypoint: Address) -> Self { pub unsafe fn new(program: &[u8], entrypoint: Address) -> Self {
let mut vm = Vm::new( let mut vm = Vm::new(
mem::Memory::default(), mem::Memory {},
Address::new(program.as_ptr() as u64 + entrypoint.get()), Address::new(program.as_ptr() as u64 + entrypoint.get()),
); );
@ -65,12 +65,7 @@ impl<'p> Future for ExecThread {
return Poll::Ready(Err(err)); return Poll::Ready(Err(err));
} }
Ok(VmRunOk::End) => return Poll::Ready(Ok(())), Ok(VmRunOk::End) => return Poll::Ready(Ok(())),
Ok(VmRunOk::Ecall) => ecah::handler( Ok(VmRunOk::Ecall) => ecah::handler(&mut self.vm),
&mut self.vm,
cx.ext()
.downcast_ref()
.expect("PID did not exist in Context"),
),
Ok(VmRunOk::Timer) => (), Ok(VmRunOk::Timer) => (),
Ok(VmRunOk::Breakpoint) => { Ok(VmRunOk::Breakpoint) => {
log::error!( log::error!(

View file

@ -8,10 +8,7 @@ use {
device_tree::DeviceTree, device_tree::DeviceTree,
holeybytes::ExecThread, holeybytes::ExecThread,
ipc::buffer::IpcBuffer, ipc::buffer::IpcBuffer,
task::Executor,
}, },
alloc::boxed::Box,
core::cell::LazyCell,
hashbrown::HashMap, hashbrown::HashMap,
hbvm::mem::Address, hbvm::mem::Address,
limine::{Framebuffer, FramebufferRequest, NonNullPtr}, limine::{Framebuffer, FramebufferRequest, NonNullPtr},
@ -22,18 +19,6 @@ use {
pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! { pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! {
debug!("Entered kmain"); debug!("Entered kmain");
#[cfg(feature = "ktest")]
{
use {
crate::ktest,
log::info,
};
info!("Running tests");
ktest::test_main();
loop {}
}
// let kcmd = build_cmd("Kernel Command Line", cmdline); // let kcmd = build_cmd("Kernel Command Line", cmdline);
// trace!("Cmdline: {kcmd:?}"); // trace!("Cmdline: {kcmd:?}");
@ -79,26 +64,14 @@ pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! {
"Graphics front ptr {:?}", "Graphics front ptr {:?}",
fb1.address.as_ptr().unwrap() as *const u8 fb1.address.as_ptr().unwrap() as *const u8
); );
log::info!("Started AbleOS");
let mut executor = crate::task::Executor::new(256);
unsafe { unsafe {
let executor = LazyCell::<Executor>::force_mut(&mut EXECUTOR);
for module in boot_modules.iter() { for module in boot_modules.iter() {
let cmd = module.cmd.trim_matches('"'); let cmd = module.cmd.trim_matches('"');
let cmd_len = cmd.len() as u64; let cmd_len = cmd.len() as u64;
log::info!( log::info!("Spawning {} with arguments \"{}\"", module.path, cmd);
"Starting {}",
module
.path
.split('/')
.last()
.unwrap()
.split('.')
.next()
.unwrap()
);
log::debug!("Spawning {} with arguments \"{}\"", module.path, cmd);
// decode AbleOS Executable format // decode AbleOS Executable format
let header = &module.bytes[0..46]; let header = &module.bytes[0..46];
@ -119,30 +92,27 @@ pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! {
let code_length = u64::from_le_bytes(header[7..15].try_into().unwrap()); let code_length = u64::from_le_bytes(header[7..15].try_into().unwrap());
let data_length = u64::from_le_bytes(header[15..23].try_into().unwrap()); let data_length = u64::from_le_bytes(header[15..23].try_into().unwrap());
let end = (code_length + data_length) as usize; let end = (code_length + data_length) as usize;
log::debug!("{code_length} + {data_length} = {end}"); log::info!("{code_length} + {data_length} = {end}");
let mut thr = ExecThread::new(&module.bytes[offset..end], Address::new(0)); let mut thr = ExecThread::new(&module.bytes[offset..end], Address::new(0));
if cmd_len > 0 { if cmd_len > 0 {
thr.set_arguments(cmd.as_ptr() as u64, cmd_len); thr.set_arguments(cmd.as_ptr() as u64, cmd_len);
} }
executor.spawn(Box::pin(async { executor.spawn(async move {
if let Err(e) = thr.await { if let Err(e) = thr.await {
log::error!("{e:?}"); log::error!("{e:?}");
} }
})); })
} }
debug!("Random number: {}", hardware_random_u64()); debug!("Random number: {}", hardware_random_u64());
executor.run(); executor.run();
}; };
crate::arch::spin_loop() crate::arch::spin_loop()
} }
// ! SAFETY: this is not threadsafe at all, like even a little bit.
// ! SERIOUSLY
pub static mut EXECUTOR: LazyCell<Executor> = LazyCell::new(|| Executor::new());
pub static DEVICE_TREE: Lazy<Mutex<DeviceTree>> = Lazy::new(|| { pub static DEVICE_TREE: Lazy<Mutex<DeviceTree>> = Lazy::new(|| {
let dt = DeviceTree::new(); let dt = DeviceTree::new();
Mutex::new(dt) Mutex::new(dt)
@ -160,3 +130,10 @@ pub static IPC_BUFFERS: Lazy<Mutex<IpcBuffers>> = Lazy::new(|| {
Mutex::new(bufs) Mutex::new(bufs)
}); });
#[test_case]
fn trivial_assertion() {
trace!("trivial assertion... ");
assert_eq!(1, 1);
info!("[ok]");
}

View file

@ -1,51 +0,0 @@
pub use ktest_macro::*;
use {
alloc::string::String,
log::{error, info},
};
extern "C" {
static __ktest_start: fn() -> Result<String, String>;
static __ktest_end: fn() -> Result<String, String>;
}
// TODO: Implement ktest for arm and riscv (Later problems, see below)
// Allow for arch specific tests (Leave for now)
// Should panic tests
// Test specific panic handler
pub fn test_main() {
unsafe {
let mut current_test = &__ktest_start as *const fn() -> Result<String, String>;
let test_end = &__ktest_end as *const fn() -> Result<String, String>;
let mut pass = 0;
let mut fail = 0;
while current_test < test_end {
let test_fn = *current_test;
let test_name = test_fn();
match test_name {
Ok(name) => {
info!("Test: {} passed", name);
pass += 1;
},
Err(name) => {
error!("Test: {} failed", name);
fail += 1;
}
}
current_test = current_test.add(1);
}
info!("{}/{} tests passed", pass, pass + fail);
}
}
#[ktest]
pub fn trivial_assertion() {
ktest_eq!(1, 1);
ktest_neq!(0, 1);
}

View file

@ -2,21 +2,20 @@
//! Named akern. //! Named akern.
//! Akern is woefully undersupported at the moment but we are looking to add support improve hardware discovery and make our lives as kernel and operating system developers easier and better //! Akern is woefully undersupported at the moment but we are looking to add support improve hardware discovery and make our lives as kernel and operating system developers easier and better
#![no_std] #![no_std]
#![no_main]
#![feature( #![feature(
slice_split_once, slice_split_once,
exclusive_wrapper, exclusive_wrapper,
new_uninit,
core_intrinsics, core_intrinsics,
abi_x86_interrupt, abi_x86_interrupt,
lazy_get,
alloc_error_handler, alloc_error_handler,
local_waker,
context_ext,
ptr_sub_ptr, ptr_sub_ptr,
custom_test_frameworks,
naked_functions, naked_functions,
pointer_is_aligned_to pointer_is_aligned_to
)] )]
#![allow(dead_code, internal_features, static_mut_refs)] #![test_runner(crate::test_runner)]
#![allow(dead_code, internal_features)]
extern crate alloc; extern crate alloc;
mod allocator; mod allocator;
@ -34,9 +33,6 @@ mod memory;
mod task; mod task;
mod utils; mod utils;
#[allow(improper_ctypes, non_upper_case_globals)]
mod ktest;
use versioning::Version; use versioning::Version;
/// Kernel's version /// Kernel's version
@ -49,7 +45,6 @@ pub const VERSION: Version = Version {
#[panic_handler] #[panic_handler]
#[cfg(target_os = "none")] #[cfg(target_os = "none")]
fn panic(info: &core::panic::PanicInfo) -> ! { fn panic(info: &core::panic::PanicInfo) -> ! {
use alloc::string::ToString;
arch::register_dump(); arch::register_dump();
if let Some(loc) = info.location() { if let Some(loc) = info.location() {
@ -61,7 +56,15 @@ fn panic(info: &core::panic::PanicInfo) -> ! {
)); ));
} }
let msg = info.message().to_string().replace("\n", "\r\n"); let msg = info.message();
let _ = crate::arch::log(format_args!("{msg}\r\n")); let _ = crate::arch::log(format_args!("{msg}\r\n"));
loop {} loop {}
} }
#[cfg(test)]
fn test_runner(tests: &[&dyn Fn()]) {
println!("Running {} tests", tests.len());
for test in tests {
test();
}
}

View file

@ -36,26 +36,13 @@ impl log::Log for Logger {
Level::Debug => "25", Level::Debug => "25",
Level::Trace => "103", Level::Trace => "103",
}; };
let module = record let module = record.module_path().unwrap_or_default();
.module_path() let line = record.line().unwrap_or_default();
.unwrap_or_default() crate::arch::log(format_args!(
.rsplit_once(':') "\x1b[38;5;{lvl_color}m{lvl}\x1b[0m [{module}:{line}]: {}\r\n",
.unwrap_or_default() record.args(),
.1; ))
if module == "" { .expect("write to serial console");
crate::arch::log(format_args!(
"\x1b[38;5;{lvl_color}m{lvl}\x1b[0m: {}\r\n",
record.args(),
))
.expect("write to serial console");
} else {
let line = record.line().unwrap_or_default();
crate::arch::log(format_args!(
"\x1b[38;5;{lvl_color}m{lvl}\x1b[0m [{module}:{line}]: {}\r\n",
record.args(),
))
.expect("write to serial console");
}
} }
fn flush(&self) {} fn flush(&self) {}

View file

@ -1,14 +1,9 @@
use { use {
alloc::{ alloc::{boxed::Box, sync::Arc},
boxed::Box,
collections::{BTreeMap, BTreeSet},
sync::Arc,
},
core::{ core::{
future::Future, future::Future,
pin::Pin, pin::Pin,
sync::atomic::{AtomicBool, Ordering}, task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
task::{Context, ContextBuilder, Poll, RawWaker, RawWakerVTable, Waker},
}, },
crossbeam_queue::SegQueue, crossbeam_queue::SegQueue,
slab::Slab, slab::Slab,
@ -19,6 +14,7 @@ pub fn yield_now() -> impl Future<Output = ()> {
impl Future for YieldNow { impl Future for YieldNow {
type Output = (); type Output = ();
#[inline(always)]
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
if self.0 { if self.0 {
Poll::Ready(()) Poll::Ready(())
@ -33,184 +29,150 @@ pub fn yield_now() -> impl Future<Output = ()> {
YieldNow(false) YieldNow(false)
} }
pub trait Process: Future<Output = ()> + Send {} pub struct Executor<F: Future<Output = ()> + Send> {
impl<T: Future<Output = ()> + Send> Process for T {} tasks: Slab<Task<F>>,
task_queue: Arc<TaskQueue>,
pub struct Executor {
tasks: Slab<Task>,
task_queue: Arc<SegQueue<usize>>,
interrupt_lookup: [Option<usize>; u8::MAX as usize],
buffer_lookup: BTreeMap<usize, BTreeSet<usize>>,
} }
impl Executor { impl<F: Future<Output = ()> + Send> Executor<F> {
pub fn new() -> Self { pub fn new(size: usize) -> Self {
Self { Self {
tasks: Slab::new(), tasks: Slab::with_capacity(size),
task_queue: Arc::new(SegQueue::new()), task_queue: Arc::new(TaskQueue::new()),
interrupt_lookup: [None; u8::MAX as usize],
buffer_lookup: BTreeMap::new(),
} }
} }
pub fn spawn(&mut self, future: Pin<Box<dyn Process>>) -> usize { #[inline]
let id = self.tasks.insert(Task::new(future)); pub fn spawn(&mut self, future: F) {
self.task_queue.push(id); self.task_queue
.queue
id .push(self.tasks.insert(Task::new(future)));
}
pub fn pause(&self, id: usize) {
if let Some(task) = self.tasks.get(id) {
task.set_paused(true);
}
}
pub fn unpause(&self, id: usize) {
if let Some(task) = self.tasks.get(id) {
task.set_paused(false);
self.task_queue.push(id);
}
}
pub fn interrupt_subscribe(&mut self, pid: usize, interrupt_type: u8) {
self.pause(pid);
self.interrupt_lookup[interrupt_type as usize] = Some(pid);
}
pub fn buffer_subscribe(&mut self, pid: usize, buffer_id: usize) {
self.pause(pid);
if let Some(buf) = self.buffer_lookup.get_mut(&buffer_id) {
buf.insert(pid);
} else {
self.buffer_lookup.insert(buffer_id, BTreeSet::from([pid]));
}
} }
pub fn run(&mut self) { pub fn run(&mut self) {
let mut task_batch = [0; 32]; let mut task_batch = [0; 32];
loop { let mut batch_len = 0;
let mut batch_len = 0;
while let Some(id) = self.task_queue.pop() { loop {
task_batch[batch_len] = id; self.task_queue.batch_pop(&mut task_batch, &mut batch_len);
batch_len += 1;
if batch_len == task_batch.len() { if batch_len == 0 {
if self.task_queue.is_empty() {
break; break;
} else {
continue;
} }
} }
if batch_len == 0 { for &id in &task_batch[..batch_len] {
// break;
continue;
}
for &(mut id) in &task_batch[..batch_len] {
if let Some(task) = self.tasks.get_mut(id) { if let Some(task) = self.tasks.get_mut(id) {
if task.is_paused() { let waker = task
continue; .waker
} .get_or_insert_with(|| TaskWaker::new(id, Arc::clone(&self.task_queue)));
let waker = create_waker(id, Arc::clone(&self.task_queue)); let waker = unsafe { Waker::from_raw(TaskWaker::into_raw_waker(waker)) };
let mut cx = ContextBuilder::from_waker(&waker).ext(&mut id).build(); let mut cx = Context::from_waker(&waker);
if let Poll::Ready(()) = task.poll(&mut cx) { if let Poll::Ready(()) = task.poll(&mut cx) {
self.tasks.remove(id); self.tasks.remove(id);
self.interrupt_lookup.map(|pid| { self.task_queue.free_tasks.push(id);
if let Some(pid) = pid {
if pid == id {
return None;
}
}
return pid;
});
self.buffer_lookup.iter_mut().for_each(|(_, pid_set)| {
pid_set.remove(&id);
});
} }
} }
} }
} }
} }
pub fn send_interrupt(&self, interrupt: u8) {
let id = self.interrupt_lookup[interrupt as usize];
if let Some(id) = id {
self.unpause(id);
}
}
pub fn send_buffer(&self, id: usize) {
if let Some(buf) = self.buffer_lookup.get(&id) {
buf.iter().for_each(|pid| self.unpause(*pid));
}
}
} }
struct Task { struct Task<F: Future<Output = ()> + Send> {
future: Pin<Box<dyn Process>>, future: Pin<Box<F>>,
paused: AtomicBool, waker: Option<TaskWaker>,
} }
impl Task { impl<F: Future<Output = ()> + Send> Task<F> {
fn new(future: Pin<Box<dyn Process>>) -> Self { #[inline(always)]
pub fn new(future: F) -> Self {
Self { Self {
future, future: Box::pin(future),
paused: AtomicBool::new(false), waker: None,
} }
} }
#[inline(always)]
fn poll(&mut self, cx: &mut Context) -> Poll<()> { fn poll(&mut self, cx: &mut Context) -> Poll<()> {
self.future.as_mut().poll(cx) self.future.as_mut().poll(cx)
} }
fn is_paused(&self) -> bool {
self.paused.load(Ordering::Acquire)
}
fn set_paused(&self, paused: bool) {
self.paused.store(paused, Ordering::Release)
}
} }
fn create_waker(task_id: usize, task_queue: Arc<SegQueue<usize>>) -> Waker {
let data = Box::new(TaskWaker {
task_id,
task_queue,
});
let raw_waker = RawWaker::new(Box::into_raw(data) as *const (), &VTABLE);
unsafe { Waker::from_raw(raw_waker) }
}
#[derive(Clone)]
struct TaskWaker { struct TaskWaker {
task_id: usize, id: usize,
task_queue: Arc<SegQueue<usize>>, task_queue: Arc<TaskQueue>,
} }
impl TaskWaker { impl TaskWaker {
#[inline(always)]
fn new(id: usize, task_queue: Arc<TaskQueue>) -> Self {
Self { id, task_queue }
}
#[inline(always)]
fn wake(&self) { fn wake(&self) {
self.task_queue.push(self.task_id); self.task_queue.queue.push(self.id);
}
fn into_raw_waker(waker: &TaskWaker) -> RawWaker {
let ptr = waker as *const TaskWaker;
RawWaker::new(ptr.cast(), &VTABLE)
} }
} }
const VTABLE: RawWakerVTable = RawWakerVTable::new(clone_raw, wake_raw, wake_by_ref_raw, drop_raw); const VTABLE: RawWakerVTable = RawWakerVTable::new(clone_raw, wake_raw, wake_by_ref_raw, drop_raw);
unsafe fn clone_raw(ptr: *const ()) -> RawWaker { unsafe fn clone_raw(ptr: *const ()) -> RawWaker {
let task_waker = Box::from_raw(ptr as *mut TaskWaker); let waker = &*(ptr as *const TaskWaker);
let raw_waker = RawWaker::new(Box::into_raw(task_waker.clone()) as *const (), &VTABLE); TaskWaker::into_raw_waker(waker)
raw_waker
} }
unsafe fn wake_raw(ptr: *const ()) { unsafe fn wake_raw(ptr: *const ()) {
let task_waker = Box::from_raw(ptr as *mut TaskWaker); let waker = &*(ptr as *const TaskWaker);
task_waker.wake(); waker.wake();
} }
unsafe fn wake_by_ref_raw(ptr: *const ()) { unsafe fn wake_by_ref_raw(ptr: *const ()) {
let task_waker = &*(ptr as *const TaskWaker); let waker = &*(ptr as *const TaskWaker);
task_waker.wake(); waker.wake();
} }
unsafe fn drop_raw(ptr: *const ()) { unsafe fn drop_raw(_: *const ()) {}
drop(Box::from_raw(ptr as *mut TaskWaker));
struct TaskQueue {
queue: SegQueue<usize>,
next_task: usize,
free_tasks: SegQueue<usize>,
}
impl TaskQueue {
fn new() -> Self {
Self {
queue: SegQueue::new(),
next_task: 0,
free_tasks: SegQueue::new(),
}
}
#[inline(always)]
fn batch_pop(&self, output: &mut [usize], len: &mut usize) {
*len = 0;
while let Some(id) = self.queue.pop() {
output[*len] = id;
*len += 1;
if *len == output.len() {
break;
}
}
}
#[inline(always)]
fn is_empty(&self) -> bool {
self.queue.is_empty()
}
} }

View file

@ -1,25 +1,25 @@
{ {
"arch": "aarch64", "arch": "aarch64",
"data-layout": "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32", "data-layout": "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128",
"disable-redzone": true, "disable-redzone": true,
"env": "", "env": "",
"executables": true, "executables": true,
"features": "+strict-align,+neon,+fp-armv8", "features": "+strict-align,+neon,+fp-armv8",
"linker": "rust-lld", "linker": "rust-lld",
"linker-flavor": "ld.lld", "linker-flavor": "ld.lld",
"linker-is-gnu": true, "linker-is-gnu": true,
"pre-link-args": { "pre-link-args": {
"ld.lld": [ "ld.lld": [
"-Tkernel/lds/aarch64-qemu.ld" "-Tkernel/lds/aarch64-qemu.ld"
] ]
}, },
"llvm-target": "aarch64-unknown-none", "llvm-target": "aarch64-unknown-none",
"max-atomic-width": 128, "max-atomic-width": 128,
"os": "none", "os": "none",
"panic-strategy": "abort", "panic-strategy": "abort",
"relocation-model": "static", "relocation-model": "static",
"target-c-int-width": "32", "target-c-int-width": "32",
"target-endian": "little", "target-endian": "little",
"target-pointer-width": "64", "target-pointer-width": "64",
"vendor": "ablecorp" "vendor": ""
} }

View file

@ -6,16 +6,29 @@ edition = "2021"
[dependencies] [dependencies]
str-reader = "0.1" str-reader = "0.1"
derive_more = { version = "1", default-features = false, features = [ derive_more = { version = "1", default-features = false, features = [
"add",
"add_assign",
"constructor",
"display", "display",
"from",
"into",
"mul",
"mul_assign",
"not",
"sum",
] } ] }
error-stack = "0.5" error-stack = "0.5"
fatfs = { version = "0.3", default-features = false, features = [ fatfs = "0.3"
"std",
"alloc",
] }
toml = "0.8" toml = "0.8"
hblang.git = "https://git.ablecorp.us/AbleOS/holey-bytes.git" hblang = { git = "https://git.ablecorp.us/AbleOS/holey-bytes.git", features = [
# hblang.path = "../../holey-bytes/lang/" "std",
"opts",
], default-features = false }
log = "0.4" log = "0.4"
raw-cpuid = "11" raw-cpuid = "11"
ureq = { version = "2", default-features = false, features = ["tls"] } ureq = { version = "2", default-features = false, features = ["tls"] }
# [dependencies.reqwest]
# version = "0.12"
# default-features = false
# features = ["rustls-tls", "blocking"]

View file

@ -1,6 +1,5 @@
#![allow(unused)] #![allow(unused)]
use std::{ use std::{
collections::HashMap,
fmt::format, fmt::format,
fs::{read_to_string, File}, fs::{read_to_string, File},
io::{BufWriter, Write}, io::{BufWriter, Write},
@ -14,7 +13,6 @@ pub struct Package {
name: String, name: String,
binaries: Vec<String>, binaries: Vec<String>,
build_cmd: String, build_cmd: String,
args: HashMap<String, String>,
} }
impl Package { impl Package {
@ -48,47 +46,48 @@ impl Package {
let mut binaries = vec![]; let mut binaries = vec![];
for (count, (name, table)) in bin_table.into_iter().enumerate() { for (count, (name, table)) in bin_table.into_iter().enumerate() {
// if count != 0 {
println!("{}", name);
binaries.push(name.clone()); binaries.push(name.clone());
// }
} }
let build_table = data.get("build").unwrap(); let build_table = data.get("build").unwrap();
let mut build_cmd: String = build_table.get("command").unwrap().as_str().unwrap().into(); let mut build_cmd: String = build_table.get("command").unwrap().as_str().unwrap().into();
build_cmd.remove(0); build_cmd.remove(0);
let mut args: HashMap<String, String> = match build_table.get("args") { // build_cmd.pop();
None => HashMap::new(),
Some(v) => v
.as_table()
.unwrap()
.into_iter()
.map(|(k, v)| (k.clone(), v.to_string()))
.collect::<HashMap<String, String>>(),
};
Self { Self {
name, name,
binaries, binaries,
build_cmd, build_cmd,
args,
} }
} }
pub fn build(&self, out: &mut Vec<u8>) -> std::io::Result<()> { pub fn build(&self) -> std::io::Result<()> {
if self.binaries.contains(&"hblang".to_string()) { if self.binaries.contains(&"hblang".to_string()) {
let file = self.build_cmd.split_ascii_whitespace().last().unwrap(); let file = self.build_cmd.split_ascii_whitespace().last().unwrap();
let path = format!("sysdata/programs/{}/{}", self.name, file);
// compile here
let mut warnings = String::new(); let path = format!("sysdata/programs/{}/{}", self.name, file);
let mut bytes = Vec::new();
// compile here
hblang::run_compiler( hblang::run_compiler(
&path, &path,
Options { Options {
fmt: true, fmt: true,
resolver: Some(hblang::ABLEOS_PATH_RESOLVER), optimize: true,
..Default::default() ..Default::default()
}, },
out, &mut bytes,
&mut warnings, )?;
hblang::run_compiler(
&path,
Options {
optimize: true,
..Default::default()
},
&mut bytes,
)?; )?;
match std::fs::create_dir("target/programs") { match std::fs::create_dir("target/programs") {
@ -96,33 +95,18 @@ impl Package {
Err(e) if e.kind() == std::io::ErrorKind::AlreadyExists => (), Err(e) if e.kind() == std::io::ErrorKind::AlreadyExists => (),
Err(e) => panic!("{}", e), Err(e) => panic!("{}", e),
} }
std::fs::write(format!("target/programs/{}.hbf", self.name), &bytes).unwrap();
bytes.clear();
hblang::run_compiler( hblang::run_compiler(
&path, &path,
Options { Options {
resolver: Some(hblang::ABLEOS_PATH_RESOLVER),
..Default::default()
},
out,
&mut warnings,
)?;
std::fs::write(format!("target/programs/{}.hbf", self.name), &out)?;
out.clear();
let err = hblang::run_compiler(
&path,
Options {
resolver: Some(hblang::ABLEOS_PATH_RESOLVER),
dump_asm: true, dump_asm: true,
optimize: true,
..Default::default() ..Default::default()
}, },
out, &mut bytes,
&mut warnings, )?;
); std::fs::write(format!("target/programs/{}.hba", self.name), &bytes).unwrap();
std::fs::write(format!("target/programs/{}.hba", self.name), &out)?;
out.clear();
return err;
} }
Ok(()) Ok(())
} }

View file

@ -1,7 +1,6 @@
mod dev; mod dev;
use { use {
core::fmt::Write as _,
derive_more::Display, derive_more::Display,
dev::Package, dev::Package,
error_stack::{bail, report, Context, Report, Result, ResultExt}, error_stack::{bail, report, Context, Report, Result, ResultExt},
@ -27,7 +26,6 @@ fn main() -> Result<(), Error> {
let mut release = false; let mut release = false;
let mut debuginfo = false; let mut debuginfo = false;
let mut target = Target::X86_64; let mut target = Target::X86_64;
let mut tests = false;
for arg in args { for arg in args {
if arg == "-r" || arg == "--release" { if arg == "-r" || arg == "--release" {
release = true; release = true;
@ -39,42 +37,17 @@ fn main() -> Result<(), Error> {
target = Target::Aarch64; target = Target::Aarch64;
} else if arg == "avx2" { } else if arg == "avx2" {
target = Target::X86_64Avx2; target = Target::X86_64Avx2;
} else if arg == "--ktest" {
tests = true;
} else { } else {
return Err(report!(Error::InvalidSubCom)); return Err(report!(Error::InvalidSubCom));
} }
} }
build(release, target, debuginfo, tests).change_context(Error::Build) build(release, target, debuginfo).change_context(Error::Build)
} }
// Some("test" | "t") => {
// let mut release = false;
// let mut debuginfo = false;
// let mut target = Target::X86_64;
// for arg in args {
// if arg == "-r" || arg == "--release" {
// release = true;
// } else if arg == "-d" || arg == "--debuginfo" {
// debuginfo = true;
// } else if arg == "rv64" || arg == "riscv64" || arg == "riscv64-virt" {
// target = Target::Riscv64Virt;
// } else if arg == "arm64" || arg == "aarch64" || arg == "aarch64-virt" {
// target = Target::Aarch64;
// } else if arg == "avx2" {
// target = Target::X86_64Avx2;
// } else {
// return Err(report!(Error::InvalidSubCom));
// }
// }
// test(release, target, debuginfo).change_context(Error::Build)
// }
Some("run" | "r") => { Some("run" | "r") => {
let mut release = false; let mut release = false;
let mut debuginfo = false; let mut debuginfo = false;
let mut target = Target::X86_64; let mut target = Target::X86_64;
let mut tests = false;
let mut do_accel = true; let mut do_accel = true;
for arg in args { for arg in args {
if arg == "-r" || arg == "--release" { if arg == "-r" || arg == "--release" {
@ -89,14 +62,12 @@ fn main() -> Result<(), Error> {
do_accel = false; do_accel = false;
} else if arg == "avx2" { } else if arg == "avx2" {
target = Target::X86_64Avx2; target = Target::X86_64Avx2;
} else if arg == "--ktest" {
tests = true;
} else { } else {
return Err(report!(Error::InvalidSubCom)); return Err(report!(Error::InvalidSubCom));
} }
} }
build(release, target, debuginfo, tests)?; build(release, target, debuginfo)?;
run(release, target, do_accel) run(release, target, do_accel)
} }
Some("help" | "h") => { Some("help" | "h") => {
@ -110,7 +81,6 @@ fn main() -> Result<(), Error> {
" -r / --release: build in release mode\n", " -r / --release: build in release mode\n",
" -d / --debuginfo: build with debug info\n", " -d / --debuginfo: build with debug info\n",
" --noaccel: run without acceleration (e.g, no kvm)\n", " --noaccel: run without acceleration (e.g, no kvm)\n",
" --ktest: Enables tests via ktest\n",
"[ rv64 / riscv64 / riscv64-virt / aarch64 / arm64 / aarch64-virt / avx2 ]: sets target" "[ rv64 / riscv64 / riscv64-virt / aarch64 / arm64 / aarch64-virt / avx2 ]: sets target"
),); ),);
Ok(()) Ok(())
@ -234,9 +204,6 @@ TERM_BACKDROP={}
let modules = value.get_mut("modules").unwrap().as_table_mut().unwrap(); let modules = value.get_mut("modules").unwrap().as_table_mut().unwrap();
// let mut real_modules = modules.clone(); // let mut real_modules = modules.clone();
let mut errors = String::new();
let mut out = Vec::new();
modules modules
.into_iter() .into_iter()
.map(|(_, value)| -> Result<(), io::Error> { .map(|(_, value)| -> Result<(), io::Error> {
@ -251,26 +218,11 @@ TERM_BACKDROP={}
let p = Package::load_from_file( let p = Package::load_from_file(
format!("sysdata/programs/{}/meta.toml", path).to_owned(), format!("sysdata/programs/{}/meta.toml", path).to_owned(),
); );
match p.build(&mut out) { p.build()?;
Ok(()) => {}
Err(e) => {
writeln!(errors, "========= while compiling {} {} =========", path, e)
.unwrap();
errors.push_str(&String::from_utf8_lossy(&out));
out.clear();
}
}
} }
Ok(()) Ok(())
}) })
.for_each(drop); .for_each(drop);
if !errors.is_empty() {
let _ = writeln!(errors, "!!! STOPPING DUE TO PREVIOUS ERRORS !!!");
std::eprint!("{errors}");
continue;
}
modules.into_iter().for_each(|(_key, value)| { modules.into_iter().for_each(|(_key, value)| {
if value.is_table() { if value.is_table() {
let path = value.get("path").expect("You must have `path` as a value"); let path = value.get("path").expect("You must have `path` as a value");
@ -339,7 +291,7 @@ fn copy_file_to_img(fpath: &str, fs: &FileSystem<File>) {
.expect("Copy failed"); .expect("Copy failed");
} }
fn build(release: bool, target: Target, debuginfo: bool, tests: bool) -> Result<(), Error> { fn build(release: bool, target: Target, debuginfo: bool) -> Result<(), Error> {
let fs = get_fs().change_context(Error::Io)?; let fs = get_fs().change_context(Error::Io)?;
let mut com = Command::new("cargo"); let mut com = Command::new("cargo");
com.current_dir("kernel"); com.current_dir("kernel");
@ -351,10 +303,6 @@ fn build(release: bool, target: Target, debuginfo: bool, tests: bool) -> Result<
com.env("RUSTFLAGS", "-Cdebug-assertions=true"); com.env("RUSTFLAGS", "-Cdebug-assertions=true");
} }
if tests {
com.args(["--features", "ktest"]);
}
if target == Target::Riscv64Virt { if target == Target::Riscv64Virt {
com.args(["--target", "targets/riscv64-virt-ableos.json"]); com.args(["--target", "targets/riscv64-virt-ableos.json"]);
} }
@ -411,7 +359,6 @@ fn run(release: bool, target: Target, do_accel: bool) -> Result<(), Error> {
}; };
let (mut com, mut com2) = (Command::new(target_str), Command::new(target_str)); let (mut com, mut com2) = (Command::new(target_str), Command::new(target_str));
let ovmf_path = fetch_ovmf(target); let ovmf_path = fetch_ovmf(target);
#[cfg(target_arch = "x86_64")]
let accel = if do_accel { let accel = if do_accel {
let supported = String::from_utf8( let supported = String::from_utf8(
com2.args(["--accel", "help"]) com2.args(["--accel", "help"])
@ -447,24 +394,16 @@ fn run(release: bool, target: Target, do_accel: bool) -> Result<(), Error> {
} else { } else {
"accel=tcg" "accel=tcg"
}; };
#[cfg(not(target_arch = "x86_64"))]
let accel = "accel=tcg";
match target { match target {
Target::X86_64 | Target::X86_64Avx2 => { Target::X86_64 | Target::X86_64Avx2 => {
#[rustfmt::skip] #[rustfmt::skip]
com.args([ com.args([
"-bios", &ovmf_path.change_context(Error::OvmfFetch)?, "-bios", &ovmf_path.change_context(Error::OvmfFetch)?,
//"-hda", "target/disk.img", "-drive", "file=target/disk.img,format=raw",
"-drive", "file=target/disk.img,index=0,if=ide,format=raw",
"-device", "vmware-svga", "-device", "vmware-svga",
// "-serial", "stdio",
"-m", "2G", "-m", "2G",
"-smp", "1", "-smp", "1",
"-audiodev",
"pa,id=speaker",
"-machine",
"pcspk-audiodev=speaker",
"-parallel", "none", "-parallel", "none",
"-monitor", "none", "-monitor", "none",
"-machine", accel, "-machine", accel,
@ -490,7 +429,7 @@ fn run(release: bool, target: Target, do_accel: bool) -> Result<(), Error> {
#[rustfmt::skip] #[rustfmt::skip]
com.args([ com.args([
"-M", "virt", "-M", "virt",
"-cpu", "max", "-cpu", "neoverse-n2",
"-device", "ramfb", "-device", "ramfb",
"-device", "qemu-xhci", "-device", "qemu-xhci",
"-device", "usb-kbd", "-device", "usb-kbd",

View file

@ -1,7 +1,3 @@
[toolchain] [toolchain]
# old toolchain channel = "nightly-2024-07-27"
# channel = "nightly-2024-07-27"
# last stable
# channel = "nightly-2024-11-20"
channel = "nightly"
components = ["rust-src", "llvm-tools"] components = ["rust-src", "llvm-tools"]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

Binary file not shown.

View file

@ -1,4 +0,0 @@
(horizontal
spacing : 10
(label "hi")
(label "goodbye"))

View file

@ -1 +0,0 @@
(label "hello")

View file

@ -1,3 +0,0 @@
(vertical
(label "hello")
(label "hello" color:red))

View file

@ -5,37 +5,42 @@ render := @use("../../../libraries/render/src/lib.hb")
input := @use("../../intouch/src/lib.hb") input := @use("../../intouch/src/lib.hb")
widgets := @use("widgets/widgets.hb") widgets := @use("widgets.hb")
ui := @use("ui.hb")
WindowID := struct { WindowID := struct {
host_id: uint, host_id: int,
window_id: uint, window_id: int,
} }
VoidWindowID := WindowID.(0, 0) VoidWindowID := WindowID.(0, 0)
create_window := fn(channel: uint): ^render.Surface { create_window := fn(channel: int): ^render.Surface {
// get the horizon buffer // get the horizon buffer
// request a new window and provide the callback buffer // request a new window and provide the callback buffer
// wait to recieve a message // wait to recieve a message
windowing_system_buffer := buffer.search("XHorizon") windowing_system_buffer := buffer.search("XHorizon\0")
mem_buf := memory.request_page(1) mem_buf := memory.request_page(1)
if windowing_system_buffer == 0 { if windowing_system_buffer == 0 {
return @as(^render.Surface, idk) return @as(^render.Surface, idk)
} else { } else {
// ! bad able, stop using string messages :ragey:
// msg := "\{01}\0"
// msg_length := 2
// @as(void, @eca(3, windowing_system_buffer, msg, msg_length))
x := 0 x := 0
loop if x > 1000 break else x += 1 loop if x > 1000 break else x += 1
ret := buffer.recv([4096]u8, windowing_system_buffer, mem_buf) ret := buffer.recv([u8; 4096], windowing_system_buffer, mem_buf)
if ret == null { if ret == 0 {
log.info("No messages") log.info("No messages\0")
} }
if *mem_buf == 0 { if *mem_buf == 0 {
log.info("No messages") log.info("No messages\0")
} }
return @as(^render.Surface, idk) return @as(^render.Surface, idk)

View file

@ -1,44 +0,0 @@
stn := @use("../../../libraries/stn/src/lib.hb");
.{string, log} := stn;
.{Vec2} := stn.math
render := @use("../../../libraries/render/src/lib.hb");
.{Surface} := render;
.{Font} := render.text
UI := struct {raw: []u8, is_dirty: bool, surface: Surface, // Each child has their WidgetType as their first byte
// children: ^^u8,
}
render_ui := fn(surface: Surface, ui: UI): void {
if ui.is_dirty {
render.clear(ui.surface, render.black)
ui.is_dirty = false
}
pos := Vec2(uint).(0, 0)
render.put_surface(surface, ui.surface, pos, false)
}
sexpr_parser := fn(sexpr: []u8): UI {
i := 0
paren_balance := 0
loop {
if i == sexpr.len {
if paren_balance != 0 {
log.error("Unbalanced Parens")
}
break
} else if sexpr[i] == '(' {
log.info("Open paren")
paren_balance += 1
} else if sexpr[i] == ')' {
log.info("Closed paren")
paren_balance -= 1
}
i += 1
}
ui_surface := render.new_surface(100, 100)
return UI.(sexpr, true, ui_surface)
}

View file

@ -0,0 +1,20 @@
// Widget types
// End types
LayoutChildHorizontalFirst := 0
LayoutChildVerticalFirst := 1
Size := struct {
min_width: int,
max_width: int,
min_height: int,
max_height: int,
}
Widget := struct {
size: Size,
clickable: bool,
layout: u8,
a: bool,
}

View file

@ -1,13 +0,0 @@
render := @use("../../../../libraries/render/src/lib.hb");
.{Surface} := render
Image := struct {
magic: uint,
is_dirty: bool,
surface: Surface,
}
image_from_surface := fn(surface: Surface): Image {
img := Image.(4, true, surface)
return img
}

View file

@ -1,41 +0,0 @@
stn := @use("../../../../libraries/stn/src/lib.hb");
.{string, log} := stn;
.{Vec2} := stn.math
render := @use("../../../../libraries/render/src/lib.hb");
.{Surface, Color} := render;
.{Font} := render.text
Label := struct {
magic: uint,
is_dirty: bool,
surface: Surface,
text: []u8,
bg: Color,
fg: Color,
new_label := fn(text: []u8, width: uint): Self {
text_surface := render.Surface.new(width, 20)
label := Self.(3, true, text_surface, text, render.BLACK, render.WHITE)
return label
}
$set_label_text := fn(self: ^Self, text: []u8): void {
self.is_dirty = true
self.text = text
}
$set_color := fn(self: ^Self, bg: Color, fg: Color): void {
self.bg = bg
self.fg = fg
self.is_dirty = true
}
}
render_label_to_surface := fn(surface: Surface, label: Label, font: Font, pos: Vec2(uint)): void {
if label.is_dirty {
label.surface.clear(label.bg)
label.surface.put_text(font, .(0, 0), label.fg, label.text)
}
surface.put_surface(label.surface, pos, false)
}

View file

@ -1,7 +0,0 @@
NoWidget := 0
VerticalWidgetType := 1
HorizontalWidgetType := 2
LabelWidgetType := 3
ImageWidgetType := 4

View file

@ -1,36 +0,0 @@
// Widget types
// End types
stn := @use("../../../../libraries/stn/src/lib.hb");
.{string, log} := stn;
.{Vec2} := stn.math
render := @use("../../../../libraries/render/src/lib.hb");
.{Surface} := render;
.{Font} := render.text
widget_types := @use("widget_types.hb")
label := @use("label.hb")
image := @use("image.hb")
Size := struct {
min_width: int,
max_width: int,
min_height: int,
max_height: int,
}
Vertical := packed struct {
magic: uint,
// array of children, idk
// use a vec or linked list or whatever
children: ^^u8,
}
Horizontal := packed struct {
magic: uint,
// array of children, idk
// use a vec or linked list or whatever
children: ^^u8,
}

View file

@ -1,18 +0,0 @@
keycodes := @use("keycodes.hb");
.{KeyCode} := keycodes
KeyEvent := packed struct {
up: bool,
just_triggered: bool,
key: KeyCode,
}
MouseEvent := packed struct {
x_change: i8,
y_change: i8,
left: bool,
middle: bool,
right: bool,
}
GamepadEvent := struct {}

View file

@ -1,121 +1,67 @@
/*
Originally I was modelling this after the following(1). I have since changed my mind.
I am now modelling it as I see fit. This is likely not the final version.
1) https://www.libsdl.org/release/SDL-1.2.15/include/SDL_keysym.h
*/
KeyCode := u32 KeyCode := u32
// Typically this is not a keycode you will ever recieve. // https://www.libsdl.org/release/SDL-1.2.15/include/SDL_keysym.h
None := KeyCode.(0) Backspace := KeyCode.(8)
Tab := KeyCode.(9)
Clear := KeyCode.(12)
Return := KeyCode.(13)
Pause := KeyCode.(19)
Escape := KeyCode.(27)
Space := KeyCode.(32)
Escape := KeyCode.(1) A := KeyCode.(97)
/* Alphabet keycodes */ /*
ETC
*/
Z := KeyCode.(122)
A := KeyCode.(2) Delete := KeyCode.(127)
B := KeyCode.(3)
C := KeyCode.(4)
D := KeyCode.(5)
E := KeyCode.(6)
F := KeyCode.(7)
G := KeyCode.(8)
H := KeyCode.(9)
I := KeyCode.(10)
J := KeyCode.(11)
K := KeyCode.(12)
L := KeyCode.(13)
M := KeyCode.(14)
N := KeyCode.(15)
O := KeyCode.(16)
P := KeyCode.(17)
Q := KeyCode.(18)
R := KeyCode.(19)
S := KeyCode.(20)
T := KeyCode.(21)
U := KeyCode.(22)
V := KeyCode.(23)
W := KeyCode.(24)
X := KeyCode.(25)
Y := KeyCode.(26)
Z := KeyCode.(27)
/* Numeric keycodes*/
Number0 := KeyCode.(28)
Number1 := KeyCode.(29)
Number2 := KeyCode.(30)
Number3 := KeyCode.(31)
Number4 := KeyCode.(32)
Number5 := KeyCode.(33)
Number6 := KeyCode.(34)
Number7 := KeyCode.(35)
Number8 := KeyCode.(36)
Number9 := KeyCode.(37)
KeypadNumber0 := KeyCode.(38)
KeypadNumber1 := KeyCode.(39)
KeypadNumber2 := KeyCode.(40)
KeypadNumber3 := KeyCode.(41)
KeypadNumber4 := KeyCode.(42)
KeypadNumber5 := KeyCode.(43)
KeypadNumber6 := KeyCode.(44)
KeypadNumber7 := KeyCode.(45)
KeypadNumber8 := KeyCode.(46)
KeypadNumber9 := KeyCode.(47)
KeypadPeriod := KeyCode.(48)
KeypadDivide := KeyCode.(49)
KeypadMultiply := KeyCode.(50)
KeypadMinus := KeyCode.(51)
KeypadPlus := KeyCode.(52)
KeypadEnter := KeyCode.(53)
KeypadEquals := KeyCode.(54)
Delete := KeyCode.(55)
/* Locking Keys */
NumLock := KeyCode.(56)
CapsLock := KeyCode.(57)
ScrollLock := KeyCode.(58)
/* "Alt Gr" key */
Mode := KeyCode.(59)
/* Multi-key compose key */
Compose := KeyCode.(60)
LeftAlt := KeyCode.(61)
LeftControl := KeyCode.(62)
LeftMeta := KeyCode.(63)
LeftShift := KeyCode.(64)
/* Left "Windows" key */
LeftSuper := KeyCode.(65)
RightAlt := KeyCode.(66)
RightControl := KeyCode.(67)
RightMeta := KeyCode.(68)
RightShift := KeyCode.(69)
/* Right "Windows" key */
RightSuper := KeyCode.(70)
/* /*
This block of any triggers on any press of any of the keys. ETC
Typically this is the event to care about.
*/ */
AnyNumber0 := KeyCode.(71)
AnyNumber1 := KeyCode.(72)
AnyNumber2 := KeyCode.(73)
AnyNumber3 := KeyCode.(74)
AnyNumber4 := KeyCode.(75)
AnyNumber5 := KeyCode.(76)
AnyNumber6 := KeyCode.(77)
AnyNumber7 := KeyCode.(78)
AnyNumber8 := KeyCode.(79)
AnyNumber9 := KeyCode.(80)
AnyAlt := KeyCode.(81) KeypadNumber0 := KeyCode.(256)
AnyControl := KeyCode.(82) KeypadNumber1 := KeyCode.(257)
AnyMeta := KeyCode.(83) KeypadNumber2 := KeyCode.(258)
AnyShift := KeyCode.(84) KeypadNumber3 := KeyCode.(259)
/* Any "Windows" key */ KeypadNumber4 := KeyCode.(260)
AnySuper := KeyCode.(85) KeypadNumber5 := KeyCode.(261)
KeypadNumber6 := KeyCode.(262)
KeypadNumber7 := KeyCode.(263)
KeypadNumber8 := KeyCode.(264)
KeypadNumber9 := KeyCode.(265)
KeypadPeriod := KeyCode.(266)
KeypadDivide := KeyCode.(267)
KeypadMultiply := KeyCode.(268)
KeypadMinus := KeyCode.(269)
KeypadPlus := KeyCode.(270)
KeypadEnter := KeyCode.(271)
KeypadEquals := KeyCode.(272)
NumLock := KeyCode.(300)
CapsLock := KeyCode.(301)
ScrollLock := KeyCode.(302)
RightShift := KeyCode.(303)
LeftShift := KeyCode.(304)
RightControl := KeyCode.(305)
LeftControl := KeyCode.(306)
RightAlt := KeyCode.(307)
LeftAlt := KeyCode.(308)
RightMeta := KeyCode.(309)
LeftMeta := KeyCode.(310)
/* Left "Windows" key */
LeftSuper := KeyCode.(311)
/* Right "Windows" key */
RightSuper := KeyCode.(312)
/* "Alt Gr" key */
Mode := KeyCode.(313)
/* Multi-key compose key */
Compose := KeyCode.(314)

View file

@ -1,36 +1,22 @@
stn := @use("stn"); keycodes := @use("keycodes.hb");
.{log, buffer, memory} := stn .{KeyCode} := keycodes
keycodes := @use("keycodes.hb")
events := @use("events.hb"); MouseEvent := struct {
.{KeyEvent, MouseEvent} := events x_change: u8,
y_change: u8,
recieve_key_event := fn(): ?KeyEvent { left: u8,
kevent := KeyEvent.(false, false, 0) middle: u8,
right: u8,
buf_id := buffer.search("PS/2 Keyboard")
// Read out of the Keyboard buffer here
buffer.recv(KeyEvent, buf_id, &kevent)
if kevent.just_triggered {
return kevent
}
return null
} }
recieve_mouse_event := fn(): ?MouseEvent { KeyEvent := struct {
mevent := MouseEvent.(0, 0, false, false, false) // 0 if down
// 1 if up
up: u8,
// 0 if not just triggered
// 1 if just triggered
just_triggered: u8,
key: KeyCode,
}
buf_id := buffer.search("PS/2 Mouse") GamepadEvent := struct {}
// Read out of the Mouse buffer here
buffer.recv(MouseEvent, buf_id, &mevent)
if mevent.x_change != 0 | mevent.y_change != 0 | mevent.left | mevent.middle | mevent.right {
return mevent
}
return null
}

View file

@ -1,4 +1,4 @@
.{string, memory, buffer, log} := @use("stn") .{string, memory, buffer, log} := @use("../../stn/src/lib.hb")
PCIAddress := struct { PCIAddress := struct {
bus: u8, bus: u8,
@ -51,9 +51,9 @@ check_device := fn(bus: u8, device: u8): PciDeviceInfo {
pci_id := get_ids(bus, device, 0) pci_id := get_ids(bus, device, 0)
if pci_id.vendor == 0xFFFF { if pci_id.vendor == 0xFFFF {
log.warn(":|") log.warn(":|\0")
} else { } else {
log.info(":)") log.info(":)\0")
} }
address := calculate_address(bus, device, 0, 0x8) address := calculate_address(bus, device, 0, 0x8)
reg2 := config_read32(bus, device, 0, 0x8) reg2 := config_read32(bus, device, 0, 0x8)

View file

@ -3,4 +3,7 @@ Rendering interface for SVGA and Software renderers
# TODO: # TODO:
- SVGA Driver - SVGA Driver
- needs pci driver - needs pci driver
- needs init (requiring program)
- Double Buffer mode for Software renderer
- needs init (requiring program)

View file

@ -1,4 +1,7 @@
# Images # Images
- General over image format
- Support formats:
- PNG
- Animation - Animation
# API # API

View file

@ -0,0 +1,102 @@
.{Color, Surface, new_surface} := @use("./lib.hb");
.{log, memory} := @use("../../stn/src/lib.hb")
BitmapFileHeader := packed struct {
img_type: u16,
size: u32,
reserved_1: u16,
reserved_2: u16,
offset: u32,
}
BitmapInfoHeader := packed struct {
size: u32,
width: i32,
height: i32,
planes: u16,
bits: u16,
compression: u32,
image_size: u32,
x_resolution: i32,
y_resolution: i32,
n_colours: u32,
important_colours: u32,
}
BitmapColorHeader := packed struct {
red_mask: u32,
green_mask: u32,
blue_mask: u32,
alpha_mask: u32,
color_space_type: u32,
unused: u32,
}
surface_from_bmp := fn(bmp: ^u8): Surface {
file_header := @as(^BitmapFileHeader, @bitcast(bmp))
if file_header.img_type != 0x4D42 {
log.error("failed to load bmp image: not a bmp image, idiot\0")
return idk
}
info_header := @as(^BitmapInfoHeader, @bitcast(bmp + @sizeof(BitmapFileHeader)))
bmp += file_header.offset
px := info_header.width * info_header.height
ptr := @as(^Color, @bitcast(bmp))
tmp := @as(Color, idk)
row := @as(i32, 0)
loop if row == info_header.height / 2 break else {
col := @as(i32, 0)
loop if col == info_header.width break else {
top_index := row * info_header.width + col
bottom_index := (info_header.height - 1 - row) * info_header.width + col
tmp = *(ptr + top_index);
*(ptr + top_index) = *(ptr + bottom_index);
*(ptr + bottom_index) = tmp
col += 1
}
row += 1
}
return .(@bitcast(bmp), info_header.width, info_header.height)
}
new_surface_from_bmp := fn(bmp: ^u8): Surface {
file_header := @as(^BitmapFileHeader, @bitcast(bmp))
if file_header.img_type != 0x4D42 {
log.error("failed to load bmp image: not a bmp image, idiot\0")
return idk
}
info_header := @as(^BitmapInfoHeader, @bitcast(bmp + @sizeof(BitmapFileHeader)))
bmp += file_header.offset
width := @as(uint, @intcast(info_header.width))
height := @as(uint, @intcast(info_header.height))
surface := new_surface(width, height)
top_start_idx := surface.buf
bottom_start_idx := surface.buf + width * (height - 1)
rows_to_copy := height
top_cursor := @as(^Color, @bitcast(bmp))
bottom_cursor := top_cursor + width * (height - 1)
loop if rows_to_copy <= 1 break else {
@inline(memory.copy, Color, top_cursor, bottom_start_idx, @bitcast(width))
@inline(memory.copy, Color, bottom_cursor, top_start_idx, @bitcast(width))
top_start_idx += surface.width
bottom_start_idx -= surface.width
top_cursor += width
bottom_cursor -= width
rows_to_copy -= 2
}
if rows_to_copy == 1 {
@inline(memory.copy, Color, top_cursor, top_start_idx, @bitcast(width))
}
return surface
}

View file

@ -1,49 +0,0 @@
.{Color, Surface, new_surface, put_surface} := @use("lib:render");
.{log} := @use("stn")
BitmapFileHeader := packed struct {
magic: u16,
size: u32,
reserved_1: u16,
reserved_2: u16,
offset: u32,
}
BitmapInfoHeader := packed struct {
size: u32,
width: i32,
height: i32,
planes: u16,
bits: u16,
compression: u32,
image_size: u32,
x_resolution: i32,
y_resolution: i32,
n_colours: u32,
important_colours: u32,
}
BitmapColorHeader := packed struct {
red_mask: u32,
green_mask: u32,
blue_mask: u32,
alpha_mask: u32,
color_space_type: u32,
unused: u32,
}
from := fn(bmp: ^u8): ?Surface {
file_header := @as(^BitmapFileHeader, @bitcast(bmp))
info_header := @as(^BitmapInfoHeader, @bitcast(bmp + @sizeof(BitmapFileHeader)))
if file_header.magic != 0x4D42 | info_header.width == 0 | info_header.height == 0 {
log.error("Invalid BMP image.")
return null
}
lhs := Surface.(@bitcast(bmp + file_header.offset), info_header.width, info_header.height, info_header.width * info_header.height)
rhs := Surface.new(info_header.width, info_header.height)
rhs.put_surface(lhs, .(0, 0), true)
return rhs
}

View file

@ -1,31 +0,0 @@
.{log} := @use("stn");
.{Surface} := @use("lib:render")
bmp := @use("bmp.hb")
qoi := @use("qoi.hb")
$BMP := 0x4D42
$QOI := 0x66696F71
get_format := fn(file: ^u8): ?uint {
if *@as(^u16, @bitcast(file)) == BMP {
return BMP
} else if *@as(^u32, @bitcast(file)) == QOI {
return QOI
} else {
return null
}
}
from := fn(file: ^u8): ?Surface {
format := get_format(file)
if format == null {
log.error("Could not detect image format.")
return null
} else if format == BMP {
return bmp.from(file)
} else if format == QOI {
return qoi.from(file)
}
return null
}

View file

@ -1,101 +0,0 @@
.{Color, Surface, new_surface} := @use("lib:render");
.{log} := @use("stn")
/* source:
https://github.com/phoboslab/qoi/blob/master/qoi.h */
$QOI_SRGB := 0
$QOI_LINEAR := 1
$QOI_OP_INDEX := 0x0
$QOI_OP_DIFF := 0x40
$QOI_OP_LUMA := 0x80
$QOI_OP_RUN := 0xC0
$QOI_OP_RGB := 0xFE
$QOI_OP_RGBA := 0xFF
$QOI_MASK_2 := 0xC0
$QOI_COLOR_HASH := fn(c: Color): u8 {
return (c.r * 3 + c.g * 5 + c.b * 7 + c.a * 11) % 64
}
$QOI_MAGIC := 0x716F6966
$QOI_PIXELS_MAX := 400000000
QuiteOkayHeader := packed struct {
magic: u32,
width: u32,
height: u32,
channels: u8,
colorspace: u8,
}
be_to_le := fn(big: u32): u32 {
return big >> 24 | big >> 8 & 0xFF00 | big << 8 & 0xFF0000 | big << 24
}
from := fn(qoi: ^u8): ?Surface {
header := @as(^QuiteOkayHeader, @bitcast(qoi))
qoi += @sizeof(QuiteOkayHeader)
width := be_to_le(header.width)
height := be_to_le(header.height)
if be_to_le(header.magic) != QOI_MAGIC | width == 0 | height == 0 | header.channels < 3 | header.channels > 4 {
log.error("Invalid QOI image.")
return null
}
surface := Surface.new(width, height)
index := @as([64]Color, idk)
run := 0
px := Color.(0, 0, 0, 255)
px_pos := 0
total_pixels := width * height
loop if px_pos >= total_pixels break else {
if run > 0 {
run -= 1
} else {
b1 := *qoi
qoi += 1
if b1 == QOI_OP_RGB {
px.r = *qoi
px.g = *(qoi + 1)
px.b = *(qoi + 2)
qoi += 3
} else if b1 == QOI_OP_RGBA {
px.r = *qoi
px.g = *(qoi + 1)
px.b = *(qoi + 2)
px.a = *(qoi + 3)
qoi += 4
} else if (b1 & QOI_MASK_2) == QOI_OP_INDEX {
px = index[b1 & 0x3F]
} else if (b1 & QOI_MASK_2) == QOI_OP_DIFF {
px.r = px.r + (b1 >> 4 & 0x3) - 2 & 0xFF
px.g = px.g + (b1 >> 2 & 0x3) - 2 & 0xFF
px.b = px.b + (b1 & 0x3) - 2 & 0xFF
} else if (b1 & QOI_MASK_2) == QOI_OP_LUMA {
b2 := *qoi
vg := (b1 & 0x3F) - 32
px.r = px.r + vg - 8 + (b2 >> 4 & 0xF) & 0xFF
px.g = px.g + vg & 0xFF
px.b = px.b + vg - 8 + (b2 & 0xF) & 0xFF
qoi += 1
} else if (b1 & QOI_MASK_2) == QOI_OP_RUN {
run = b1 & 0x3F
}
index[QOI_COLOR_HASH(px)] = px
};
*(surface.buf + px_pos) = px
px_pos += 1
}
return surface
}

View file

@ -1,28 +1,51 @@
software := @use("software.hb") software := @use("software.hb")
image := @use("image/lib.hb") image := @use("image.hb")
text := @use("text.hb") text := @use("text.hb")
// default mode // default mode
mode := software mode := software
init := mode.init init := mode.init
doublebuffer := mode.doublebuffer
Surface := mode.Surface Surface := mode.Surface
new_surface := mode.new_surface
surface_from_ptr := mode.surface_from_ptr
clone_surface := mode.clone_surface
free_surface := mode.free_surface
index := mode.index
indexptr := mode.indexptr
// Colours // Colours
Color := packed struct {b: u8, g: u8, r: u8, a: u8} Color := packed struct {b: u8, g: u8, r: u8, a: u8}
$WHITE := Color.(255, 255, 255, 255) white := Color.(255, 255, 255, 255)
$BLACK := Color.(0, 0, 0, 255) black := Color.(0, 0, 0, 255)
$GRAY := Color.(127, 127, 127, 255) gray := Color.(127, 127, 127, 255)
$RED := Color.(0, 0, 205, 255) red := Color.(0, 0, 205, 255)
$GREEN := Color.(0, 205, 0, 255) green := Color.(0, 205, 0, 255)
$YELLOW := Color.(0, 205, 205, 255) yellow := Color.(0, 205, 205, 255)
$BLUE := Color.(205, 0, 0, 255) blue := Color.(205, 0, 0, 255)
$MAGENTA := Color.(205, 0, 205, 255) magenta := Color.(205, 0, 205, 255)
$CYAN := Color.(205, 205, 0, 255) cyan := Color.(205, 205, 0, 255)
$LIGHT_GRAY := Color.(229, 229, 229, 255) light_gray := Color.(229, 229, 229, 255)
$LIGHT_RED := Color.(0, 0, 255, 255) light_red := Color.(0, 0, 255, 255)
$LIGHT_GREEN := Color.(0, 255, 0, 255) light_green := Color.(0, 255, 0, 255)
$LIGHT_YELLOW := Color.(0, 255, 255, 255) light_yellow := Color.(0, 255, 255, 255)
$LIGHT_BLUE := Color.(255, 0, 0, 255) light_blue := Color.(255, 0, 0, 255)
$LIGHT_MAGENTA := Color.(255, 0, 255, 255) light_magenta := Color.(255, 0, 255, 255)
$LIGHT_CYAN := Color.(255, 255, 0, 255) light_cyan := Color.(255, 255, 0, 255)
// Drawing
put_pixel := mode.put_pixel
put_rect := mode.put_rect
put_filled_rect := mode.put_filled_rect
put_line := mode.put_line
clear := mode.clear
put_surface := mode.put_surface
put_text := mode.put_text
// thanks peony for these three!
put_trirect := mode.put_trirect
put_vline := mode.put_vline
put_hline := mode.put_hline
// Display
sync := mode.sync

View file

@ -1,443 +1,320 @@
.{math, memory, dt} := @use("stn"); .{math, memory, dt} := @use("../../stn/src/lib.hb");
.{Color, text} := @use("lib:render"); .{Color, text} := @use("lib.hb");
.{get_glyph, get_glyph_unicode, Font, UNC_TABLE_SIZE} := text; .{get_glyph, Font} := text;
.{Vec2} := math .{Vec2} := math
// safety: don't use before init() or you will get a memory access violation
framebuffer := memory.dangling(Color)
utf8_len_table := u8.[0, 0, 2, 3]
init := fn(doublebuffer: bool): Surface {
framebuffer = dt.get(^Color, "framebuffer/fb0/ptr")
width := dt.get(uint, "framebuffer/fb0/width")
height := dt.get(uint, "framebuffer/fb0/height")
if doublebuffer {
return Surface.new(width, height)
} else {
return .(framebuffer, width, height, width * height)
}
}
Surface := struct { Surface := struct {
buf: ^Color, buf: ^Color,
width: uint, width: uint,
height: uint, height: uint,
size: uint, }
new := fn(width: uint, height: uint): Self { new_surface := fn(width: uint, height: uint): Surface {
size := width * height return .(
return .( @inline(memory.alloc, Color, width * height),
memory.alloc(Color, size), width,
width, height,
height, )
size, }
)
surface_from_ptr := fn(ptr: ^Color, width: uint, height: uint): Surface {
return .(
ptr,
width,
height,
)
}
clone_surface := fn(surface: ^Surface): Surface {
new := new_surface(surface.width, surface.height)
@inline(memory.copy, Color, surface.buf, new.buf, @intcast(surface.width * surface.height))
return new
}
// ! is broken, check memory.free function
free_surface := fn(surface: Surface): void {
return @inline(memory.free, Color, surface.buf, @intcast(surface.width * surface.height), false)
}
framebuffer := @as(^Color, idk)
init := fn(doublebuffer: bool): Surface {
framebuffer = dt.get(^Color, "framebuffer/fb0/ptr\0")
width := dt.get(uint, "framebuffer/fb0/width\0")
height := dt.get(uint, "framebuffer/fb0/height\0")
if doublebuffer {
return new_surface(width, height)
} else {
return .(framebuffer, width, height)
}
}
clear := fn(surface: Surface, color: Color): void {
return @inline(memory.set, Color, &color, surface.buf, surface.width * surface.height)
}
sync := fn(surface: Surface): void {
// vague safety
if surface.buf == framebuffer {
return
}
return @inline(memory.copy, Color, surface.buf, framebuffer, @bitcast(surface.width * surface.height))
}
index := fn(surface: Surface, x: uint, y: uint): uint {
return x + surface.width * y
}
indexptr := fn(surface: Surface, x: uint, y: uint): ^Color {
return surface.buf + @inline(index, surface, x, y)
}
put_pixel := fn(surface: Surface, pos: Vec2(uint), color: Color): void {
*@inline(indexptr, surface, pos.x, pos.y) = color
return
}
put_filled_rect := fn(surface: Surface, pos: Vec2(uint), tr: Vec2(uint), color: Color): void {
top_start_idx := @inline(indexptr, surface, pos.x, pos.y)
bottom_start_idx := @inline(indexptr, surface, pos.x, pos.y + tr.y - 1)
rows_to_fill := tr.y
loop if rows_to_fill <= 1 break else {
@inline(memory.set, Color, &color, top_start_idx, @bitcast(tr.x))
@inline(memory.set, Color, &color, bottom_start_idx, @bitcast(tr.x))
top_start_idx += surface.width
bottom_start_idx -= surface.width
rows_to_fill -= 2
} }
clone := fn(self: ^Self): Self { if rows_to_fill == 1 {
new_self := Self.new(self.width, self.height) @inline(memory.set, Color, &color, top_start_idx, @bitcast(tr.x))
memory.copy(Color, self.buf, new_self.buf, self.size)
return new_self
}
$clear := fn(self: Self, color: Color): void {
memory.set(Color, &color, self.buf, self.size)
} }
$sync := fn(self: Self): void { return
memory.copy(Color, self.buf, framebuffer, self.size) }
put_rect := fn(surface: Surface, pos: Vec2(uint), tr: Vec2(uint), color: Color): void {
start_idx := @inline(indexptr, surface, pos.x, pos.y)
end_idx := @inline(indexptr, surface, pos.x, pos.y + tr.y)
right_start_idx := @inline(indexptr, surface, pos.x + tr.x, pos.y)
loop if start_idx > end_idx break else {
*start_idx = color;
*right_start_idx = color
start_idx += surface.width
right_start_idx += surface.width
} }
$index := fn(self: Self, x: uint, y: uint): uint { @inline(memory.set, Color, &color, @inline(indexptr, surface, pos.x, pos.y), @bitcast(tr.x + 1))
return x + self.width * y @inline(memory.set, Color, &color, @inline(indexptr, surface, pos.x, pos.y + tr.y), @bitcast(tr.x + 1))
return
}
put_line_low := fn(surface: Surface, p0: Vec2(uint), p1: Vec2(uint), color: Color): void {
dx := @as(int, @bitcast(p1.x - p0.x))
dy := @as(int, @bitcast(p1.y - p0.y))
yi := 1
if dy < 0 {
yi = -1
dy = -dy
} }
D := @as(int, 2) * dy - dx
$indexptr := fn(self: Self, x: uint, y: uint): ^Color { y := p0.y
return self.buf + self.index(x, y) x := p0.x
} loop if x == p1.x break else {
*@inline(indexptr, surface, x, y) = color
$put_pixel := fn(self: Self, pos: Vec2(uint), color: Color): void { if D > 0 {
*self.indexptr(pos.x, pos.y) = color y += yi
} D += 2 * (dy - dx)
put_filled_rect := fn(self: Self, pos: Vec2(uint), tr: Vec2(uint), color: Color): void {
top_start_idx := self.indexptr(pos.x, pos.y)
bottom_start_idx := self.indexptr(pos.x, pos.y + tr.y - 1)
rows_to_fill := tr.y
loop if rows_to_fill <= 1 break else {
memory.set(Color, &color, top_start_idx, tr.x)
memory.set(Color, &color, bottom_start_idx, tr.x)
top_start_idx += self.width
bottom_start_idx -= self.width
rows_to_fill -= 2
}
if rows_to_fill == 1 {
memory.set(Color, &color, top_start_idx, tr.x)
}
}
put_rect := fn(self: Self, pos: Vec2(uint), tr: Vec2(uint), color: Color): void {
start_idx := self.indexptr(pos.x, pos.y)
end_idx := self.indexptr(pos.x, pos.y + tr.y)
right_start_idx := self.indexptr(pos.x + tr.x, pos.y)
loop if start_idx > end_idx break else {
*start_idx = color;
*right_start_idx = color
start_idx += self.width
right_start_idx += self.width
}
memory.set(Color, &color, self.indexptr(pos.x, pos.y), @bitcast(tr.x + 1))
memory.set(Color, &color, self.indexptr(pos.x, pos.y + tr.y), @bitcast(tr.x + 1))
}
put_line_low := fn(self: Self, p0: Vec2(uint), p1: Vec2(uint), color: Color): void {
dx := @as(int, @bitcast(p1.x - p0.x))
dy := @as(int, @bitcast(p1.y - p0.y))
yi := 1
if dy < 0 {
yi = -1
dy = -dy
}
D := @as(int, 2) * dy - dx
y := p0.y
x := p0.x
loop if x == p1.x break else {
*self.indexptr(x, y) = color
if D > 0 {
y += yi
D += 2 * (dy - dx)
} else {
D += 2 * dy
}
x += 1
}
}
put_line_high := fn(self: Self, p0: Vec2(uint), p1: Vec2(uint), color: Color): void {
dx := @as(int, @bitcast(p1.x - p0.x))
dy := @as(int, @bitcast(p1.y - p0.y))
xi := 1
if dy < 0 {
xi = -1
dx = -dx
}
D := @as(int, 2) * dx - dy
x := p0.x
y := p0.y
loop if y == p1.y break else {
*self.indexptr(x, y) = color
if D > 0 {
x += xi
D += 2 * (dx - dy)
} else {
D += 2 * dx
}
y += 1
}
}
put_line := fn(self: Self, p0: Vec2(uint), p1: Vec2(uint), color: Color): void {
if math.abs(int, @bitcast(p1.y - p0.y)) < math.abs(int, @bitcast(p1.x - p0.x)) {
if p0.x > p1.x {
@inline(put_line_low, self, p1, p0, color)
} else {
@inline(put_line_low, self, p0, p1, color)
}
} else { } else {
if p0.y > p1.y { D += 2 * dy
@inline(put_line_high, self, p1, p0, color) }
} else { x += 1
@inline(put_line_high, self, p0, p1, color) }
} return
}
put_line_high := fn(surface: Surface, p0: Vec2(uint), p1: Vec2(uint), color: Color): void {
dx := @as(int, @bitcast(p1.x - p0.x))
dy := @as(int, @bitcast(p1.y - p0.y))
xi := 1
if dy < 0 {
xi = -1
dx = -dx
}
D := @as(int, 2) * dx - dy
x := p0.x
y := p0.y
loop if y == p1.y break else {
*@inline(indexptr, surface, x, y) = color
if D > 0 {
x += xi
D += 2 * (dx - dy)
} else {
D += 2 * dx
}
y += 1
}
return
}
put_line := fn(surface: Surface, p0: Vec2(uint), p1: Vec2(uint), color: Color): void {
if math.abs(uint, p1.y - p0.y) < math.abs(uint, p1.x - p0.x) {
if p0.x > p1.x {
@inline(put_line_low, surface, p1, p0, color)
} else {
@inline(put_line_low, surface, p0, p1, color)
}
} else {
if p0.y > p1.y {
@inline(put_line_high, surface, p1, p0, color)
} else {
@inline(put_line_high, surface, p0, p1, color)
} }
} }
return
}
put_surface := fn(self: Self, top: Self, pos: Vec2(uint), flip_v: bool): void { put_surface := fn(surface: Surface, top: Surface, pos: Vec2(uint), flip_v: bool): void {
src_top_cursor := top.buf top_start_idx := @inline(indexptr, surface, pos.x, pos.y)
src_bottom_cursor := top.buf + top.width * (top.height - 1) bottom_start_idx := @inline(indexptr, surface, pos.x, pos.y + top.height - 1)
rows_to_copy := top.height
dst_top_idx := self.indexptr(pos.x, pos.y) top_cursor := top.buf
dst_bottom_idx := self.indexptr(pos.x, pos.y + top.height - 1) bottom_cursor := top.buf + top.width * (top.height - 1)
dst_increment := self.width
loop if rows_to_copy <= 1 break else {
if flip_v { if flip_v {
dst_increment = -dst_increment @inline(memory.copy, Color, top_cursor, bottom_start_idx, @bitcast(top.width))
tmp := dst_top_idx @inline(memory.copy, Color, bottom_cursor, top_start_idx, @bitcast(top.width))
dst_top_idx = dst_bottom_idx } else {
dst_bottom_idx = tmp @inline(memory.copy, Color, top_cursor, top_start_idx, @bitcast(top.width))
@inline(memory.copy, Color, bottom_cursor, bottom_start_idx, @bitcast(top.width))
} }
rows_to_copy := top.height top_start_idx += surface.width
bottom_start_idx -= surface.width
loop if rows_to_copy <= 1 break else { top_cursor += top.width
memory.copy(Color, src_top_cursor, dst_top_idx, top.width) bottom_cursor -= top.width
memory.copy(Color, src_bottom_cursor, dst_bottom_idx, top.width) rows_to_copy -= 2
dst_top_idx += dst_increment
dst_bottom_idx -= dst_increment
src_top_cursor += top.width
src_bottom_cursor -= top.width
rows_to_copy -= 2
}
if rows_to_copy == 1 {
memory.copy(Color, src_top_cursor, dst_top_idx, top.width)
}
} }
// peony-made if rows_to_copy == 1 {
put_trirect := fn(self: Self, pos: Vec2(uint), size: Vec2(int), color0: Color, color1: Color): void { @inline(memory.copy, Color, top_cursor, top_start_idx, @bitcast(top.width))
step := Vec2(int).(1, 1)
if size.x < 0 {
step.x = -1
}
if size.y < 0 {
step.y /= @bitcast(size.x)
}
start_y := pos.y
target := pos + @bitcast(size)
loop if pos.x == target.x break else {
@inline(put_vline, self, pos.x, pos.y, target.y, color0)
@inline(put_vline, self, pos.x, pos.y, start_y, color1)
pos += @bitcast(step)
}
} }
// peony-made return
put_vline := fn(self: Self, x: uint, y0: uint, y1: uint, color: Color): void { }
if y1 < y0 {
tmp := y0
y0 = y1
y1 = tmp
}
y := y0
loop if y == y1 break else { // peony-made
*self.indexptr(x, y) = color put_trirect := fn(surface: Surface, pos: Vec2(uint), size: Vec2(int), color0: Color, color1: Color): void {
y += 1 step := Vec2(int).(1, 1)
} if size.x < 0 {
step.x = -1
}
if size.y < 0 {
step.y /= @bitcast(size.x)
} }
// peony-made start_y := pos.y
put_hline := fn(self: Self, y: uint, x0: uint, x1: uint, color: Color): void { target := pos + @bitcast(size)
if x1 < x0 {
tmp := x0 loop if pos.x == target.x break else {
x0 = x1 @inline(put_vline, surface, pos.x, pos.y, target.y, color0)
x1 = tmp @inline(put_vline, surface, pos.x, pos.y, start_y, color1)
} pos += @bitcast(step)
memory.set(Color, &color, self.indexptr(x0, y), @bitcast(x1 - x0))
} }
put_circle := fn(self: Self, pos: Vec2(uint), radius: uint, color: Color): void { return
x := 0 }
y := radius
error := @as(int, 3) - 2 * @intcast(radius) // peony-made
loop if x > y break else { put_vline := fn(surface: Surface, x: uint, y0: uint, y1: uint, color: Color): void {
self.put_pixel(pos + .(x, y), color) if y1 < y0 {
self.put_pixel(pos + .(-x, y), color) tmp := y0
self.put_pixel(pos + .(x, -y), color) y0 = y1
self.put_pixel(pos + .(-x, -y), color) y1 = tmp
self.put_pixel(pos + .(y, x), color) }
self.put_pixel(pos + .(-y, x), color) y := y0
self.put_pixel(pos + .(y, -x), color)
self.put_pixel(pos + .(-y, -x), color) loop if y == y1 break else {
if error < 0 { *@inline(indexptr, surface, x, y) = color
error += 4 * @intcast(x) + 6 y += 1
} else {
error += 4 * (@intcast(x) - @intcast(y)) + 10
y -= 1
}
x += 1
}
} }
put_filled_circle := fn(self: Self, pos: Vec2(uint), radius: uint, color: Color): void { return
x := 0 }
y := radius
error := @as(int, 3) - 2 * @intcast(radius)
loop if x > y break else { // peony-made
self.put_hline(pos.y + y, pos.x - x, pos.x + x, color) put_hline := fn(surface: Surface, y: uint, x0: uint, x1: uint, color: Color): void {
self.put_hline(pos.y - y, pos.x - x, pos.x + x, color) if x1 < x0 {
tmp := x0
if x != y { x0 = x1
self.put_hline(pos.y + x, pos.x - y, pos.x + y, color) x1 = tmp
self.put_hline(pos.y - x, pos.x - y, pos.x + y, color)
}
if error < 0 {
error += 4 * @intcast(x) + 6
} else {
error += 4 * (@intcast(x) - @intcast(y)) + 10
y -= 1
}
x += 1
}
} }
@inline(memory.set, Color, &color, @inline(indexptr, surface, x0, y), @bitcast(x1 - x0 - 1))
put_textured_circle := fn(self: Self, source: Self, source_pos: Vec2(uint), pos: Vec2(uint), radius: uint): void { return
x := 0 }
y := radius
error := @as(int, 3) - 2 * @intcast(radius)
loop if x > y break else { put_text := fn(surface: Surface, font: Font, pos: Vec2(uint), color: Color, str: ^u8): void {
memory.copy(Color, source.indexptr(source_pos.x - x, source_pos.y + y), self.indexptr(pos.x - x, pos.y + y), 2 * x) cursor := Vec2(uint).(pos.x, pos.y)
memory.copy(Color, source.indexptr(source_pos.x - x, source_pos.y - y), self.indexptr(pos.x - x, pos.y - y), 2 * x) current_char := str
if x != y { loop if *current_char == 0 break else {
memory.copy(Color, source.indexptr(source_pos.x - y, source_pos.y + x), self.indexptr(pos.x - y, pos.y + x), 2 * y) if *current_char == 10 {
memory.copy(Color, source.indexptr(source_pos.x - y, source_pos.y - x), self.indexptr(pos.x - y, pos.y - x), 2 * y) cursor.x = pos.x
} cursor.y += font.height + font.line_gap
current_char += 1
if error < 0 { continue
error += 4 * @intcast(x) + 6
} else {
error += 4 * (@intcast(x) - @intcast(y)) + 10
y -= 1
}
x += 1
} }
}
put_text := fn(self: Self, font: Font, pos: Vec2(uint), color: Color, str: []u8): void { glyph_data := @inline(get_glyph, font, @intcast(*current_char))
cursor := Vec2(uint).(pos.x, pos.y) if glyph_data == idk {
current_char += 1
continue
}
max_y := self.height - font.height if cursor.x % surface.width + font.width >= surface.width {
next_line_y := font.height + font.line_gap cursor.x = pos.x
char_advance := font.width + font.char_gap cursor.y += font.height + font.line_gap
self_width := self.width }
if cursor.y + font.height > surface.height break
i := 0 dest := @inline(indexptr, surface, cursor.x, cursor.y)
src := glyph_data
rows_remaining := font.height
loop if i >= str.len break else { loop if rows_remaining == 0 break else {
if cursor.y > max_y break byte := *glyph_data
pixel_dest := dest
mask := @as(u8, 0x80)
bits_remaining := font.width
glyph_data := @as(^u8, idk) loop if bits_remaining == 0 break else {
code_point := @as(uint, 0) if (byte & mask) != 0 {
*pixel_dest = color
if (str[i] & 0x80) == 0 {
if str[i] == '\n' {
cursor.x = pos.x
cursor.y += next_line_y
i += 1
continue
} }
pixel_dest += 1
if font.unicode == null { mask >>= 1
if str[i] > font.num_glyphs { if mask == 0 {
i += 1
continue
}
glyph_data = get_glyph(font, str[i])
} else {
if str[i] < UNC_TABLE_SIZE {
glyph_index := *(font.unicode + str[i])
if glyph_index == 0xFFFF {
i += 1
continue
}
glyph_data = font.data + glyph_index * font.bytes_per_glyph
} else {
i += 1
continue
}
}
i += 1
} else if font.unicode != null {
first_byte := str[i]
num_bytes := @as(uint, 0)
num_bytes = utf8_len_table[first_byte >> 5 & 0x3]
if num_bytes == 0 {
i += 1
continue
}
code_point = first_byte & (0x7F >> num_bytes | 0x1F)
valid_sequence := true
bytes_processed := 1
loop if bytes_processed >= num_bytes break else {
i += 1
if i == str.len | (str[i] & 0xC0) != 0x80 {
valid_sequence = false
}
if valid_sequence == false {
break
}
code_point = code_point << 6 | str[i] & 0x3F
bytes_processed += 1
}
if valid_sequence == false {
i += 1
continue
}
i += 1
if code_point == '\n' {
cursor.x = pos.x
cursor.y += next_line_y
continue
}
if code_point >= UNC_TABLE_SIZE {
continue
}
glyph_index := *(font.unicode + code_point)
if glyph_index == 0xFFFF {
continue
}
glyph_data = font.data + glyph_index * font.bytes_per_glyph
}
if cursor.x + font.width >= self_width {
cursor.x = pos.x
cursor.y += next_line_y
}
dest := self.indexptr(cursor.x, cursor.y)
rows := font.height
loop if rows == 0 break else {
byte := *glyph_data
pixel_dest := dest
mask := @as(u8, 0x80)
bits := font.width
loop if bits == 0 break else {
if (byte & mask) != 0 {
*pixel_dest = color
}
pixel_dest += 1
mask >>= 1
if mask == 0 & bits > 0 {
glyph_data += 1
byte = *glyph_data
mask = 0x80
}
bits -= 1
}
if mask != 0x80 {
glyph_data += 1 glyph_data += 1
byte = *glyph_data
mask = 0x80
} }
dest += self_width bits_remaining -= 1
rows -= 1
} }
cursor.x += char_advance glyph_data += 1
dest += surface.width
rows_remaining -= 1
} }
cursor.x += font.width + font.char_gap
current_char += 1
} }
return
} }

View file

@ -1,4 +1,4 @@
.{log, memory} := @use("stn") .{log} := @use("../../stn/src/lib.hb")
PSF1Header := packed struct { PSF1Header := packed struct {
magic: u16, magic: u16,
@ -23,16 +23,16 @@ Font := struct {
height: uint, height: uint,
num_glyphs: uint, num_glyphs: uint,
bytes_per_glyph: uint, bytes_per_glyph: uint,
has_unicode_table: bool,
line_gap: uint, line_gap: uint,
char_gap: uint, char_gap: uint,
unicode: ?^u16,
} }
font_from_psf1 := fn(psf: ^u8): ?Font { font_from_psf1 := fn(psf: ^u8): Font {
header := @as(^PSF1Header, @bitcast(psf)) header := @as(^PSF1Header, @bitcast(psf))
if header.magic != 0x436 { if header.magic != 0x436 {
log.error("failed to load psf font: not a psf1 font, idiot") log.error("failed to load psf font: not a psf1 font, idiot\0")
return null return idk
} }
psf += @sizeof(PSF1Header) psf += @sizeof(PSF1Header)
@ -40,121 +40,36 @@ font_from_psf1 := fn(psf: ^u8): ?Font {
return .( return .(
psf, psf,
8, 8,
header.character_size, @intcast(header.character_size),
256, 256,
header.character_size, @intcast(header.character_size),
false,
0, 0,
0, 0,
null,
) )
} }
font_from_psf2 := fn(psf: ^u8, unicode: bool): ?Font { font_from_psf2 := fn(psf: ^u8): Font {
header := @as(^PSF2Header, @bitcast(psf)) header := @as(^PSF2Header, @bitcast(psf))
if header.magic != 0x864AB572 { if header.magic != 0x864AB572 {
log.error("failed to load psf font: not a psf2 font, idiot") log.error("failed to load psf font: not a psf2 font, idiot\0")
return null return idk
} }
psf += header.header_size psf += header.header_size
font := Font.( return .(
psf, psf,
header.width, @intcast(header.width),
header.height, @intcast(header.height),
header.num_glyph, @intcast(header.num_glyph),
header.bytes_per_glyph, @intcast(header.bytes_per_glyph),
(header.flags & 1) != 0,
0, 0,
0, 0,
null,
) )
if (header.flags & 1) != 0 & unicode {
init_unicode(&font)
}
return font
} }
$get_glyph := fn(font: Font, index: u8): ^u8 { get_glyph := fn(font: Font, index: uint): ^u8 {
return font.data + @as(uint, index) * font.bytes_per_glyph return font.data + index * font.bytes_per_glyph
}
$UNC_TABLE_SIZE := 1 << 16
init_unicode := fn(font: ^Font): void {
font.unicode = memory.alloc(u16, UNC_TABLE_SIZE)
memory.set(u16, &0xFFFF, font.unicode, UNC_TABLE_SIZE)
table := font.data + font.num_glyphs * font.bytes_per_glyph
curr_glyph := @as(u16, 0)
loop if curr_glyph >= font.num_glyphs break else {
loop {
byte := *table
table += 1
if byte == 0xFF break
if byte == 0xFE {
continue
}
unicode := @as(uint, 0)
bytes_to_read := @as(uint, 1)
if (byte & 0x80) == 0 {
unicode = byte
} else if (byte & 0xE0) == 0xC0 {
unicode = byte & 0x1F
bytes_to_read = 2
} else if (byte & 0xF0) == 0xE0 {
unicode = byte & 0xF
bytes_to_read = 3
} else if (byte & 0xF8) == 0xF0 {
unicode = byte & 0x7
bytes_to_read = 4
} else {
continue
}
valid := true
loop if bytes_to_read <= 1 break else {
next_byte := *table
if (next_byte & 0xC0) != 0x80 {
valid = false
break
}
unicode = unicode << 6 | next_byte & 0x3F
table += 1
bytes_to_read -= 1
}
if valid == false continue
if bytes_to_read == 4 {
if unicode < 0x10000 | unicode > 0x10FFFF continue
if unicode <= 0xFFFF {
if unicode < UNC_TABLE_SIZE {
*(@unwrap(font.unicode) + unicode) = curr_glyph
}
} else {
unicode -= 0x10000
high_surrogate := 0xD800 | unicode >> 10 & 0x3FF
low_surrogate := 0xDC00 | unicode & 0x3FF
if high_surrogate < UNC_TABLE_SIZE {
*(@unwrap(font.unicode) + high_surrogate) = curr_glyph
}
if low_surrogate < UNC_TABLE_SIZE {
*(@unwrap(font.unicode) + low_surrogate) = curr_glyph
}
}
} else {
if unicode < UNC_TABLE_SIZE {
*(@unwrap(font.unicode) + unicode) = curr_glyph
}
}
}
curr_glyph += 1
}
} }

View file

@ -1,4 +0,0 @@
AllocReturn := struct {
byte_count: uint,
ptr: ?^u8,
}

View file

@ -1,90 +0,0 @@
.{log, panic, memory} := @use("stn")
alloc_return := @use("alloc_return.hb")
/* the block size is 64 bytes, 64 blocks of 64 bytes.
this will very quickly lead to exhaustion of free blocks.
*/
BlockAlloc := struct {
// hi
state: uint,
ptr: ?^u8,
$init := fn(): Self {
alloc_page_ptr := memory.request_page(1)
state := 0xFFFFFFFFFFFFFFFF
return .(state, alloc_page_ptr)
}
alloc := fn(self: Self, alloc_type: type, count: uint): alloc_return.AllocReturn {
offset := 0
state_2 := 0
loop {
xyz := self.state & 1
abc := if xyz == 1 {
true
} else {
false
}
// check if the `offset` bit is 1, if it is move to the next offset
if abc {
offset += 1
return .(0, null)
} else {
log.info("Already Allocated")
}
// else {
// // self it to 1 and return the ptr to the allocation
// self.state |= a
// // return ptr + offset * 64
// if self.ptr != null {
// return .(64, self.ptr + offset * 64)
// } else {
// // panic.panic("Allocator is not inited.")
// // return .(0, null)
// }
// }
// there are only 64 blocks
if offset >= 64 {
return .(0, null)
}
}
}
dealloc := fn(self: Self, ptr: ^u8, alloc_type: type, count: uint): void {
// size := size_of(alloc_type)*count
size := 64
// get the size alligned to the nearest block
// rounded_size := nearest_block_size_rounded_up(size)
rounded_size := 64
state_bit_start := {
// Do math here to figure out what starting ptr corresponds to what bit
3
}
offset := 0
loop {
if rounded_size > 0 {
// set state_bit_start+offset to 0
// at the end move to the next one
offset += 1
} else {
break
}
rounded_size -= 64
}
return void
}
$deinit := fn(self: Self): void {
self.state = 0
self.ptr = null
}
}
// request a kernel page
// ptr := memory.alloc(1)

View file

@ -1,19 +0,0 @@
alloc_return := @use("alloc_return.hb")
FakeAlloc := struct {
$init := fn(): Self {
return .()
}
$alloc := fn(self: Self, alloc_type: type, count: uint): alloc_return.AllocReturn {
return .(0, null)
}
$dealloc := fn(self: Self, ptr: ^u8, alloc_type: type, count: uint): void {
return void
}
// Nothing to clean up here
$deinit := fn(self: Self): void {
return void
}
}

View file

@ -1,2 +0,0 @@
.{BlockAlloc} := @use("block_alloc.hb");
.{FakeAlloc} := @use("fake_alloc.hb")

View file

@ -1,25 +0,0 @@
allocators := @use("alloc/alloc.hb")
AStruct := struct {
a_field: u8,
}
main := fn():void{
alloc := allocators.FakeAlloc.init()
astruct := alloc.alloc(AStruct, 2)
if astruct.ptr != null{
panic("FakeAlloc actually allocated.")
}
alloc.dealloc(astruct_ptr, AStruct, 2)
alloc.deinit()
balloc := allocators.BlockAlloc.init()
bstruct_ptr := balloc.alloc(AStruct, 2)
if bstruct_ptr == null {
panic("BlockAlloc actually didn't allocate.")
}
balloc.dealloc(bstruct_ptr, AStruct, 2)
balloc.deinit()
}

Binary file not shown.

View file

@ -1,37 +1,27 @@
$await := fn(buffer_id: uint): void { string := @use("string.hb")
return @eca(7, buffer_id)
}
$recv := fn($Expr: type, buffer_id: uint, memory_map_location: ^Expr): void { recv := fn($Expr: type, buffer_id: int, memory_map_location: ^u8): ^Expr {
return @eca(4, buffer_id, memory_map_location, @sizeof(Expr)) return @eca(4, buffer_id, memory_map_location, @sizeof(Expr))
} }
$write := fn($Expr: type, buffer_id: uint, msg: ^Expr): void { write := fn($Expr: type, msg: ^Expr, buffer_id: int): void {
return @eca(3, buffer_id, msg, @sizeof(Expr)) return @eca(3, buffer_id, msg, @sizeof(Expr))
} }
$recv_length := fn(length: uint, memory_map_location: ^u8, buffer_id: uint): void { recv_length := fn(buffer_id: int, memory_map_location: ^u8, length: int): void {
return @eca(4, buffer_id, memory_map_location, length) return @eca(4, buffer_id, memory_map_location, length)
} }
$write_length := fn(length: uint, msg: ^u8, buffer_id: uint): void { write_length := fn(msg: ^u8, buffer_id: int, length: int): void {
return @eca(3, buffer_id, msg, length) return @eca(3, buffer_id, msg, length)
} }
BufferMsg := packed struct {operation: u8, msg: ^u8, msg_len: uint} BufferMsg := packed struct {operation: u8, msg: ^u8, msg_len: uint}
$create := fn(msg: []u8): uint { create := fn(msg: ^u8): int {
return @eca(3, 0, BufferMsg.(0, msg.ptr, msg.len), @sizeof(BufferMsg)) return @eca(3, 0, BufferMsg.(0, msg, @inline(string.length, msg)), @sizeof(BufferMsg))
} }
$create_nameless := fn(): uint { search := fn(msg: ^u8): int {
return @eca(1, 0) return @eca(3, 0, BufferMsg.(3, msg, @inline(string.length, msg)), @sizeof(BufferMsg))
}
$delete := fn(buffer_id: uint): void {
return @eca(2, buffer_id)
}
$search := fn(msg: []u8): uint {
return @eca(3, 0, BufferMsg.(3, msg.ptr, msg.len), @sizeof(BufferMsg))
} }

View file

@ -1,3 +1,5 @@
$get := fn($Expr: type, query: []u8): Expr { .{string} := @use("../../stn/src/lib.hb")
return @eca(3, 5, query, query.len)
get := fn($Expr: type, query: ^u8): Expr {
return @eca(3, 5, query, @inline(string.length, query))
} }

View file

@ -2,7 +2,7 @@ acs := @use("acs.hb");
.{DiskID, FileID} := acs .{DiskID, FileID} := acs
// Paths without a node-disk component are to be treated as local files. // Paths without a node-disk component are to be treated as local files.
// file_path := "DID:/test" // file_path := "DID:/test\0";
Path := struct { Path := struct {
// DiskID holds the host id // DiskID holds the host id
disk_id: DiskID, disk_id: DiskID,

View file

@ -1,285 +0,0 @@
.{Kind, usize, string, signed_int, panic, float, integer, memory, log: .{LogLevel}} := @use("stn")
fmt_int := fn(v: @Any(), str: []u8, radix: @TypeOf(v)): uint {
is_negative := signed_int(@TypeOf(v)) & v < 0
prefix_len := 0
if is_negative {
v = -v
str[0] = '-'
prefix_len += 1
}
if radix == 16 {
*@as(^[2]u8, @bitcast(str.ptr + prefix_len)) = *@bitcast("0x".ptr)
prefix_len += 2
} else if radix == 2 {
*@as(^[2]u8, @bitcast(str.ptr + prefix_len)) = *@bitcast("0b".ptr)
prefix_len += 2
} else if radix == 8 {
*@as(^[2]u8, @bitcast(str.ptr + prefix_len)) = *@bitcast("0o".ptr)
prefix_len += 2
}
if v == 0 {
str[prefix_len] = '0'
return prefix_len + 1
}
i := prefix_len
loop if v <= 0 break else {
remainder := v % radix
v /= radix
if remainder > 9 {
str[i] = @intcast(remainder - 10 + 'A')
} else {
str[i] = @intcast(remainder + '0')
}
i += 1
}
string.reverse(str[prefix_len..i])
return i
}
fmt_bool := fn(v: bool, str: []u8): uint {
if v {
*@as(^[4]u8, @bitcast(str.ptr)) = *@bitcast("true".ptr)
return 4
} else {
*@as(^[5]u8, @bitcast(str.ptr)) = *@bitcast("false".ptr)
return 5
}
}
$FP_TOLERANCE := 0.00000001
fmt_float := fn(v: @Any(), str: []u8, precision: uint, radix: int): uint {
is_negative := v < 0
prefix_len := 0
if is_negative {
v = -v
str[0] = '-'
prefix_len += 1
}
if radix == 16 {
*@as(^[2]u8, @bitcast(str.ptr + prefix_len)) = *@bitcast("0x".ptr)
prefix_len += 2
} else if radix == 2 {
*@as(^[2]u8, @bitcast(str.ptr + prefix_len)) = *@bitcast("0b".ptr)
prefix_len += 2
} else if radix == 8 {
*@as(^[2]u8, @bitcast(str.ptr + prefix_len)) = *@bitcast("0o".ptr)
prefix_len += 2
}
integer_part := @fti(v)
fractional_part := v - @itf(integer_part)
i := prefix_len
loop if integer_part == 0 & i > prefix_len break else {
remainder := integer_part % radix
integer_part /= radix
if remainder > 9 {
str[i] = @intcast(remainder - 10 + 'A')
} else {
str[i] = @intcast(remainder + '0')
}
i += 1
}
string.reverse(str[prefix_len..i])
str[i] = '.'
i += 1
p := precision
loop if p <= 0 | fractional_part < FP_TOLERANCE break else {
fractional_part *= @itf(radix)
digit := @fti(fractional_part)
if digit > 9 {
str[i] = @intcast(digit - 10 + 'A')
} else {
str[i] = @intcast(digit + '0')
}
i += 1
fractional_part -= @itf(digit)
p -= 1
}
return i
}
fmt_container := fn(v: @Any(), str: []u8, opts: FormatOptions): uint {
T2 := @TypeOf(v)
kind := Kind.of(T2)
i := 0
len := 0
if kind == .Struct {
*@as(^[@intcast(@nameof(T2).len)]u8, @bitcast(str.ptr + len)) = *@bitcast(@nameof(T2).ptr)
len += @nameof(T2).len;
*@as(^[2]u8, @bitcast(str.ptr + len)) = *@bitcast(".(".ptr)
len += 2
} else if kind == .Slice {
*@as(^[@intcast(@nameof(@ChildOf(T2)).len)]u8, @bitcast(str.ptr + len)) = *@bitcast(@nameof(@ChildOf(T2)).ptr)
len += @nameof(@ChildOf(T2)).len;
*@as(^[2]u8, @bitcast(str.ptr + len)) = *@bitcast(".[".ptr)
len += 2
} else if kind == .Tuple {
*@as(^[2]u8, @bitcast(str.ptr + len)) = *@bitcast(".(".ptr)
len += 2
}
if kind == .Slice {
loop {
len += @inline(format, v[i], str[len..], opts)
i += 1
if i == v.len break else {
*@as(^[2]u8, @bitcast(str.ptr + len)) = *@bitcast(", ".ptr)
len += 2
}
}
} else {
$loop {
len += @inline(format, v[i], str[len..], opts)
i += 1
if i == @lenof(T2) break else {
*@as(^[2]u8, @bitcast(str.ptr + len)) = *@bitcast(", ".ptr)
len += 2
}
}
}
if kind == .Struct | kind == .Tuple {
*@as(^[1]u8, @bitcast(str.ptr + len)) = *@bitcast(")".ptr)
len += 1
} else if kind == .Slice {
*@as(^[1]u8, @bitcast(str.ptr + len)) = *@bitcast("]".ptr)
len += 1
}
return len
}
fmt_nullable := fn(v: @Any(), str: []u8, opts: FormatOptions): uint {
if v == null {
*@as(^[4]u8, @bitcast(str.ptr)) = *@bitcast("null".ptr)
return 4
} else {
return @inline(format, @as(@ChildOf(@TypeOf(v)), v), str, opts)
}
}
fmt_enum := fn(v: @Any(), str: []u8, opts: FormatOptions): uint {
T := @TypeOf(v)
len := @nameof(T).len;
*@as(^[@intcast(@nameof(T).len)]u8, @bitcast(str.ptr)) = *@bitcast(@nameof(T).ptr);
*@as(^[2]u8, @bitcast(str.ptr + len)) = *@bitcast(".(".ptr)
len += 2
len += fmt_int(@as(usize(T), @bitcast(v)), str[len..], 10);
*@as(^[2]u8, @bitcast(str.ptr + len)) = *@bitcast(")".ptr)
return len + 1
}
/* TODO:
* Custom formatters using struct methods (T._fmt(self, str): uint),
* Format struct fields "Name.{a: x, b: y, c: z}"
* Optionally tabulate
* Add more FormatOption fields
* Support scientific notation for floating point
* Support format string
*/
FormatOptions := struct {
precision: uint = 2,
radix: uint = 10,
// temporarily here, will change later maybe
log: LogLevel = .Info,
}
/* SAFETY:
* Assumes the buffer is wide enough for the formatted text and a null char
* Does not clear the buffer for you
*/
format := fn(v: @Any(), str: []u8, opts: FormatOptions): uint {
T := @TypeOf(v)
match Kind.of(T) {
.Pointer => return @inline(fmt_int, @as(uint, @bitcast(v)), str, 16),
.Builtin => {
if integer(T) {
return @inline(fmt_int, v, str, @intcast(opts.radix))
} else if T == bool {
return @inline(fmt_bool, v, str)
} else if float(T) {
return @inline(fmt_float, v, str, opts.precision, @intcast(opts.radix))
}
},
.Opt => return @inline(fmt_nullable, v, str, opts),
.Enum => return @inline(fmt_enum, v, str, opts),
.Struct => return @inline(fmt_container, v, str, opts),
.Tuple => return @inline(fmt_container, v, str, opts),
.Slice => if T != []u8 return @inline(fmt_container, v, str, opts) else {
i := 0
loop if i == v.len break else {
str[i] = v[i]
i += 1
}
return v.len
},
_ => @error("Type: \"", T, "\" is not supported."),
}
}
format_with_str := fn(v: @Any(), read: []u8, write: []u8, opts: FormatOptions): uint {
T := @TypeOf(v)
n := string.count(read, '{')
if n != string.count(read, '}') panic("Missing closing '}' in format string.")
if Kind.of(T) == .Tuple {
if @lenof(T) != n panic("Format string has different number of '{}' than args given.")
m := 0
i := 0
j := 0
$loop if m > @lenof(T) break else {
if m == @lenof(T) {
loop if i == read.len break else {
write[j] = read[i]
i += 1
j += 1
}
m += 1
} else {
v2 := v[m]
loop if i == read.len break else {
if read[i] == '{' & read[i + 1] == '}' {
j += format(v2, write[j..], opts)
i += 2
break
} else {
write[j] = read[i]
i += 1
j += 1
}
}
m += 1
}
}
return j
} else if n > 1 {
panic("Format string has multiple '{}' but value provided is not a tuple.")
} else {
i := 0
j := 0
loop if i == read.len break else {
if read[i] == '{' & read[i + 1] == '}' {
j += format(v, write[j..], opts)
i += 2
} else {
write[j] = read[i]
i += 1
j += 1
}
}
return j
}
}

View file

@ -1,181 +0,0 @@
/*
* This code is an implementation of the FoldHash algorithm from https://github.com/orlp/foldhash,
* originally written by Orson Peters under the zlib license.
*
* Changes to the original code were made to meet the simplicity requirements of this implementation.
* Behaviour aims to be equivalent but not identical to the original code.
*
* Copyright (c) 2024 Orson Peters
*
* This software is provided 'as-is', without any express or implied warranty. In
* no event will the authors be held liable for any damages arising from the use of
* this software.
*
* Permission is granted to anyone to use this software for any purpose, including
* commercial applications, and to alter it and redistribute it freely, subject to
* the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim
* that you wrote the original software. If you use this software in a product,
* an acknowledgment in the product documentation would be appreciated but is
* not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*/;
.{math, random} := @use("stn")
$ARBITRARY0 := 0x243F6A8885A308D3
$ARBITRARY1 := 0x13198A2E03707344
$ARBITRARY2 := 0xA4093822299F31D0
$ARBITRARY3 := 0x82EFA98EC4E6C89
$ARBITRARY4 := 0x452821E638D01377
$ARBITRARY5 := 0xBE5466CF34E90C6C
$ARBITRARY6 := 0xC0AC29B7C97C50DD
$ARBITRARY7 := 0x3F84D5B5B5470917
$ARBITRARY8 := 0x9216D5D98979FB1B
$ARBITRARY9 := 0xD1310BA698DFB5AC
$FIXED_GLOBAL_SEED := uint.[ARBITRARY4, ARBITRARY5, ARBITRARY6, ARBITRARY7]
global_seed := 0
u128 := packed struct {a: uint, b: uint}
$folded_multiply := fn(x: uint, y: uint): uint {
lx := @as(u32, @intcast(x))
ly := @as(u32, @intcast(y))
hx := x >> 32
hy := y >> 32
afull := lx * hy
bfull := hx * ly
return afull ^ (bfull << 32 | bfull >> 32)
}
hash_bytes_medium := fn(bytes: ^u8, len: uint, s0: uint, s1: uint, fold_seed: uint): uint {
lo := bytes
end := bytes + len
hi := end - 16
loop if lo >= hi break else {
a := *@as(^uint, @bitcast(lo))
b := *@as(^uint, @bitcast(lo + 8))
c := *@as(^uint, @bitcast(hi))
d := *@as(^uint, @bitcast(hi + 8))
s0 = folded_multiply(a ^ s0, c ^ fold_seed)
s1 = folded_multiply(b ^ s1, d ^ fold_seed)
hi -= 16
lo += 16
}
return s0 ^ s1
}
hash_bytes_long := fn(bytes: ^u8, len: uint, s0: uint, s1: uint, s2: uint, s3: uint, fold_seed: uint): uint {
$chunk_size := 64
chunks := len / chunk_size
remainder := len % chunk_size
ptr := bytes
i := 0
loop if i >= chunks break else {
a := *@as(^uint, @bitcast(ptr))
b := *@as(^uint, @bitcast(ptr + 8))
c := *@as(^uint, @bitcast(ptr + 16))
d := *@as(^uint, @bitcast(ptr + 24))
e := *@as(^uint, @bitcast(ptr + 32))
f := *@as(^uint, @bitcast(ptr + 40))
g := *@as(^uint, @bitcast(ptr + 48))
h := *@as(^uint, @bitcast(ptr + 56))
s0 = folded_multiply(a ^ s0, e ^ fold_seed)
s1 = folded_multiply(b ^ s1, f ^ fold_seed)
s2 = folded_multiply(c ^ s2, g ^ fold_seed)
s3 = folded_multiply(d ^ s3, h ^ fold_seed)
ptr += chunk_size
i += 1
}
s0 ^= s2
s1 ^= s3
if remainder > 0 {
remainder_start := bytes + len - math.max(uint, remainder, 16)
return @inline(hash_bytes_medium, remainder_start, math.max(uint, remainder, 16), s0, s1, fold_seed)
}
return s0 ^ s1
}
FoldHasher := struct {
accumulator: uint,
original_seed: uint,
sponge: u128,
sponge_len: u8,
fold_seed: uint,
expand_seed: uint,
expand_seed2: uint,
expand_seed3: uint,
$new := fn(seed: uint): Self {
return .(
seed,
seed,
.(0, 0),
0,
FIXED_GLOBAL_SEED[0],
FIXED_GLOBAL_SEED[1],
FIXED_GLOBAL_SEED[2],
FIXED_GLOBAL_SEED[3],
)
}
default := fn(): Self {
if global_seed == 0 {
// ! consider this "secure enough" for now
global_seed = random.any(uint)
}
return Self.new(global_seed)
}
write := fn(self: ^Self, bytes: ^u8, len: uint): void {
s0 := self.accumulator
s1 := self.expand_seed
if len <= 16 {
if len >= 8 {
s0 ^= *@bitcast(bytes)
s1 ^= *@bitcast(bytes + len - 8)
} else if len >= 4 {
s0 ^= *@as(^u32, @bitcast(bytes))
s1 ^= *@as(^u32, @bitcast(bytes + len - 4))
} else if len > 0 {
lo := *bytes
mid := *(bytes + len / 2)
hi := *(bytes + len - 1)
s0 ^= lo
s1 ^= @as(uint, hi) << 8 | mid
}
self.accumulator = folded_multiply(s0, s1)
} else if len < 256 {
self.accumulator = @inline(hash_bytes_medium, bytes, len, s0, s1, self.fold_seed)
} else {
self.accumulator = @inline(hash_bytes_long, bytes, len, s0, s1, self.expand_seed2, self.expand_seed3, self.fold_seed)
}
}
finish := fn(self: ^Self): uint {
if self.sponge_len > 0 {
return folded_multiply(self.sponge.b ^ self.accumulator, self.sponge.a ^ self.fold_seed)
} else {
return self.accumulator
}
}
reset := fn(self: ^Self): void {
self.accumulator = self.original_seed
self.sponge = .(0, 0)
self.sponge_len = 0
}
}

View file

@ -1,2 +0,0 @@
//! NON CRYPTOGRAPHIC HASHER
foldhash := @use("foldhash.hb")

View file

@ -1,7 +1,4 @@
acs := @use("acs.hb") acs := @use("acs.hb")
allocators := @use("alloc/lib.hb")
fmt := @use("fmt.hb")
hashers := @use("hash/lib.hb")
string := @use("string.hb") string := @use("string.hb")
log := @use("log.hb") log := @use("log.hb")
memory := @use("memory.hb") memory := @use("memory.hb")
@ -9,58 +6,4 @@ buffer := @use("buffer.hb")
math := @use("math.hb") math := @use("math.hb")
random := @use("random.hb") random := @use("random.hb")
file := @use("file_io.hb") file := @use("file_io.hb")
dt := @use("dt.hb") dt := @use("dt.hb")
process := @use("process.hb")
sleep := @use("sleep.hb")
panic := fn(message: ?[]u8): never {
log.printf("HBLang Panic: {}", message, .{log: .Error})
die
}
Kind := enum {
Builtin,
Struct,
Tuple,
Enum,
Union,
Pointer,
Slice,
Opt,
Function,
Template,
Global,
Const,
Module,
$of := fn($T: type): Self {
return @bitcast(@kindof(T))
}
}
$unsigned_int := fn($T: type): bool {
return T == uint | T == u8 | T == u16 | T == u32
}
$signed_int := fn($T: type): bool {
return T == int | T == i8 | T == i16 | T == i32
}
$integer := fn($T: type): bool {
return unsigned_int(T) | signed_int(T)
}
$float := fn($T: type): bool {
return T == f32 | T == f64
}
$usize := fn($T: type): type {
if @sizeof(T) == 1 return u8 else if @sizeof(T) == 2 return u16 else if @sizeof(T) == 4 return u32 else return uint
}
$bits := fn($T: type): usize(T) {
return @sizeof(T) << 3
}
$bitmask := fn($T: type): usize(T) {
return -1
}

View file

@ -1,41 +1,13 @@
.{string, fmt, memory} := @use("stn") string := @use("string.hb")
LogMsg := packed struct {level: LogLevel, string: ^u8, strlen: uint} LogMsg := packed struct {level: u8, string: ^u8, strlen: uint}
LogLevel := enum { log := fn(level: u8, message: ^u8): void {
Error, return @eca(3, 1, LogMsg.(level, message, @inline(string.length, message)), @sizeof(LogMsg))
Warn,
Info,
Debug,
Trace,
} }
$log := fn(level: LogLevel, message: []u8): void { error := fn(message: ^u8): void return @inline(log, 0, message)
return @eca(3, 1, LogMsg.(level, message.ptr, message.len), @sizeof(LogMsg)) warn := fn(message: ^u8): void return @inline(log, 1, message)
} info := fn(message: ^u8): void return @inline(log, 2, message)
debug := fn(message: ^u8): void return @inline(log, 3, message)
$error := fn(message: []u8): void return log(LogLevel.Error, message) trace := fn(message: ^u8): void return @inline(log, 4, message)
$warn := fn(message: []u8): void return log(LogLevel.Warn, message)
$info := fn(message: []u8): void return log(LogLevel.Info, message)
$debug := fn(message: []u8): void return log(LogLevel.Debug, message)
$trace := fn(message: []u8): void return log(LogLevel.Trace, message)
print_buffer := memory.dangling(u8)
print := fn(v: @Any(), opts: fmt.FormatOptions): void {
if print_buffer == memory.dangling(u8) {
print_buffer = memory.request_page(1)
}
len := @inline(fmt.format, v, print_buffer[0..memory.PAGE_SIZE], opts)
@eca(3, 1, LogMsg.(opts.log, print_buffer, len), @sizeof(LogMsg))
memory.set(u8, &0, print_buffer, len)
}
printf := fn(str: []u8, v: @Any(), opts: fmt.FormatOptions): void {
if print_buffer == memory.dangling(u8) {
print_buffer = memory.request_page(1)
}
len := @inline(fmt.format_with_str, v, str, print_buffer[0..memory.PAGE_SIZE], opts)
@eca(3, 1, LogMsg.(opts.log, print_buffer, len), @sizeof(LogMsg))
memory.set(u8, &0, print_buffer, len)
}

File diff suppressed because one or more lines are too long

View file

@ -1,79 +1,67 @@
$PAGE_SIZE := 4096 PAGE_SIZE := 4096
$MAX_ALLOC := 0xFF MAX_ALLOC := 0xFF
$MAX_FREE := 0xFF MAX_FREE := 0xFF
$uninit := fn($Expr: type): Expr { calc_pages := fn($Expr: type, num: uint): uint {
return idk return 1 + @sizeof(Expr) * num / PAGE_SIZE
} }
$nulled := fn($Expr: type): ?Expr {
return null
}
$dangling := fn($Expr: type): ^Expr {
return @bitcast(@alignof(Expr))
}
$calc_pages := fn($Expr: type, num: uint): uint {
return (num + PAGE_SIZE - 1) / PAGE_SIZE
}
// ! will be replaced, don't get attached
alloc := fn($Expr: type, num: uint): ^Expr { alloc := fn($Expr: type, num: uint): ^Expr {
return @bitcast(request_page(@intcast(calc_pages(Expr, num)))) pages := @inline(calc_pages, Expr, num)
if pages <= MAX_ALLOC {
return @bitcast(request_page(@intcast(pages)))
}
ptr := request_page(0xFF)
remaining := pages - MAX_ALLOC
loop if remaining < MAX_ALLOC break else {
_ := request_page(@intcast(MAX_ALLOC))
remaining -= MAX_ALLOC
}
_ := request_page(@intcast(remaining))
return @bitcast(ptr)
} }
// ! stub // ! stub
$free := fn($Expr: type, ptr: ^Expr, num: uint): void { free := fn($Expr: type, ptr: ^Expr, num: uint, nullify: bool): void {
release_page(@bitcast(ptr), @intcast(calc_pages(Expr, num))) return
} }
RqPageMsg := packed struct {a: u8, count: uint} RqPageMsg := packed struct {a: u8, count: u8}
$request_page := fn(count: uint): ^u8 { request_page := fn(count: u8): ^u8 {
return @eca(3, 2, &RqPageMsg.(0, count), @sizeof(RqPageMsg)) return @eca(3, 2, &RqPageMsg.(0, count), @sizeof(RqPageMsg))
} }
RlPageMsg := packed struct {a: u8, count: uint, ptr: ^u8} RlPageMsg := packed struct {a: u8, count: u8, ptr: ^u8}
$release_page := fn(ptr: ^u8, count: uint): void { release_page := fn(ptr: ^u8, count: u8): void {
return @eca(3, 2, &RlPageMsg.(1, count, ptr), @sizeof(RlPageMsg)) return @eca(3, 2, &RlPageMsg.(1, count, ptr), @sizeof(RlPageMsg))
} }
OutbMsg := packed struct {a: u8, b: u8, addr: u16, value: u8} OutbMsg := packed struct {a: u8, b: u8, addr: u16, value: u8}
$outb := fn(addr: u16, value: u8): void { outb := fn(addr: u16, value: u8): void {
return @eca(3, 3, &OutbMsg.(1, 0, addr, value), @sizeof(OutbMsg)) return @eca(3, 3, &OutbMsg.(1, 0, addr, value), @sizeof(OutbMsg))
} }
InbMsg := packed struct {a: u8, b: u8, addr: u16} InbMsg := packed struct {a: u8, b: u8, addr: u16}
$inb := fn(addr: u16): u8 { inb := fn(addr: u16): u8 {
return @eca(3, 3, &InbMsg.(0, 0, addr), @sizeof(InbMsg)) return @eca(3, 3, &InbMsg.(0, 0, addr), @sizeof(InbMsg))
} }
OutlMsg := packed struct {a: u8, b: u8, addr: u16, value: u32} OutlMsg := packed struct {a: u8, b: u8, addr: u16, value: u32}
$outl := fn(addr: u16, value: u32): void { outl := fn(addr: u16, value: u32): void {
return @eca(3, 3, &OutlMsg.(1, 2, addr, value), @sizeof(OutlMsg)) return @eca(3, 3, &OutlMsg.(1, 2, addr, value), @sizeof(OutlMsg))
} }
InlMsg := packed struct {a: u8, b: u8, addr: u16} InlMsg := packed struct {a: u8, b: u8, addr: u16}
$inl := fn(addr: u16): u32 { inl := fn(addr: u16): u32 {
return @eca(3, 3, &InlMsg.(0, 2, addr), @sizeof(InlMsg)) return @eca(3, 3, &InlMsg.(0, 2, addr), @sizeof(InlMsg))
} }
OutsMsg := packed struct {a: u8, b: u8, addr: u16, value: u16} CopyMsg := packed struct {a: u8, count: u32, src: ^u8, dest: ^u8}
$outs := fn(addr: u16, value: u32): void { copy := fn($Expr: type, src: ^Expr, dest: ^Expr, count: uint): void {
return @eca(3, 3, &OutsMsg.(1, 1, addr, value), @sizeof(OutsMsg)) return @eca(3, 2, &CopyMsg.(4, @intcast(count * @sizeof(Expr)), @bitcast(src), @bitcast(dest)), @sizeof(CopyMsg))
} }
InsMsg := packed struct {a: u8, b: u8, addr: u16} SetMsg := packed struct {a: u8, count: u32, size: u32, src: ^u8, dest: ^u8}
$ins := fn(addr: u16): u16 { set := fn($Expr: type, src: ^Expr, dest: ^Expr, count: uint): void {
return @eca(3, 3, &InsMsg.(0, 1, addr), @sizeof(InsMsg)) return @eca(3, 2, &SetMsg.(5, @intcast(count), @intcast(@sizeof(Expr)), @bitcast(src), @bitcast(dest)), @sizeof(SetMsg))
}
CopyMsg := packed struct {a: u8, count: uint, src: ^u8, dest: ^u8}
$copy := fn($Expr: type, src: ^Expr, dest: ^Expr, count: uint): void {
return @eca(3, 2, &CopyMsg.(4, count * @sizeof(Expr), @bitcast(src), @bitcast(dest)), @sizeof(CopyMsg))
}
SetMsg := packed struct {a: u8, count: uint, size: uint, src: ^u8, dest: ^u8}
$set := fn($Expr: type, src: ^Expr, dest: ^Expr, count: uint): void {
return @eca(3, 2, &SetMsg.(5, count, @sizeof(Expr), @bitcast(src), @bitcast(dest)), @sizeof(SetMsg))
} }

View file

@ -1,12 +0,0 @@
// ! will be rewritten to take a file object when filesystem is exist
// returns PID
$spawn := fn(proc_exe: ^u8, length: uint): uint {
return @eca(3, 6, proc_exe, length)
}
/* TODO:
- Spawn an empty process
- Call a function to load bytes into that process from a function
Or
- Manually fill the bytes in
- Execute the process via a run type command */

View file

@ -1,15 +1,7 @@
$any := fn($Expr: type): Expr { any := fn($Expr: type): Expr {
return *@eca(3, 4, &@as(Expr, idk), @sizeof(Expr)) return *@eca(3, 4, &@as(Expr, idk), @sizeof(Expr))
} }
$range := fn($Expr: type, min: Expr, max: Expr): Expr { range := fn($Expr: type, min: Expr, max: Expr): Expr {
return *@eca(3, 4, &@as(Expr, idk), @sizeof(Expr)) % (max - min) + *@bitcast(&1) + min return @inline(any, Expr) % (max - min) + @intcast(1) + min
}
$fill := fn($Expr: type, ptr: ^Expr): void {
return @eca(3, 4, ptr, @sizeof(Expr))
}
$fill_buffer := fn(buf: ^u8, len: uint): void {
return @eca(3, 4, buf, len)
} }

View file

@ -1,7 +0,0 @@
$subscribe_to_interrupt := fn(interrupt_number: u8): bool {
return false
}
// Pauses execution until the interrupt occures
$sleep_until_interrupt := fn(interrupt_number: u8): void {
@eca(6, interrupt_number)
}

View file

@ -1,172 +1,72 @@
// todo: splice function length := fn(ptr: ^u8): uint {
len := @as(uint, 0)
// loop if *(ptr + len) == 0 return len else len += 1
loop if *(ptr + len) == 0 break else len += 1
return len
}
reverse := fn(str: []u8): void { display_int := fn(num: int, p: ^u8, radix: uint): ^u8 {
if str.len == 0 return; ptr := p
j := str.len - 1 negative := num < 0
i := 0 if negative {
num = -num
}
if radix == 2 {
*ptr = 48
ptr += 1;
*ptr = 98
ptr += 1
} else if radix == 16 {
*ptr = 48
ptr += 1;
*ptr = 120
ptr += 1
} else if radix == 8 {
*ptr = 48
ptr += 1;
*ptr = 111
ptr += 1
}
digits_start := ptr
if num == 0 {
*ptr = 48
ptr += 1
} else {
loop if num == 0 break else {
digit := num % @bitcast(radix)
if digit < 10 {
*ptr = @intcast(digit) + 48
} else {
*ptr = @intcast(digit) + 55
}
ptr += 1
num /= @bitcast(radix)
}
}
if negative {
*ptr = 45
ptr += 1
};
*ptr = 0
@inline(reverse, digits_start)
return p
}
reverse := fn(s: ^u8): void {
i := @as(uint, 0)
j := @inline(length, s) - 1
temp := @as(u8, 0) temp := @as(u8, 0)
loop if i < j { loop if i >= j break else {
temp = str[i] temp = *(s + i);
str[i] = str[j] *(s + i) = *(s + j);
str[j] = temp *(s + j) = temp
i += 1 i += 1
j -= 1 j -= 1
} else return
}
equals := fn(lhs: []u8, rhs: []u8): bool {
if lhs.len != rhs.len return false
if lhs.ptr == rhs.ptr return true
i := 0
loop if i == lhs.len break else {
if lhs[i] != rhs[i] return false
i += 1
} }
return true return
}
clear := fn(str: []u8): void {
i := 0
loop if i == str.len break else {
str[i] = 0
i += 1
}
}
split_once := fn(haystack: []u8, needle: @Any()): ?struct {left: []u8, right: []u8} {
T := @TypeOf(needle)
i := 0
if T == []u8 {
if needle.len == 0 return null
loop {
if i + needle.len > haystack.len return null
if haystack[i] == needle[0] {
matches := true
n := 1
loop {
if n == needle.len break
if haystack[i + n] != needle[n] {
matches = false
break
}
n += 1
}
if matches return .(haystack[0..i], haystack[i + needle.len..])
}
i += 1
}
} else if T == u8 {
loop {
if haystack[i] == needle {
return .(haystack[0..i], haystack[i + 1..])
} else if i == haystack.len return null
i += 1
}
} else {
@error("Type of needle must be []u8 or u8.")
}
}
split := fn(iter: []u8, needle: @Any()): struct {
str: []u8,
needle: @TypeOf(needle),
done: bool,
next := fn(self: ^Self): ?[]u8 {
if self.done return null;
splits := split_once(self.str, self.needle)
if splits != null {
self.str = splits.right
return splits.left
} else {
self.done = true
return self.str
}
}
} {
T := @TypeOf(needle)
if T != []u8 & T != u8 {
@error("Type of needle must be []u8 or u8.")
}
return .(iter, needle, false)
}
chars := fn(iter: []u8): struct {
str: []u8,
next := fn(self: ^Self): ?u8 {
if self.str.len == 0 return null
self.str = self.str[1..]
return self.str[0]
}
} {
return .(iter)
}
count := fn(haystack: []u8, needle: @Any()): uint {
T := @TypeOf(needle)
i := 0
c := 0
if T == []u8 {
if needle.len == 0 return null
loop {
if i + needle.len > haystack.len return c
if haystack[i] == needle[0] {
matches := true
n := 1
loop {
if n == needle.len break
if haystack[i + n] != needle[n] {
matches = false
break
}
n += 1
}
if matches c += 1
}
i += 1
}
} else if T == u8 {
loop {
if haystack[i] == needle c += 1 else if i == haystack.len return c
i += 1
}
} else {
@error("Type of needle must be []u8 or u8.")
}
}
left_trim := fn(str: []u8, sub: []u8): []u8 {
i := 0
if str[0] == sub[0] {
loop if i == sub.len {
return str[i..str.len]
} else if str[i] != sub[i] | i == str.len {
break
} else {
i += 1
}
}
return str
}
right_trim := fn(str: []u8, sub: []u8): []u8 {
i := 0
if str[str.len - 1] == sub[sub.len - 1] {
loop if i == sub.len {
return str[0..str.len - i]
} else if str[str.len - i - 1] != sub[sub.len - i - 1] | i == str.len {
break
} else {
i += 1
}
}
return str
}
trim := fn(str: []u8, sub: []u8): []u8 {
return right_trim(left_trim(str, sub), sub)
} }

View file

@ -1,63 +0,0 @@
.{math: .{Vec2}, buffer, log, memory, string} := @use("stn");
.{Channel, Window, send_header, send_message, await_channel, await_header, await_message, message, BUFFER_SERVER, BUFFER_CLIENT, WindowProps, WindowData} := @use("lib:sunset_proto");
.{Surface, Color} := @use("lib:render")
// ! in the future this should be safely handled
channel := Channel.(0, 0)
find_server := fn(): void {
log.info("client: locating server")
channel2 := await_channel()
channel.server = channel2.server
channel.client = channel2.client
log.info("client: server located")
}
new := fn(props: WindowProps): ?Window {
send_header(message.syn, channel.server)
response := await_message(Channel, channel.client)
if response.header.kind != message.ack {
return null
}
log.info("client: recv ack")
send_message(WindowProps, message.props, props, response.body.server)
windowdata := await_message(WindowData, response.body.client)
if windowdata.header.kind != message.ack {
return null
}
log.info("client: recv windowdata")
surface := Surface.new(windowdata.body.props.dimensions.x, windowdata.body.props.dimensions.y)
return .(windowdata.body, surface)
}
quit := fn(client: Window): void {
send_header(message.quit, client.data.channel.server)
}
connected := fn(client: Window): bool {
return true
}
shutdown_server := fn(client: Window): bool {
return false
}
update_props := fn(client: Window): bool {
return false
}
update_permissions := fn(client: Window): bool {
return false
}
send_frame := fn(client: Window): bool {
send_header(message.frame_ready, client.data.channel.server)
response := await_message(uint, client.data.channel.client)
if response.header.kind != message.ack {
return false
}
// ! FOR NOW, server will ALWAYS be local,
// ! so we can send pointer to surface.
send_message(^Color, message.ack, client.surface.buf, client.data.channel.server)
return true
}

View file

@ -1,100 +0,0 @@
.{math: .{Vec2}, buffer, memory} := @use("stn");
.{Surface} := @use("lib:render")
$BUFFER_SERVER := "sunset_server"
$BUFFER_CLIENT := "sunset_client"
Channel := packed struct {
client: uint,
server: uint,
}
client := @use("./client.hb")
server := @use("./server.hb")
message := @use("./message.hb")
permissions := @use("./permissions.hb")
$send_message := fn($Expr: type, kind: MessageKind, msg: Expr, buffer_id: uint): void {
buffer.write(?Message(Expr), buffer_id, &@as(?Message(Expr), .(.(kind), msg)))
}
$send_header := fn(kind: MessageKind, buffer_id: uint): void {
buffer.write(?MessageHeader, buffer_id, &@as(?MessageHeader, .(kind)))
}
$recv_message := fn($Expr: type, buffer_id: uint): Message(Expr) {
response := @as(?Message(Expr), null)
buffer.recv(?Message(Expr), buffer_id, &response)
return response
}
$recv_header := fn(buffer_id: uint): ?MessageHeader {
response := @as(?MessageHeader, null)
buffer.recv(?MessageHeader, buffer_id, &response)
return response
}
await_channel := fn(): Channel {
channel := Channel.(0, 0)
loop if channel.server != 0 break else {
channel.server = buffer.search(BUFFER_SERVER)
}
loop if channel.client != 0 break else {
channel.client = buffer.search(BUFFER_CLIENT)
}
return channel
}
await_message := fn($Expr: type, buffer_id: uint): Message(Expr) {
response := @as(?Message(Expr), null)
loop {
// awaiting here causes flickering... idk why
buffer.await(buffer_id)
buffer.recv(?Message(Expr), buffer_id, &response)
if response != null {
return @as(Message(Expr), response)
}
}
}
await_header := fn(buffer_id: uint): MessageHeader {
response := @as(?MessageHeader, null)
loop {
// awaiting here causes flickering... idk why
buffer.await(buffer_id)
buffer.recv(?MessageHeader, buffer_id, &response)
if response != null {
return @as(MessageHeader, response)
}
}
}
MessageKind := u8
MessageHeader := packed struct {
kind: MessageKind,
}
Message := fn($Expr: type): type {
return packed struct {
header: MessageHeader,
body: Expr,
}
}
WindowProps := struct {
position: Vec2(uint),
dimensions: Vec2(uint),
title: []u8,
}
WindowData := struct {
props: WindowProps,
channel: Channel,
permissions: uint,
}
Window := struct {
data: WindowData,
surface: Surface,
}

View file

@ -1,8 +0,0 @@
// ! all values in this file are subject to change.
$syn := 1
$ack := 2
$refused := 3
$quit := 4
$props := 5
$shutdown := 6
$frame_ready := 7

View file

@ -1,5 +0,0 @@
$none := 0b0
$exclusive_framebuffer := 0b1
$shutdown := 0b100
$default := none

View file

@ -1,131 +0,0 @@
.{math, log, string, random, buffer, memory} := @use("stn");
.{Color, Surface, text} := @use("lib:render");
.{Channel, Window, WindowProps, WindowData, MessageHeader, BUFFER_SERVER, BUFFER_CLIENT, message, permissions, recv_header, recv_message, send_message, send_header, await_message} := @use("lib:sunset_proto")
WindowServer := struct {
window_count: uint,
channel: Channel,
// ! replace this with a collection when we get an allocator
windows: [10]?Window,
font: text.Font,
}
// ! in the future this should be safely handled
server := @as(WindowServer, idk)
psf := @embed("sysdata:assets/consolefonts/tamsyn/10x20r.psf")
start := fn(): void {
font := text.font_from_psf2(@bitcast(&psf), false)
if font == null {
log.error("server: failed to load asset")
return
}
server = .(
0,
.{client: buffer.create(BUFFER_CLIENT), server: buffer.create(BUFFER_SERVER)},
.[null, null, null, null, null, null, null, null, null, null],
@as(text.Font, font),
)
log.info("server: started server")
}
incoming := fn(): bool {
msg := recv_header(server.channel.server)
if msg == null {
return true
}
if msg.kind == message.syn {
log.info("server: recv syn")
channel := Channel.(buffer.create_nameless(), buffer.create_nameless())
send_message(Channel, message.ack, channel, server.channel.client)
props := await_message(WindowProps, channel.server)
if props.header.kind != message.props {
return true
}
log.info("server: recv props")
// ! do inspection of requested props here
data := WindowData.(props.body, channel, permissions.default)
send_message(WindowData, message.ack, data, channel.client)
surface := new_window_decorations(data.props.dimensions)
// decorations
{
title := data.props.title
deco_length := title.len * 10
// draw the window tab bar
surface.put_filled_rect(.(0, 0), .(data.props.dimensions.x + DECO_WIDTH + deco_length, DECO_HEIGHT_TOP), DECO_COLOUR)
// Draw the window tab
surface.put_filled_rect(.(0, 0), .(deco_length, DECO_HEIGHT_TOP - 1), DECO_COLOUR_DARKER)
// Draw the outside box
surface.put_rect(.(0, 0), data.props.dimensions + .(DECO_WIDTH - 1, DECO_HEIGHT_TOP + DECO_HEIGHT_BOTTOM - 1), DECO_COLOUR)
surface.put_text(server.font, .(2, 1), .(0, 0, 0, 255), data.props.title)
}
server.windows[server.window_count] = .(data, surface)
server.window_count += 1
}
return true
}
$DECO_WIDTH := 2
$DECO_HEIGHT_TOP := 20
$DECO_HEIGHT_BOTTOM := 1
$DECO_COLOUR := Color.(100, 200, 255, 255)
$DECO_COLOUR_DARKER := Color.(89, 57, 89, 255)
new_window_decorations := fn(dimensions: math.Vec2(uint)): Surface {
return @inline(Surface.new, dimensions.x + DECO_WIDTH, dimensions.y + DECO_HEIGHT_TOP + DECO_HEIGHT_BOTTOM)
}
// ! compositor code. this currently disallows tearing.
collect_frames := fn(): void {
i := 0
loop if i == 10 break else {
window := server.windows[i]
if window == null {
i += 1
continue
}
header := recv_header(window.data.channel.server)
if header == null {
i += 1
continue
}
if header.kind != message.frame_ready {
i += 1
continue
}
send_header(message.ack, window.data.channel.client)
ptr := await_message(^Color, window.data.channel.server)
if ptr.header.kind != message.ack {
i += 1
continue
}
window.surface.put_surface(
Surface.(
ptr.body,
window.data.props.dimensions.x,
window.data.props.dimensions.y,
window.data.props.dimensions.x * window.data.props.dimensions.y,
),
.(DECO_WIDTH / 2, DECO_HEIGHT_TOP),
false,
)
i += 1
}
}
render_clients := fn(screen: Surface): void {
i := 0
loop if i == 10 break else {
window := server.windows[i]
if window == null {
i += 1
continue
}
screen.put_surface(window.surface, window.data.props.position, false)
i += 1
}
}

View file

@ -1 +0,0 @@
# ablefetch

View file

@ -1,43 +0,0 @@
stn := @use("stn")
sunset := @use("lib:sunset_proto")
render := @use("lib:render")
psf := @embed("sysdata:assets/consolefonts/tamsyn/10x20r.psf")
horizon_api := @use("lib:horizon_api");
.{Vec2} := stn.math;
.{log} := stn;
.{set_color, render_label_to_surface, Label} := horizon_api.widgets.label
main := fn(): void {
sunset.client.find_server()
window := sunset.client.new(.(.(10, 10), .(400, 300), "ableFetch!"))
font := @unwrap(render.text.font_from_psf2(@bitcast(&psf), false))
// pos := Vec2(uint).(1, 100)
if window == null {
log.error("got no window")
return
}
text_label := Label.new_label("kernel : akern 0.2.0", 300)
text_label_2 := Label.new_label("os : ableos", 300)
text_label_3 := Label.new_label("wm : sunset", 300)
text_label.set_color(render.BLACK, render.WHITE)
text_label_2.set_color(render.BLACK, render.WHITE)
text_label_3.set_color(render.BLACK, render.WHITE)
pos1 := Vec2(uint).(1, 1)
pos2 := Vec2(uint).(1, 20)
pos3 := Vec2(uint).(1, 40)
render_label_to_surface(window.surface, text_label, font, pos1)
render_label_to_surface(window.surface, text_label_2, font, pos2)
render_label_to_surface(window.surface, text_label_3, font, pos3)
loop {
// stn.log.info("AAAA")
_ = sunset.client.send_frame(window)
// stn.sleep.sleep_until_interrupt(100)
}
}

Some files were not shown because too many files have changed in this diff Show more