dev/prometeuc-improvements #5

Merged
bquarkz merged 11 commits from dev/prometeuc-improvements into master 2026-01-21 10:55:48 +00:00
76 changed files with 2820 additions and 756 deletions

2
.gitignore vendored
View File

@ -54,3 +54,5 @@ sdcard/**
dist-staging
dist-staging/**
temp
temp/**

296
Cargo.lock generated
View File

@ -86,7 +86,7 @@ dependencies = [
"ndk-context",
"ndk-sys 0.6.0+11769913",
"num_enum",
"thiserror",
"thiserror 1.0.69",
]
[[package]]
@ -187,12 +187,6 @@ dependencies = [
"libloading 0.7.4",
]
[[package]]
name = "assert-unchecked"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7330592adf847ee2e3513587b4db2db410a0d751378654e7e993d9adcbe5c795"
[[package]]
name = "atomic-waker"
version = "1.1.2"
@ -270,9 +264,6 @@ name = "bumpalo"
version = "3.19.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510"
dependencies = [
"allocator-api2",
]
[[package]]
name = "bytemuck"
@ -297,7 +288,7 @@ dependencies = [
"polling",
"rustix 0.38.44",
"slab",
"thiserror",
"thiserror 1.0.69",
]
[[package]]
@ -476,9 +467,9 @@ dependencies = [
[[package]]
name = "compact_str"
version = "0.8.1"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b79c4069c6cad78e2e0cdfcbd26275770669fb39fd308a752dc110e83b9af32"
checksum = "3fdb1325a1cece981e8a296ab8f0f9b63ae357bd0784a9faaf548cc7b480707a"
dependencies = [
"castaway",
"cfg-if",
@ -642,6 +633,12 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76"
[[package]]
name = "dragonbox_ecma"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a5577f010d4e1bb3f3c4d6081e05718eb6992cf20119cab4d3abadff198b5ae"
[[package]]
name = "either"
version = "1.15.0"
@ -664,6 +661,12 @@ dependencies = [
"windows-sys 0.61.2",
]
[[package]]
name = "fastrand"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
[[package]]
name = "find-msvc-tools"
version = "0.1.7"
@ -784,7 +787,7 @@ checksum = "6f56f6318968d03c18e1bcf4857ff88c61157e9da8e47c5f29055d60e1228884"
dependencies = [
"log",
"presser",
"thiserror",
"thiserror 1.0.69",
"winapi",
"windows 0.52.0",
]
@ -819,20 +822,14 @@ dependencies = [
"allocator-api2",
]
[[package]]
name = "hashbrown"
version = "0.15.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
dependencies = [
"allocator-api2",
]
[[package]]
name = "hashbrown"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
dependencies = [
"allocator-api2",
]
[[package]]
name = "hassle-rs"
@ -844,7 +841,7 @@ dependencies = [
"com",
"libc",
"libloading 0.8.9",
"thiserror",
"thiserror 1.0.69",
"widestring",
"winapi",
]
@ -909,7 +906,7 @@ dependencies = [
"combine",
"jni-sys",
"log",
"thiserror",
"thiserror 1.0.69",
"walkdir",
"windows-sys 0.45.0",
]
@ -1091,7 +1088,7 @@ dependencies = [
"rustc-hash 1.1.0",
"spirv",
"termcolor",
"thiserror",
"thiserror 1.0.69",
"unicode-xid",
]
@ -1106,7 +1103,7 @@ dependencies = [
"log",
"ndk-sys 0.5.0+25.2.9519653",
"num_enum",
"thiserror",
"thiserror 1.0.69",
]
[[package]]
@ -1121,7 +1118,7 @@ dependencies = [
"ndk-sys 0.6.0+11769913",
"num_enum",
"raw-window-handle",
"thiserror",
"thiserror 1.0.69",
]
[[package]]
@ -1509,23 +1506,24 @@ checksum = "9c6901729fa79e91a0913333229e9ca5dc725089d1c363b2f4b4760709dc4a52"
[[package]]
name = "oxc-miette"
version = "1.0.2"
version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e03e63fd113c068b82d07c9c614b0b146c08a3ac0a4dface3ea1d1a9d14d549e"
checksum = "60a7ba54c704edefead1f44e9ef09c43e5cfae666bdc33516b066011f0e6ebf7"
dependencies = [
"cfg-if",
"owo-colors",
"oxc-miette-derive",
"textwrap",
"thiserror",
"thiserror 2.0.18",
"unicode-segmentation",
"unicode-width 0.2.2",
]
[[package]]
name = "oxc-miette-derive"
version = "1.0.2"
version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e21f680e8c5f1900297d394627d495351b9e37761f7bbf90116bd5eeb6e80967"
checksum = "d4faecb54d0971f948fbc1918df69b26007e6f279a204793669542e1e8b75eb3"
dependencies = [
"proc-macro2",
"quote",
@ -1534,29 +1532,27 @@ dependencies = [
[[package]]
name = "oxc_allocator"
version = "0.48.2"
version = "0.110.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17374a91329f2e362bc8be31cb3e171ef226777d0ea668e17a39620443693027"
checksum = "2174c7c8f77137b1bd1c653d7a5a531ae41f3b8fec1dd0251c801689784e7a2e"
dependencies = [
"allocator-api2",
"bumpalo",
"hashbrown 0.15.5",
"hashbrown 0.16.1",
"oxc_data_structures",
"rustc-hash 2.1.1",
"simdutf8",
]
[[package]]
name = "oxc_ast"
version = "0.48.2"
version = "0.110.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21b38cfe954ee987354af015020f5cb2723df6fed6cd688eff24388437c7eb7e"
checksum = "62f1902f97a5cac8767b76a1d8a1b3124e9db80c176ebbc98f75143dcc124a15"
dependencies = [
"bitflags 2.10.0",
"cow-utils",
"num-bigint",
"num-traits",
"oxc_allocator",
"oxc_ast_macros",
"oxc_data_structures",
"oxc_diagnostics",
"oxc_estree",
"oxc_regular_expression",
"oxc_span",
@ -1565,57 +1561,83 @@ dependencies = [
[[package]]
name = "oxc_ast_macros"
version = "0.48.2"
version = "0.110.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85f9e03eff90b041078edcc8aff09457eb4126fa5d62a383fdb082d3ae286274"
checksum = "c5a31bd55516a98a35b2d99fa5813a3d3a5b798bad3262c819dfe7344bc6f390"
dependencies = [
"phf",
"proc-macro2",
"quote",
"syn 2.0.114",
]
[[package]]
name = "oxc_diagnostics"
version = "0.48.2"
name = "oxc_ast_visit"
version = "0.110.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a24c41929c1910d83fb6f4c508190a8b2d1bad02e81c8cb3a9d3f474ca0ad2c1"
checksum = "e2c520a488c04ba5267223edd0bb245fb7f10e2358e8955802a5d962bb95b50a"
dependencies = [
"cow-utils",
"oxc-miette",
]
[[package]]
name = "oxc_ecmascript"
version = "0.48.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30fba86c97b571671f941b818e6831ba821aac398b9f6f3b4e3367ca264b8324"
dependencies = [
"num-bigint",
"num-traits",
"oxc_allocator",
"oxc_ast",
"oxc_span",
"oxc_syntax",
]
[[package]]
name = "oxc_estree"
version = "0.48.2"
name = "oxc_data_structures"
version = "0.110.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e587034bb5f108dd987e5419a4ad35a173550bd9439fc2b610d34e4ce41e8b23"
checksum = "a42840ce8d83a08a92823dda6189e4d97359feca24a4fa732f3256c4614bb5a4"
[[package]]
name = "oxc_diagnostics"
version = "0.110.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4f7b09c1563a67ede53af131f717b31ba89a992959ebad188b5158c21d4dc0a"
dependencies = [
"cow-utils",
"oxc-miette",
"percent-encoding",
]
[[package]]
name = "oxc_ecmascript"
version = "0.110.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4813b352bd5b0b05badf0c9e6c5ec7ea58a6a7ab49bec8d18ead262624c6ef8d"
dependencies = [
"cow-utils",
"num-bigint",
"num-traits",
"oxc_allocator",
"oxc_ast",
"oxc_regular_expression",
"oxc_span",
"oxc_syntax",
]
[[package]]
name = "oxc_estree"
version = "0.110.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e54fb3effe995e6538d68070bf0a450b5ffd11dd41b62f11a4d01efa1f40e278"
[[package]]
name = "oxc_index"
version = "2.0.0"
version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5eca5d9726cd0a6e433debe003b7bc88b2ecad0bb6109f0cef7c55e692139a34"
checksum = "eb3e6120999627ec9703025eab7c9f410ebb7e95557632a8902ca48210416c2b"
dependencies = [
"nonmax",
"serde",
]
[[package]]
name = "oxc_parser"
version = "0.48.2"
version = "0.110.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8dc385aca3586877f8c918aed1141b885dedcfc1019d6ea5be4105f8e2a7965e"
checksum = "5592bf8b64743944eb46528f9eabdde2b2435c8293cd502f5c183f9dff644e16"
dependencies = [
"assert-unchecked",
"bitflags 2.10.0",
"cow-utils",
"memchr",
@ -1623,6 +1645,7 @@ dependencies = [
"num-traits",
"oxc_allocator",
"oxc_ast",
"oxc_data_structures",
"oxc_diagnostics",
"oxc_ecmascript",
"oxc_regular_expression",
@ -1634,14 +1657,14 @@ dependencies = [
[[package]]
name = "oxc_regular_expression"
version = "0.48.2"
version = "0.110.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8d172402f6d542ab2837d35126cc42ad6989b9c2289b06bc5c8c89dceb60c48"
checksum = "09de7f7e0fb82f54750e3a95346a828fd354b9aeac00f131719008733e66a18d"
dependencies = [
"bitflags 2.10.0",
"oxc_allocator",
"oxc_ast_macros",
"oxc_diagnostics",
"oxc_estree",
"oxc_span",
"phf",
"rustc-hash 2.1.1",
@ -1650,9 +1673,9 @@ dependencies = [
[[package]]
name = "oxc_span"
version = "0.48.2"
version = "0.110.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75881376dfdbb6a23f12a66794904f0d215629f208edcf7e156c0770e89e2101"
checksum = "2a42c0759b745eca0fe776890af46ce12e79e61796995e51a8eb9dcdf5516ab0"
dependencies = [
"compact_str",
"oxc-miette",
@ -1663,22 +1686,21 @@ dependencies = [
[[package]]
name = "oxc_syntax"
version = "0.48.2"
version = "0.110.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6d88037a5de07f66299ab523a65545cc48d550658cea8cadcea09b60596dd49"
checksum = "b63eac2e04a75a10c5714aeb753cdfa06b1abc66bbaa748b7994700f52c9b184"
dependencies = [
"assert-unchecked",
"bitflags 2.10.0",
"cow-utils",
"dragonbox_ecma",
"nonmax",
"oxc_allocator",
"oxc_ast_macros",
"oxc_data_structures",
"oxc_estree",
"oxc_index",
"oxc_span",
"phf",
"rustc-hash 2.1.1",
"ryu-js",
"unicode-id-start",
]
@ -1719,29 +1741,30 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
[[package]]
name = "phf"
version = "0.11.3"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078"
checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf"
dependencies = [
"phf_macros",
"phf_shared",
"serde",
]
[[package]]
name = "phf_generator"
version = "0.11.3"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d"
checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737"
dependencies = [
"fastrand",
"phf_shared",
"rand",
]
[[package]]
name = "phf_macros"
version = "0.11.3"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216"
checksum = "812f032b54b1e759ccd5f8b6677695d5268c588701effba24601f6932f8269ef"
dependencies = [
"phf_generator",
"phf_shared",
@ -1752,9 +1775,9 @@ dependencies = [
[[package]]
name = "phf_shared"
version = "0.11.3"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5"
checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266"
dependencies = [
"siphasher",
]
@ -1794,7 +1817,7 @@ dependencies = [
"bytemuck",
"pollster",
"raw-window-handle",
"thiserror",
"thiserror 1.0.69",
"ultraviolet",
"wgpu",
]
@ -1874,19 +1897,33 @@ checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773"
name = "prometeu"
version = "0.1.0"
dependencies = [
"anyhow",
"clap",
"cpal",
"pixels",
"prometeu-core",
"ringbuf",
"serde_json",
"winit",
"prometeu-compiler",
"prometeu-runtime-desktop",
]
[[package]]
name = "prometeu-bytecode"
version = "0.1.0"
[[package]]
name = "prometeu-compiler"
version = "0.1.0"
dependencies = [
"anyhow",
"clap",
"oxc_allocator",
"oxc_ast",
"oxc_ast_visit",
"oxc_parser",
"oxc_span",
"prometeu-bytecode",
"prometeu-core",
"serde",
"serde_json",
]
[[package]]
name = "prometeu-core"
version = "0.1.0"
@ -1908,22 +1945,6 @@ dependencies = [
"winit",
]
[[package]]
name = "prometeuc"
version = "0.1.0"
dependencies = [
"anyhow",
"clap",
"oxc_allocator",
"oxc_ast",
"oxc_parser",
"oxc_span",
"prometeu-bytecode",
"prometeu-core",
"serde",
"serde_json",
]
[[package]]
name = "quick-xml"
version = "0.38.4"
@ -1948,21 +1969,6 @@ version = "5.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
[[package]]
name = "range-alloc"
version = "0.1.4"
@ -2098,12 +2104,6 @@ version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a50f4cf475b65d88e057964e0e9bb1f0aa9bbb2036dc65c64596b42932536984"
[[package]]
name = "ryu-js"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd29631678d6fb0903b69223673e122c32e9ae559d0960a38d574695ebc0ea15"
[[package]]
name = "safe_arch"
version = "0.7.4"
@ -2202,12 +2202,6 @@ version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "simdutf8"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
[[package]]
name = "siphasher"
version = "1.0.1"
@ -2255,7 +2249,7 @@ dependencies = [
"log",
"memmap2",
"rustix 0.38.44",
"thiserror",
"thiserror 1.0.69",
"wayland-backend",
"wayland-client",
"wayland-csd-frame",
@ -2350,7 +2344,16 @@ version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
dependencies = [
"thiserror-impl",
"thiserror-impl 1.0.69",
]
[[package]]
name = "thiserror"
version = "2.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"
dependencies = [
"thiserror-impl 2.0.18",
]
[[package]]
@ -2364,6 +2367,17 @@ dependencies = [
"syn 2.0.114",
]
[[package]]
name = "thiserror-impl"
version = "2.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
]
[[package]]
name = "tiny-skia"
version = "0.11.4"
@ -2754,7 +2768,7 @@ dependencies = [
"raw-window-handle",
"rustc-hash 1.1.0",
"smallvec",
"thiserror",
"thiserror 1.0.69",
"web-sys",
"wgpu-hal",
"wgpu-types",
@ -2798,7 +2812,7 @@ dependencies = [
"renderdoc-sys",
"rustc-hash 1.1.0",
"smallvec",
"thiserror",
"thiserror 1.0.69",
"wasm-bindgen",
"web-sys",
"wgpu-types",

View File

@ -4,7 +4,7 @@ members = [
"crates/prometeu-runtime-desktop",
"crates/prometeu",
"crates/prometeu-bytecode",
"crates/prometeuc",
"crates/prometeu-compiler",
]
resolver = "2"
@ -15,4 +15,6 @@ repository = "https://github.com/prometeu/runtime"
# The profile that 'dist' will build with
[profile.dist]
inherits = "release"
lto = "thin"
lto = true
codegen-units = 1
strip = "symbols"

View File

@ -34,7 +34,7 @@ This repository is organized as a Rust workspace and contains several components
- **[prometeu-core](./crates/prometeu-core)**: The logical core, VM, and internal OS.
- **[prometeu-runtime-desktop](crates/prometeu-runtime-desktop)**: Host for execution on Desktop systems.
- **[docs/](./docs)**: Technical documentation and system specifications.
- **[devtools-protocol/](./devtools-protocol)**: Definition of the communication protocol for development tools.
- **[devtools-protocol/](devtools)**: Definition of the communication protocol for development tools.
- **[test-cartridges/](./test-cartridges)**: Cartridge examples and test suites.
---

17
build/program.disasm.txt Normal file
View File

@ -0,0 +1,17 @@
00000000 Call U32(18) U32(0)
0000000A FrameSync
0000000C Jmp U32(0)
00000012 PushI32 U32(1) ; test_supported.ts:2
00000018 SetLocal U32(0) ; test_supported.ts:2
0000001E GetLocal U32(0) ; test_supported.ts:3
00000024 PushI32 U32(10) ; test_supported.ts:3
0000002A Lt ; test_supported.ts:3
0000002C JmpIfFalse U32(80) ; test_supported.ts:3
00000032 GetLocal U32(0) ; test_supported.ts:4
00000038 PushI32 U32(1) ; test_supported.ts:4
0000003E Add ; test_supported.ts:4
00000040 Dup ; test_supported.ts:4
00000042 SetLocal U32(0) ; test_supported.ts:4
00000048 Pop ; test_supported.ts:4
0000004A Jmp U32(80)
00000050 Ret

BIN
build/program.pbc Normal file

Binary file not shown.

74
build/symbols.json Normal file
View File

@ -0,0 +1,74 @@
[
{
"pc": 18,
"file": "test_supported.ts",
"line": 2,
"col": 13
},
{
"pc": 24,
"file": "test_supported.ts",
"line": 2,
"col": 9
},
{
"pc": 30,
"file": "test_supported.ts",
"line": 3,
"col": 9
},
{
"pc": 36,
"file": "test_supported.ts",
"line": 3,
"col": 13
},
{
"pc": 42,
"file": "test_supported.ts",
"line": 3,
"col": 9
},
{
"pc": 44,
"file": "test_supported.ts",
"line": 3,
"col": 5
},
{
"pc": 50,
"file": "test_supported.ts",
"line": 4,
"col": 13
},
{
"pc": 56,
"file": "test_supported.ts",
"line": 4,
"col": 17
},
{
"pc": 62,
"file": "test_supported.ts",
"line": 4,
"col": 13
},
{
"pc": 64,
"file": "test_supported.ts",
"line": 4,
"col": 9
},
{
"pc": 66,
"file": "test_supported.ts",
"line": 4,
"col": 9
},
{
"pc": 72,
"file": "test_supported.ts",
"line": 4,
"col": 9
}
]

View File

@ -2,6 +2,8 @@
name = "prometeu-bytecode"
version = "0.1.0"
edition = "2021"
license.workspace = true
repository.workspace = true
[dependencies]
# No dependencies for now

View File

@ -18,6 +18,18 @@ pub enum Asm {
Label(String),
}
pub fn update_pc_by_operand(initial_pc: u32, operands: &Vec<Operand>) -> u32 {
let mut pcp: u32 = initial_pc;
for operand in operands {
match operand {
Operand::U32(_) | Operand::I32(_) | Operand::Label(_) => pcp += 4,
Operand::I64(_) | Operand::F64(_) => pcp += 8,
Operand::Bool(_) => pcp += 1,
}
}
pcp
}
pub fn assemble(instructions: &[Asm]) -> Result<Vec<u8>, String> {
let mut labels = HashMap::new();
let mut current_pc = 0u32;
@ -30,13 +42,7 @@ pub fn assemble(instructions: &[Asm]) -> Result<Vec<u8>, String> {
}
Asm::Op(_opcode, operands) => {
current_pc += 2; // OpCode is u16 (2 bytes)
for operand in operands {
match operand {
Operand::U32(_) | Operand::I32(_) | Operand::Label(_) => current_pc += 4,
Operand::I64(_) | Operand::F64(_) => current_pc += 8,
Operand::Bool(_) => current_pc += 1,
}
}
current_pc = update_pc_by_operand(current_pc, operands);
}
}
}

View File

@ -0,0 +1,27 @@
[package]
name = "prometeu-compiler"
version = "0.1.0"
edition = "2021"
license.workspace = true
repository.workspace = true
[[bin]]
name = "prometeu-compiler"
path = "src/main.rs"
[package.metadata.dist]
dist = true
include = ["../../VERSION.txt"]
[dependencies]
prometeu-bytecode = { path = "../prometeu-bytecode" }
prometeu-core = { path = "../prometeu-core" }
oxc_parser = "0.110.0"
oxc_allocator = "0.110.0"
oxc_ast = "0.110.0"
oxc_ast_visit = "0.110.0"
oxc_span = "0.110.0"
clap = { version = "4.5.54", features = ["derive"] }
serde = { version = "1.0.228", features = ["derive"] }
serde_json = "1.0.149"
anyhow = "1.0.100"

View File

@ -2,7 +2,7 @@ use clap::{Parser, Subcommand};
use std::path::PathBuf;
#[derive(Parser)]
#[command(name = "prometeuc")]
#[command(name = "prometeu-compiler")]
#[command(about = "Prometeu Compiler", long_about = None)]
pub struct Cli {
#[command(subcommand)]
@ -32,4 +32,9 @@ pub enum Commands {
#[arg(long, default_value_t = true)]
emit_symbols: bool,
},
/// Verifies a Prometeu project
Verify {
/// Project directory
project_dir: PathBuf,
},
}

View File

@ -0,0 +1,26 @@
use oxc_ast::ast::*;
use anyhow::{Result, anyhow};
pub fn get_callee_name(expr: &Expression) -> Result<String> {
get_member_expr_name(expr)
}
pub fn get_member_expr_name(expr: &Expression) -> Result<String> {
match expr {
Expression::Identifier(ident) => {
let name = ident.name.to_string();
// Remove prefix 'P' if it's followed by an uppercase letter (e.g., PGfx -> Gfx)
if name.len() > 1 && name.starts_with('P') && name.chars().nth(1).unwrap().is_uppercase() {
Ok(name[1..].to_string())
} else {
Ok(name)
}
}
Expression::StaticMemberExpression(member) => {
let obj = get_member_expr_name(&member.object)?;
let prop = member.property.name.to_string();
Ok(format!("{}.{}", obj, prop))
}
_ => Err(anyhow!("Unsupported expression")),
}
}

View File

@ -0,0 +1,507 @@
use anyhow::{Result, anyhow};
use oxc_ast::ast::*;
use oxc_span::{Span, GetSpan};
use prometeu_bytecode::opcode::OpCode;
use prometeu_bytecode::asm::{Asm, Operand, assemble};
use prometeu_bytecode::pbc::{ConstantPoolEntry, PbcFile, write_pbc};
use crate::compiler::Symbol;
use crate::syscall_map;
use crate::codegen::ast_util;
use prometeu_core::prometeu_os::Syscall;
use std::collections::HashMap;
use prometeu_bytecode::asm;
use prometeu_core::model::Color;
pub struct Codegen {
file_name: String,
source_text: String,
pub symbols: Vec<Symbol>,
instructions: Vec<(Asm, bool)>, // (Asm, has_symbol)
locals: HashMap<String, u32>,
constant_pool: Vec<ConstantPoolEntry>,
next_local: u32,
label_count: u32,
}
impl Codegen {
pub fn new(file_name: String, source_text: String) -> Self {
Self {
file_name,
source_text,
symbols: Vec::new(),
instructions: Vec::new(),
locals: HashMap::new(),
constant_pool: vec![ConstantPoolEntry::Null], // Index 0 is always Null
next_local: 0,
label_count: 0,
}
}
fn add_constant(&mut self, entry: ConstantPoolEntry) -> u32 {
if let Some(pos) = self.constant_pool.iter().position(|e| e == &entry) {
pos as u32
} else {
let pos = self.constant_pool.len();
self.constant_pool.push(entry);
pos as u32
}
}
pub fn compile_program(&mut self, program: &Program) -> Result<Vec<u8>> {
self.compile_programs(vec![(self.file_name.clone(), self.source_text.clone(), program)])
}
pub fn compile_programs(&mut self, programs: Vec<(String, String, &Program)>) -> Result<Vec<u8>> {
// First pass: collect all functions and their indices
let mut all_functions = Vec::new();
for (file, source, program) in &programs {
for item in &program.body {
match item {
Statement::FunctionDeclaration(f) => {
all_functions.push((file.clone(), source.clone(), f.as_ref()));
}
Statement::ExportNamedDeclaration(decl) => {
if let Some(Declaration::FunctionDeclaration(f)) = &decl.declaration {
all_functions.push((file.clone(), source.clone(), f.as_ref()));
}
}
_ => {}
}
}
}
// Find tick function (should be in the first program, which is the entry)
let mut tick_fn_name = None;
if let Some((_, _, entry_program)) = programs.first() {
for item in &entry_program.body {
let f_opt = match item {
Statement::FunctionDeclaration(f) => Some(f.as_ref()),
Statement::ExportNamedDeclaration(decl) => {
if let Some(Declaration::FunctionDeclaration(f)) = &decl.declaration {
Some(f.as_ref())
} else {
None
}
}
_ => None,
};
if let Some(f) = f_opt {
if let Some(ident) = &f.id {
if ident.name == "tick" {
tick_fn_name = Some(ident.name.to_string());
break;
}
}
}
}
}
let tick_fn_name = tick_fn_name.ok_or_else(|| anyhow!("export function tick() not found in entry file"))?;
// Entry point: loop calling tick
self.emit_label("entry".to_string());
self.emit_op(OpCode::Call, vec![Operand::Label(tick_fn_name), Operand::U32(0)], Span::default());
self.emit_op(OpCode::Pop, vec![], Span::default());
self.emit_op(OpCode::FrameSync, vec![], Span::default());
self.emit_op(OpCode::Jmp, vec![Operand::Label("entry".to_string())], Span::default());
// Compile all functions
for (file, source, f) in all_functions {
self.file_name = file;
self.source_text = source;
if let Some(ident) = &f.id {
let name = ident.name.to_string();
self.emit_label(name);
self.compile_function(f)?;
self.emit_op(OpCode::Ret, vec![], Span::default());
}
}
let asm_vec: Vec<Asm> = self.instructions.iter().map(|(a, _)| a.clone()).collect();
let bytecode = assemble(&asm_vec).map_err(|e| anyhow!("Assemble error: {}", e))?;
// Finalize symbols (associate PC)
self.finalize_symbols();
let pbc = PbcFile {
cp: self.constant_pool.clone(),
rom: bytecode,
};
write_pbc(&pbc).map_err(|e| anyhow!("PBC Write error: {}", e))
}
fn compile_function(&mut self, f: &Function) -> Result<()> {
self.locals.clear();
self.next_local = 0;
// Start scope for parameters and local variables
self.emit_op(OpCode::PushScope, vec![], f.span);
// Map parameters to locals
for param in &f.params.items {
if let BindingPattern::BindingIdentifier(ident) = &param.pattern {
let name = ident.name.to_string();
let id = self.next_local;
self.locals.insert(name, id);
self.next_local += 1;
}
}
if let Some(body) = &f.body {
for stmt in &body.statements {
self.compile_stmt(stmt)?;
}
}
// ABI Rule: Every function MUST leave exactly one value on the stack before RET.
// If the function doesn't have a return statement, we push Null.
// For now, we always push Null at the end if it's not a return.
// In a more complex compiler, we would check if all paths return.
self.emit_op(OpCode::PopScope, vec![], Span::default());
self.emit_op(OpCode::PushConst, vec![Operand::U32(0)], Span::default()); // Index 0 is Null in PBC
Ok(())
}
fn compile_stmt(&mut self, stmt: &Statement) -> Result<()> {
match stmt {
Statement::VariableDeclaration(var) => {
for decl in &var.declarations {
if let BindingPattern::BindingIdentifier(ident) = &decl.id {
let name = ident.name.to_string();
if let Some(init) = &decl.init {
self.compile_expr(init)?;
} else {
self.emit_op(OpCode::PushI32, vec![Operand::I32(0)], decl.span);
}
let id = self.next_local;
self.locals.insert(name, id);
self.next_local += 1;
}
}
}
Statement::ExpressionStatement(expr_stmt) => {
self.compile_expr(&expr_stmt.expression)?;
self.emit_op(OpCode::Pop, vec![], expr_stmt.span);
}
Statement::IfStatement(if_stmt) => {
let else_label = self.new_label("else");
let end_label = self.new_label("end_if");
self.compile_expr(&if_stmt.test)?;
self.emit_op(OpCode::JmpIfFalse, vec![Operand::Label(else_label.clone())], if_stmt.span);
self.compile_stmt(&if_stmt.consequent)?;
self.emit_op(OpCode::Jmp, vec![Operand::Label(end_label.clone())], Span::default());
self.emit_label(else_label);
if let Some(alt) = &if_stmt.alternate {
self.compile_stmt(alt)?;
}
self.emit_label(end_label);
}
Statement::BlockStatement(block) => {
self.emit_op(OpCode::PushScope, vec![], block.span);
for stmt in &block.body {
self.compile_stmt(stmt)?;
}
self.emit_op(OpCode::PopScope, vec![], block.span);
}
_ => return Err(anyhow!("Unsupported statement type at {:?}", stmt.span())),
}
Ok(())
}
fn compile_expr(&mut self, expr: &Expression) -> Result<()> {
match expr {
Expression::NumericLiteral(n) => {
let val = n.value;
if val.fract() == 0.0 && val >= i32::MIN as f64 && val <= i32::MAX as f64 {
self.emit_op(OpCode::PushI32, vec![Operand::I32(val as i32)], n.span);
} else {
self.emit_op(OpCode::PushI64, vec![Operand::I64(val as i64)], n.span);
}
}
Expression::BooleanLiteral(b) => {
self.emit_op(OpCode::PushBool, vec![Operand::Bool(b.value)], b.span);
}
Expression::StringLiteral(s) => {
let idx = self.add_constant(ConstantPoolEntry::String(s.value.to_string()));
self.emit_op(OpCode::PushConst, vec![Operand::U32(idx)], s.span);
}
Expression::NullLiteral(n) => {
self.emit_op(OpCode::PushConst, vec![Operand::U32(0)], n.span);
}
Expression::Identifier(ident) => {
let name = ident.name.to_string();
if let Some(&id) = self.locals.get(&name) {
self.emit_op(OpCode::GetLocal, vec![Operand::U32(id)], ident.span);
} else {
return Err(anyhow!("Undefined variable: {} at {:?}", name, ident.span));
}
}
Expression::AssignmentExpression(assign) => {
if let AssignmentTarget::AssignmentTargetIdentifier(ident) = &assign.left {
let name = ident.name.to_string();
self.compile_expr(&assign.right)?;
if let Some(&id) = self.locals.get(&name) {
self.emit_op(OpCode::SetLocal, vec![Operand::U32(id)], assign.span);
self.emit_op(OpCode::GetLocal, vec![Operand::U32(id)], assign.span);
} else {
return Err(anyhow!("Undefined variable: {} at {:?}", name, ident.span));
}
} else {
return Err(anyhow!("Unsupported assignment target at {:?}", assign.span));
}
}
Expression::BinaryExpression(bin) => {
self.compile_expr(&bin.left)?;
self.compile_expr(&bin.right)?;
let op = match bin.operator {
BinaryOperator::Addition => OpCode::Add,
BinaryOperator::Subtraction => OpCode::Sub,
BinaryOperator::Multiplication => OpCode::Mul,
BinaryOperator::Division => OpCode::Div,
BinaryOperator::Equality => OpCode::Eq,
BinaryOperator::Inequality => OpCode::Neq,
BinaryOperator::LessThan => OpCode::Lt,
BinaryOperator::GreaterThan => OpCode::Gt,
BinaryOperator::LessEqualThan => OpCode::Lte,
BinaryOperator::GreaterEqualThan => OpCode::Gte,
_ => return Err(anyhow!("Unsupported binary operator {:?} at {:?}", bin.operator, bin.span)),
};
self.emit_op(op, vec![], bin.span);
}
Expression::LogicalExpression(log) => {
self.compile_expr(&log.left)?;
self.compile_expr(&log.right)?;
let op = match log.operator {
LogicalOperator::And => OpCode::And,
LogicalOperator::Or => OpCode::Or,
_ => return Err(anyhow!("Unsupported logical operator {:?} at {:?}", log.operator, log.span)),
};
self.emit_op(op, vec![], log.span);
}
Expression::UnaryExpression(unary) => {
self.compile_expr(&unary.argument)?;
let op = match unary.operator {
UnaryOperator::UnaryNegation => OpCode::Neg,
UnaryOperator::UnaryPlus => return Ok(()),
UnaryOperator::LogicalNot => OpCode::Not,
_ => return Err(anyhow!("Unsupported unary operator {:?} at {:?}", unary.operator, unary.span)),
};
self.emit_op(op, vec![], unary.span);
}
Expression::CallExpression(call) => {
let name = ast_util::get_callee_name(&call.callee)?;
if let Some(syscall_id) = syscall_map::map_syscall(&name) {
if syscall_id == 0xFFFF_FFFF {
// Color.rgb(r, g, b)
if call.arguments.len() != 3 {
return Err(anyhow!("Color.rgb expects 3 arguments at {:?}", call.span));
}
// We'll emit the bit manipulation logic here or just a special syscall if we had one.
// Since we have bitwise opcodes, let's use them!
// ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3)
// Argument 0: r
if let Some(expr) = call.arguments[0].as_expression() {
self.compile_expr(expr)?;
self.emit_op(OpCode::PushI32, vec![Operand::I32(3)], call.span);
self.emit_op(OpCode::Shr, vec![], call.span);
self.emit_op(OpCode::PushI32, vec![Operand::I32(11)], call.span);
self.emit_op(OpCode::Shl, vec![], call.span);
}
// Argument 1: g
if let Some(expr) = call.arguments[1].as_expression() {
self.compile_expr(expr)?;
self.emit_op(OpCode::PushI32, vec![Operand::I32(2)], call.span);
self.emit_op(OpCode::Shr, vec![], call.span);
self.emit_op(OpCode::PushI32, vec![Operand::I32(5)], call.span);
self.emit_op(OpCode::Shl, vec![], call.span);
}
self.emit_op(OpCode::BitOr, vec![], call.span);
// Argument 2: b
if let Some(expr) = call.arguments[2].as_expression() {
self.compile_expr(expr)?;
self.emit_op(OpCode::PushI32, vec![Operand::I32(3)], call.span);
self.emit_op(OpCode::Shr, vec![], call.span);
}
self.emit_op(OpCode::BitOr, vec![], call.span);
} else {
for arg in &call.arguments {
if let Some(expr) = arg.as_expression() {
self.compile_expr(expr)?;
}
}
self.emit_op(OpCode::Syscall, vec![Operand::U32(syscall_id)], call.span);
}
} else {
// Local function call
for arg in &call.arguments {
if let Some(expr) = arg.as_expression() {
self.compile_expr(expr)?;
}
}
self.emit_op(OpCode::Call, vec![Operand::Label(name), Operand::U32(call.arguments.len() as u32)], call.span);
}
}
Expression::StaticMemberExpression(member) => {
let full_name = ast_util::get_member_expr_name(expr)?;
if full_name.to_lowercase().starts_with("color.") {
match full_name.to_lowercase().as_str() {
"color.black" => self.emit_op(OpCode::PushI32, vec![Operand::I32(Color::BLACK.raw() as i32)], member.span),
"color.white" => self.emit_op(OpCode::PushI32, vec![Operand::I32(Color::WHITE.raw() as i32)], member.span),
"color.red" => self.emit_op(OpCode::PushI32, vec![Operand::I32(Color::RED.raw() as i32)], member.span),
"color.green" => self.emit_op(OpCode::PushI32, vec![Operand::I32(Color::GREEN.raw() as i32)], member.span),
"color.blue" => self.emit_op(OpCode::PushI32, vec![Operand::I32(Color::BLUE.raw() as i32)], member.span),
"color.yellow" => self.emit_op(OpCode::PushI32, vec![Operand::I32(Color::YELLOW.raw() as i32)], member.span),
"color.cyan" => self.emit_op(OpCode::PushI32, vec![Operand::I32(Color::CYAN.raw() as i32)], member.span),
"color.gray" | "color.grey" => self.emit_op(OpCode::PushI32, vec![Operand::I32(Color::GRAY.raw() as i32)], member.span),
"color.orange" => self.emit_op(OpCode::PushI32, vec![Operand::I32(Color::ORANGE.raw() as i32)], member.span),
"color.indigo" => self.emit_op(OpCode::PushI32, vec![Operand::I32(Color::INDIGO.raw() as i32)], member.span),
"color.magenta" => self.emit_op(OpCode::PushI32, vec![Operand::I32(Color::MAGENTA.raw() as i32)], member.span),
"color.colorKey" | "color.color_key" => self.emit_op(OpCode::PushI32, vec![Operand::I32(Color::COLOR_KEY.raw() as i32)], member.span),
_ => return Err(anyhow!("Unsupported color constant: {} at {:?}", full_name, member.span)),
}
} else if full_name.to_lowercase().starts_with("pad.") {
let parts: Vec<&str> = full_name.split('.').collect();
if parts.len() == 3 {
let btn_name = parts[1];
let state_name = parts[2];
let btn_id = self.map_btn_name(btn_name)?;
let syscall_id = match state_name {
"down" => Syscall::InputGetPad as u32,
"pressed" => Syscall::InputGetPadPressed as u32,
"released" => Syscall::InputGetPadReleased as u32,
"holdFrames" => Syscall::InputGetPadHold as u32,
_ => return Err(anyhow!("Unsupported button state: {} at {:?}", state_name, member.span)),
};
self.emit_op(OpCode::PushI32, vec![Operand::I32(btn_id as i32)], member.span);
self.emit_op(OpCode::Syscall, vec![Operand::U32(syscall_id)], member.span);
} else {
return Err(anyhow!("Partial Pad access not supported: {} at {:?}", full_name, member.span));
}
} else if full_name.to_lowercase().starts_with("touch.") {
let parts: Vec<&str> = full_name.split('.').collect();
match parts.len() {
2 => {
let prop = parts[1];
let syscall_id = match prop {
"x" => Syscall::TouchGetX as u32,
"y" => Syscall::TouchGetY as u32,
_ => return Err(anyhow!("Unsupported touch property: {} at {:?}", prop, member.span)),
};
self.emit_op(OpCode::Syscall, vec![Operand::U32(syscall_id)], member.span);
}
3 if parts[1] == "button" => {
let state_name = parts[2];
let syscall_id = match state_name {
"down" => Syscall::TouchIsDown as u32,
"pressed" => Syscall::TouchIsPressed as u32,
"released" => Syscall::TouchIsReleased as u32,
"holdFrames" => Syscall::TouchGetHold as u32,
_ => return Err(anyhow!("Unsupported touch button state: {} at {:?}", state_name, member.span)),
};
self.emit_op(OpCode::Syscall, vec![Operand::U32(syscall_id)], member.span);
}
_ => return Err(anyhow!("Unsupported touch access: {} at {:?}", full_name, member.span)),
}
} else {
return Err(anyhow!("Member expression outside call not supported: {} at {:?}", full_name, member.span));
}
}
_ => return Err(anyhow!("Unsupported expression type at {:?}", expr.span())),
}
Ok(())
}
fn map_btn_name(&self, btn_name: &str) -> Result<u32> {
match btn_name.to_lowercase().as_str() {
"up" => Ok(syscall_map::BTN_UP),
"down" => Ok(syscall_map::BTN_DOWN),
"left" => Ok(syscall_map::BTN_LEFT),
"right" => Ok(syscall_map::BTN_RIGHT),
"a" => Ok(syscall_map::BTN_A),
"b" => Ok(syscall_map::BTN_B),
"x" => Ok(syscall_map::BTN_X),
"y" => Ok(syscall_map::BTN_Y),
"l" => Ok(syscall_map::BTN_L),
"r" => Ok(syscall_map::BTN_R),
"start" => Ok(syscall_map::BTN_START),
"select" => Ok(syscall_map::BTN_SELECT),
_ => Err(anyhow!("Unsupported button: {}", btn_name)),
}
}
fn new_label(&mut self, prefix: &str) -> String {
let label = format!("{}_{}", prefix, self.label_count);
self.label_count += 1;
label
}
fn emit_label(&mut self, name: String) {
self.instructions.push((Asm::Label(name), false));
}
fn emit_op(&mut self, opcode: OpCode, operands: Vec<Operand>, span: Span) {
let has_symbol = if !span.is_unspanned() {
let (line, col) = self.lookup_pos(span.start);
self.symbols.push(Symbol {
pc: 0,
file: self.file_name.clone(),
line,
col,
});
true
} else {
false
};
self.instructions.push((Asm::Op(opcode, operands), has_symbol));
}
fn lookup_pos(&self, pos: u32) -> (usize, usize) {
let mut line = 1;
let mut col = 1;
for (i, c) in self.source_text.char_indices() {
if i as u32 == pos {
break;
}
if c == '\n' {
line += 1;
col = 1;
} else {
col += 1;
}
}
(line, col)
}
fn finalize_symbols(&mut self) {
let mut current_pc = 0u32;
let mut symbol_ptr = 0;
for (instr, has_symbol) in &self.instructions {
match instr {
Asm::Label(_) => {}
Asm::Op(_opcode, operands) => {
if *has_symbol && symbol_ptr < self.symbols.len() {
self.symbols[symbol_ptr].pc = current_pc;
symbol_ptr += 1;
}
current_pc += 2;
current_pc = asm::update_pc_by_operand(current_pc, operands);
}
}
}
}
}

View File

@ -1,3 +1,5 @@
pub mod codegen;
pub mod validator;
pub mod ast_util;
pub use codegen::Codegen;

View File

@ -0,0 +1,163 @@
use oxc_ast::ast::*;
use oxc_ast_visit::{Visit, walk};
use oxc_span::GetSpan;
use anyhow::{Result, anyhow};
use crate::syscall_map;
use crate::codegen::ast_util;
pub struct Validator {
errors: Vec<String>,
local_functions: std::collections::HashSet<String>,
}
impl Validator {
pub fn validate(program: &Program) -> Result<()> {
let mut validator = Self {
errors: Vec::new(),
local_functions: std::collections::HashSet::new(),
};
// 1. Collect all local function names
for item in &program.body {
match item {
Statement::FunctionDeclaration(f) => {
if let Some(ident) = &f.id {
validator.local_functions.insert(ident.name.to_string());
}
}
Statement::ExportNamedDeclaration(decl) => {
if let Some(Declaration::FunctionDeclaration(f)) = &decl.declaration {
if let Some(ident) = &f.id {
validator.local_functions.insert(ident.name.to_string());
}
}
}
Statement::ImportDeclaration(decl) => {
if let Some(specifiers) = &decl.specifiers {
for specifier in specifiers {
match specifier {
ImportDeclarationSpecifier::ImportSpecifier(s) => {
validator.local_functions.insert(s.local.name.to_string());
}
ImportDeclarationSpecifier::ImportDefaultSpecifier(s) => {
validator.local_functions.insert(s.local.name.to_string());
}
ImportDeclarationSpecifier::ImportNamespaceSpecifier(s) => {
validator.local_functions.insert(s.local.name.to_string());
}
}
}
}
}
_ => {}
}
}
// 2. Recursive validation of the AST
validator.visit_program(program);
if validator.errors.is_empty() {
Ok(())
} else {
Err(anyhow!("Validation errors:\n{}", validator.errors.join("\n")))
}
}
}
impl<'a> Visit<'a> for Validator {
fn visit_statement(&mut self, stmt: &Statement<'a>) {
match stmt {
Statement::VariableDeclaration(_) |
Statement::ExpressionStatement(_) |
Statement::IfStatement(_) |
Statement::BlockStatement(_) |
Statement::ExportNamedDeclaration(_) |
Statement::ImportDeclaration(_) |
Statement::FunctionDeclaration(_) => {
// Supported
walk::walk_statement(self, stmt);
}
_ => {
self.errors.push(format!("Unsupported statement type at {:?}", stmt.span()));
}
}
}
fn visit_expression(&mut self, expr: &Expression<'a>) {
match expr {
Expression::NumericLiteral(_) |
Expression::BooleanLiteral(_) |
Expression::StringLiteral(_) |
Expression::NullLiteral(_) |
Expression::Identifier(_) |
Expression::AssignmentExpression(_) |
Expression::BinaryExpression(_) |
Expression::LogicalExpression(_) |
Expression::UnaryExpression(_) |
Expression::CallExpression(_) |
Expression::StaticMemberExpression(_) => {
// Base types supported, detailed checks in specific visit methods if needed
walk::walk_expression(self, expr);
}
_ => {
self.errors.push(format!("Unsupported expression type at {:?}", expr.span()));
}
}
}
fn visit_unary_expression(&mut self, expr: &UnaryExpression<'a>) {
match expr.operator {
UnaryOperator::UnaryNegation |
UnaryOperator::UnaryPlus |
UnaryOperator::LogicalNot => {
walk::walk_unary_expression(self, expr);
}
_ => {
self.errors.push(format!("Unsupported unary operator {:?} at {:?}", expr.operator, expr.span));
}
}
}
fn visit_binary_expression(&mut self, expr: &BinaryExpression<'a>) {
match expr.operator {
BinaryOperator::Addition |
BinaryOperator::Subtraction |
BinaryOperator::Multiplication |
BinaryOperator::Division |
BinaryOperator::Equality |
BinaryOperator::Inequality |
BinaryOperator::LessThan |
BinaryOperator::GreaterThan |
BinaryOperator::LessEqualThan |
BinaryOperator::GreaterEqualThan => {
walk::walk_binary_expression(self, expr);
}
_ => {
self.errors.push(format!("Unsupported binary operator {:?} at {:?}", expr.operator, expr.span));
}
}
}
fn visit_call_expression(&mut self, expr: &CallExpression<'a>) {
if let Ok(name) = ast_util::get_callee_name(&expr.callee) {
if syscall_map::map_syscall(&name).is_none() && !self.local_functions.contains(&name) {
self.errors.push(format!("Unsupported function call: {} at {:?}", name, expr.span));
}
} else {
self.errors.push(format!("Unsupported callee expression at {:?}", expr.callee.span()));
}
walk::walk_call_expression(self, expr);
}
fn visit_logical_expression(&mut self, expr: &LogicalExpression<'a>) {
match expr.operator {
LogicalOperator::And |
LogicalOperator::Or => {
walk::walk_logical_expression(self, expr);
}
_ => {
self.errors.push(format!("Unsupported logical operator {:?} at {:?}", expr.operator, expr.span));
}
}
}
}

View File

@ -0,0 +1,154 @@
use std::path::{Path, PathBuf};
use anyhow::{Result, Context, anyhow};
use oxc_allocator::Allocator;
use oxc_parser::Parser;
use oxc_span::SourceType;
use oxc_ast::ast::*;
use crate::codegen::Codegen;
use crate::codegen::validator::Validator;
use std::fs;
use std::collections::{HashMap, VecDeque};
use prometeu_bytecode::disasm::disasm;
use serde::Serialize;
#[derive(Serialize)]
pub struct Symbol {
pub pc: u32,
pub file: String,
pub line: usize,
pub col: usize,
}
pub struct CompilationUnit {
pub rom: Vec<u8>,
pub symbols: Vec<Symbol>,
}
impl CompilationUnit {
pub fn export(&self, out: &Path, emit_disasm: bool, emit_symbols: bool) -> Result<()> {
fs::write(out, &self.rom).with_context(|| format!("Failed to write PBC to {:?}", out))?;
if emit_symbols {
let symbols_path = out.with_file_name("symbols.json");
let symbols_json = serde_json::to_string_pretty(&self.symbols)?;
fs::write(&symbols_path, symbols_json)?;
}
if emit_disasm {
let disasm_path = out.with_extension("disasm.txt");
// Try to parse as PBC, if fails use raw
let rom_to_disasm = if let Ok(pbc) = prometeu_bytecode::pbc::parse_pbc(&self.rom) {
pbc.rom
} else {
self.rom.clone()
};
let instructions = disasm(&rom_to_disasm).map_err(|e| anyhow::anyhow!("Disassembly failed: {}", e))?;
let mut disasm_text = String::new();
for instr in instructions {
let symbol = self.symbols.iter().find(|s| s.pc == instr.pc);
let comment = if let Some(s) = symbol {
format!(" ; {}:{}", s.file, s.line)
} else {
"".to_string()
};
let operands_str = instr.operands.iter()
.map(|o| format!("{:?}", o))
.collect::<Vec<_>>()
.join(" ");
disasm_text.push_str(&format!("{:08X} {:?} {}{}\n", instr.pc, instr.opcode, operands_str, comment));
}
fs::write(disasm_path, disasm_text)?;
}
Ok(())
}
}
fn resolve_import(base_path: &Path, import_str: &str) -> Result<PathBuf> {
let mut path = base_path.parent().unwrap().join(import_str);
if !path.exists() {
if path.with_extension("ts").exists() {
path.set_extension("ts");
} else if path.with_extension("js").exists() {
path.set_extension("js");
}
}
if !path.exists() {
return Err(anyhow!("Cannot resolve import '{}' from {:?}", import_str, base_path));
}
Ok(path.canonicalize()?)
}
pub fn compile(entry: &Path) -> Result<CompilationUnit> {
let allocator = Allocator::default();
let mut modules = HashMap::new();
let mut queue = VecDeque::new();
let entry_abs = entry.canonicalize()
.with_context(|| format!("Failed to canonicalize entry path: {:?}", entry))?;
queue.push_back(entry_abs.clone());
while let Some(path) = queue.pop_front() {
let path_str = path.to_string_lossy().to_string();
if modules.contains_key(&path_str) {
continue;
}
let source_text = fs::read_to_string(&path)
.with_context(|| format!("Failed to read file: {:?}", path))?;
// Allocate source_text in the allocator to keep it alive
let source_text_ptr: &str = allocator.alloc_str(&source_text);
let source_type = SourceType::from_path(&path).unwrap_or_default();
let parser_ret = Parser::new(&allocator, source_text_ptr, source_type).parse();
if !parser_ret.errors.is_empty() {
for error in parser_ret.errors {
eprintln!("{:?}", error);
}
return Err(anyhow!("Failed to parse module: {:?}", path));
}
// Validate individual module
Validator::validate(&parser_ret.program)?;
// Find imports to add to queue
for item in &parser_ret.program.body {
if let Statement::ImportDeclaration(decl) = item {
let import_path = decl.source.value.as_str();
let resolved = resolve_import(&path, import_path)?;
queue.push_back(resolved);
}
}
modules.insert(path_str, (source_text_ptr, parser_ret.program));
}
let entry_str = entry_abs.to_string_lossy().to_string();
let mut program_list = Vec::new();
// Add entry program first
let entry_data = modules.get(&entry_str).ok_or_else(|| anyhow!("Entry module not found after loading"))?;
program_list.push((entry_str.clone(), entry_data.0.to_string(), &entry_data.1));
// Add all other programs
for (path, (source, program)) in &modules {
if path != &entry_str {
program_list.push((path.clone(), source.to_string(), program));
}
}
let mut codegen = Codegen::new(entry_str.clone(), entry_data.0.to_string());
let rom = codegen.compile_programs(program_list)?;
Ok(CompilationUnit {
rom,
symbols: codegen.symbols,
})
}

View File

@ -1,12 +1,12 @@
use clap::Parser;
use anyhow::Result;
pub mod cli;
pub mod codegen;
pub mod compiler;
pub mod syscall_map;
fn main() -> Result<()> {
use clap::Parser;
use anyhow::Result;
pub fn run() -> Result<()> {
let cli = cli::Cli::parse();
match cli.command {
@ -29,7 +29,16 @@ fn main() -> Result<()> {
println!("Entry: {:?}", entry);
println!("Output: {:?}", out);
compiler::compile(&entry, &out, emit_disasm, emit_symbols)?;
let compilation_unit = compiler::compile(&entry)?;
compilation_unit.export(&out, emit_disasm, emit_symbols)?;
}
cli::Commands::Verify { project_dir } => {
let entry = project_dir.join("src/main.ts");
println!("Verifying project at {:?}", project_dir);
println!("Entry: {:?}", entry);
compiler::compile(&entry)?;
println!("Project is valid!");
}
}

View File

@ -0,0 +1,5 @@
use anyhow::Result;
fn main() -> Result<()> {
prometeu_compiler::run()
}

View File

@ -21,7 +21,7 @@ pub fn map_syscall(name: &str) -> Option<u32> {
// Fallback para nomes especiais do compilador
match name {
"input.btnA" | "input.btnB" => Some(Syscall::InputGetPad as u32),
"Color.rgb" | "color.rgb" => Some(0xFFFF_FFFF), // ID especial para Color.rgb (não é um syscall real)
_ => None,
}
}

View File

@ -5,6 +5,6 @@ edition = "2024"
license.workspace = true
[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
serde = { version = "1.0.228", features = ["derive"] }
serde_json = "1.0.149"
prometeu-bytecode = { path = "../prometeu-bytecode" }

View File

@ -133,6 +133,8 @@ impl Gfx {
color: Color,
mode: BlendMode,
) {
if color == Color::COLOR_KEY { return; }
let fw = self.w as i32;
let fh = self.h as i32;
@ -160,6 +162,7 @@ impl Gfx {
/// Draws a single pixel.
pub fn draw_pixel(&mut self, x: i32, y: i32, color: Color) {
if color == Color::COLOR_KEY { return; }
if x >= 0 && x < self.w as i32 && y >= 0 && y < self.h as i32 {
self.back[y as usize * self.w + x as usize] = color.0;
}
@ -167,6 +170,8 @@ impl Gfx {
/// Draws a line between two points using Bresenham's algorithm.
pub fn draw_line(&mut self, x0: i32, y0: i32, x1: i32, y1: i32, color: Color) {
if color == Color::COLOR_KEY { return; }
let dx = (x1 - x0).abs();
let sx = if x0 < x1 { 1 } else { -1 };
let dy = -(y1 - y0).abs();
@ -193,6 +198,8 @@ impl Gfx {
/// Draws a circle outline using Midpoint Circle Algorithm.
pub fn draw_circle(&mut self, xc: i32, yc: i32, r: i32, color: Color) {
if color == Color::COLOR_KEY { return; }
if r < 0 { return; }
let mut x = 0;
let mut y = r;
@ -223,6 +230,8 @@ impl Gfx {
/// Draws a filled circle.
pub fn fill_circle(&mut self, xc: i32, yc: i32, r: i32, color: Color) {
if color == Color::COLOR_KEY { return; }
if r < 0 { return; }
let mut x = 0;
let mut y = r;
@ -255,6 +264,8 @@ impl Gfx {
/// Draws a rectangle outline.
pub fn draw_rect(&mut self, x: i32, y: i32, w: i32, h: i32, color: Color) {
if color == Color::COLOR_KEY { return; }
if w <= 0 || h <= 0 { return; }
self.draw_horizontal_line(x, x + w - 1, y, color);
self.draw_horizontal_line(x, x + w - 1, y + h - 1, color);
@ -269,6 +280,8 @@ impl Gfx {
}
fn draw_horizontal_line(&mut self, x0: i32, x1: i32, y: i32, color: Color) {
if color == Color::COLOR_KEY { return; }
if y < 0 || y >= self.h as i32 { return; }
let start = x0.max(0);
let end = x1.min(self.w as i32 - 1);
@ -279,6 +292,8 @@ impl Gfx {
}
fn draw_vertical_line(&mut self, x: i32, y0: i32, y1: i32, color: Color) {
if color == Color::COLOR_KEY { return; }
if x < 0 || x >= self.w as i32 { return; }
let start = y0.max(0);
let end = y1.min(self.h as i32 - 1);

View File

@ -60,4 +60,14 @@ impl Color {
pub const fn raw(self) -> u16 {
self.0
}
pub const fn hex(self) -> i32 {
let (r5, g6, b5) = Self::unpack_to_native(self.0);
let r8 = ((r5 as u32) << 3) | ((r5 as u32) >> 2);
let g8 = ((g6 as u32) << 2) | ((g6 as u32) >> 4);
let b8 = ((b5 as u32) << 3) | ((b5 as u32) >> 2);
let hex = r8 << 16 | g8 << 8 | b8;
hex as i32
}
}

View File

@ -325,26 +325,31 @@ impl PrometeuOS {
Ok(100)
}
pub fn get_color(&self, index: usize, hw: &mut dyn HardwareBridge) -> Color {
if let Some(bank) = hw.gfx().banks[0].as_ref() {
bank.palettes[0][index % 16]
} else {
match index % 16 {
0 => Color::BLACK,
1 => Color::WHITE,
2 => Color::RED,
3 => Color::GREEN,
4 => Color::BLUE,
5 => Color::YELLOW,
6 => Color::CYAN,
7 => Color::INDIGO,
8 => Color::GRAY,
_ => Color::BLACK,
}
}
pub fn get_color(&self, value: i64) -> Color {
// Agora usamos o valor diretamente como RGB565.
Color::from_raw(value as u16)
}
// Helper para syscalls
pub fn get_button<'a>(&self, id: u32, hw: &'a dyn HardwareBridge) -> Option<&'a crate::model::Button> {
let pad = hw.pad();
match id {
0 => Some(&pad.up),
1 => Some(&pad.down),
2 => Some(&pad.left),
3 => Some(&pad.right),
4 => Some(&pad.a),
5 => Some(&pad.b),
6 => Some(&pad.x),
7 => Some(&pad.y),
8 => Some(&pad.l),
9 => Some(&pad.r),
10 => Some(&pad.start),
11 => Some(&pad.select),
_ => None,
}
}
pub fn is_button_down(&self, id: u32, hw: &mut dyn HardwareBridge) -> bool {
match id {
0 => hw.pad().up.down,
@ -464,6 +469,17 @@ mod tests {
assert!(cycles_after_tick_2 > cycles_after_tick_1, "VM should have consumed more cycles because FrameSync reset the budget");
}
#[test]
fn test_get_color_logic() {
let os = PrometeuOS::new(None);
// Deve retornar a cor raw diretamente
assert_eq!(os.get_color(0x07E0), Color::GREEN);
assert_eq!(os.get_color(0xF800), Color::RED);
assert_eq!(os.get_color(0x001F), Color::BLUE);
assert_eq!(os.get_color(3), Color::from_raw(3));
}
#[test]
fn test_syscall_log_write_and_rate_limit() {
let mut os = PrometeuOS::new(None);
@ -575,70 +591,70 @@ impl NativeInterface for PrometeuOS {
// gfx.clear(color_index) -> null
Syscall::GfxClear => {
let color_idx = vm.pop_integer()? as usize;
let color = self.get_color(color_idx, hw);
let color_val = vm.pop_integer()?;
let color = self.get_color(color_val);
hw.gfx_mut().clear(color);
vm.push(Value::Null);
Ok(100)
}
// gfx.draw_rect(x, y, w, h, color_index) -> null
Syscall::GfxFillRect => {
let color_idx = vm.pop_integer()? as usize;
let color_val = vm.pop_integer()?;
let h = vm.pop_integer()? as i32;
let w = vm.pop_integer()? as i32;
let y = vm.pop_integer()? as i32;
let x = vm.pop_integer()? as i32;
let color = self.get_color(color_idx, hw);
let color = self.get_color(color_val);
hw.gfx_mut().fill_rect(x, y, w, h, color);
vm.push(Value::Null);
Ok(200)
}
// gfx.draw_line(x1, y1, x2, y2, color_index) -> null
Syscall::GfxDrawLine => {
let color_idx = vm.pop_integer()? as usize;
let color_val = vm.pop_integer()?;
let y2 = vm.pop_integer()? as i32;
let x2 = vm.pop_integer()? as i32;
let y1 = vm.pop_integer()? as i32;
let x1 = vm.pop_integer()? as i32;
let color = self.get_color(color_idx, hw);
let color = self.get_color(color_val);
hw.gfx_mut().draw_line(x1, y1, x2, y2, color);
vm.push(Value::Null);
Ok(200)
}
// gfx.draw_circle(x, y, r, color_index) -> null
Syscall::GfxDrawCircle => {
let color_idx = vm.pop_integer()? as usize;
let color_val = vm.pop_integer()?;
let r = vm.pop_integer()? as i32;
let y = vm.pop_integer()? as i32;
let x = vm.pop_integer()? as i32;
let color = self.get_color(color_idx, hw);
let color = self.get_color(color_val);
hw.gfx_mut().draw_circle(x, y, r, color);
vm.push(Value::Null);
Ok(200)
}
// gfx.draw_disc(x, y, r, border_color_idx, fill_color_idx) -> null
Syscall::GfxDrawDisc => {
let fill_color_idx = vm.pop_integer()? as usize;
let border_color_idx = vm.pop_integer()? as usize;
let fill_color_val = vm.pop_integer()?;
let border_color_val = vm.pop_integer()?;
let r = vm.pop_integer()? as i32;
let y = vm.pop_integer()? as i32;
let x = vm.pop_integer()? as i32;
let fill_color = self.get_color(fill_color_idx, hw);
let border_color = self.get_color(border_color_idx, hw);
let fill_color = self.get_color(fill_color_val);
let border_color = self.get_color(border_color_val);
hw.gfx_mut().draw_disc(x, y, r, border_color, fill_color);
vm.push(Value::Null);
Ok(300)
}
// gfx.draw_square(x, y, w, h, border_color_idx, fill_color_idx) -> null
Syscall::GfxDrawSquare => {
let fill_color_idx = vm.pop_integer()? as usize;
let border_color_idx = vm.pop_integer()? as usize;
let fill_color_val = vm.pop_integer()?;
let border_color_val = vm.pop_integer()?;
let h = vm.pop_integer()? as i32;
let w = vm.pop_integer()? as i32;
let y = vm.pop_integer()? as i32;
let x = vm.pop_integer()? as i32;
let fill_color = self.get_color(fill_color_idx, hw);
let border_color = self.get_color(border_color_idx, hw);
let fill_color = self.get_color(fill_color_val);
let border_color = self.get_color(border_color_val);
hw.gfx_mut().draw_square(x, y, w, h, border_color, fill_color);
vm.push(Value::Null);
Ok(200)
@ -653,6 +669,49 @@ impl NativeInterface for PrometeuOS {
vm.push(Value::Boolean(is_down));
Ok(50)
}
Syscall::InputGetPadPressed => {
let button_id = vm.pop_integer()? as u32;
let val = self.get_button(button_id, hw).map(|b| b.pressed).unwrap_or(false);
vm.push(Value::Boolean(val));
Ok(50)
}
Syscall::InputGetPadReleased => {
let button_id = vm.pop_integer()? as u32;
let val = self.get_button(button_id, hw).map(|b| b.released).unwrap_or(false);
vm.push(Value::Boolean(val));
Ok(50)
}
Syscall::InputGetPadHold => {
let button_id = vm.pop_integer()? as u32;
let val = self.get_button(button_id, hw).map(|b| b.hold_frames).unwrap_or(0);
vm.push(Value::Int32(val as i32));
Ok(50)
}
Syscall::TouchGetX => {
vm.push(Value::Int32(hw.touch().x));
Ok(50)
}
Syscall::TouchGetY => {
vm.push(Value::Int32(hw.touch().y));
Ok(50)
}
Syscall::TouchIsDown => {
vm.push(Value::Boolean(hw.touch().f.down));
Ok(50)
}
Syscall::TouchIsPressed => {
vm.push(Value::Boolean(hw.touch().f.pressed));
Ok(50)
}
Syscall::TouchIsReleased => {
vm.push(Value::Boolean(hw.touch().f.released));
Ok(50)
}
Syscall::TouchGetHold => {
vm.push(Value::Int32(hw.touch().f.hold_frames as i32));
Ok(50)
}
// --- Audio Syscalls ---

View File

@ -15,6 +15,16 @@ pub enum Syscall {
// Input
InputGetPad = 0x2001,
InputGetPadPressed = 0x2002,
InputGetPadReleased = 0x2003,
InputGetPadHold = 0x2004,
TouchGetX = 0x2101,
TouchGetY = 0x2102,
TouchIsDown = 0x2103,
TouchIsPressed = 0x2104,
TouchIsReleased = 0x2105,
TouchGetHold = 0x2106,
// Audio
AudioPlaySample = 0x3001,
@ -45,6 +55,15 @@ impl Syscall {
0x1005 => Some(Self::GfxDrawDisc),
0x1006 => Some(Self::GfxDrawSquare),
0x2001 => Some(Self::InputGetPad),
0x2002 => Some(Self::InputGetPadPressed),
0x2003 => Some(Self::InputGetPadReleased),
0x2004 => Some(Self::InputGetPadHold),
0x2101 => Some(Self::TouchGetX),
0x2102 => Some(Self::TouchGetY),
0x2103 => Some(Self::TouchIsDown),
0x2104 => Some(Self::TouchIsPressed),
0x2105 => Some(Self::TouchIsReleased),
0x2106 => Some(Self::TouchGetHold),
0x3001 => Some(Self::AudioPlaySample),
0x4001 => Some(Self::FsOpen),
0x4002 => Some(Self::FsRead),
@ -59,52 +78,71 @@ impl Syscall {
}
}
pub fn as_str(&self) -> &'static str {
match self {
Self::SystemHasCart => "system.has_cart",
Self::SystemRunCart => "system.run_cart",
Self::GfxClear => "gfx.clear",
Self::GfxFillRect => "gfx.fillRect",
Self::GfxDrawLine => "gfx.drawLine",
Self::GfxDrawCircle => "gfx.drawCircle",
Self::GfxDrawDisc => "gfx.drawDisc",
Self::GfxDrawSquare => "gfx.drawSquare",
Self::InputGetPad => "input.get_pad",
Self::AudioPlaySample => "audio.playSample",
Self::FsOpen => "fs.open",
Self::FsRead => "fs.read",
Self::FsWrite => "fs.write",
Self::FsClose => "fs.close",
Self::FsListDir => "fs.listDir",
Self::FsExists => "fs.exists",
Self::FsDelete => "fs.delete",
Self::LogWrite => "log.write",
Self::LogWriteTag => "log.writeTag",
}
}
// pub fn as_str(&self) -> &'static str {
// match self {
// Self::SystemHasCart => "system.has_cart",
// Self::SystemRunCart => "system.run_cart",
// Self::GfxClear => "gfx.clear",
// Self::GfxFillRect => "gfx.fillRect",
// Self::GfxDrawLine => "gfx.drawLine",
// Self::GfxDrawCircle => "gfx.drawCircle",
// Self::GfxDrawDisc => "gfx.drawDisc",
// Self::GfxDrawSquare => "gfx.drawSquare",
// Self::InputGetPad => "input.get_pad",
// Self::InputGetPadPressed => "input.get_pad_pressed",
// Self::InputGetPadReleased => "input.get_pad_released",
// Self::InputGetPadHold => "input.get_pad_hold",
// Self::TouchGetX => "touch.getX",
// Self::TouchGetY => "touch.getY",
// Self::TouchIsDown => "touch.isDown",
// Self::TouchIsPressed => "touch.isPressed",
// Self::TouchIsReleased => "touch.isReleased",
// Self::TouchGetHold => "touch.getHold",
// Self::AudioPlaySample => "audio.playSample",
// Self::FsOpen => "fs.open",
// Self::FsRead => "fs.read",
// Self::FsWrite => "fs.write",
// Self::FsClose => "fs.close",
// Self::FsListDir => "fs.listDir",
// Self::FsExists => "fs.exists",
// Self::FsDelete => "fs.delete",
// Self::LogWrite => "log.write",
// Self::LogWriteTag => "log.writeTag",
// }
// }
pub fn from_name(name: &str) -> Option<Self> {
match name {
"system.has_cart" => Some(Self::SystemHasCart),
"system.run_cart" => Some(Self::SystemRunCart),
"system.hasCart" | "system.has_cart" => Some(Self::SystemHasCart),
"gfx.clear" => Some(Self::GfxClear),
"gfx.fillRect" | "gfx.draw_rect" => Some(Self::GfxFillRect),
"gfx.drawLine" | "gfx.draw_line" => Some(Self::GfxDrawLine),
"gfx.drawCircle" | "gfx.draw_circle" => Some(Self::GfxDrawCircle),
"gfx.drawDisc" | "gfx.draw_disc" => Some(Self::GfxDrawDisc),
"gfx.drawSquare" | "gfx.draw_square" => Some(Self::GfxDrawSquare),
"input.get_pad" => Some(Self::InputGetPad),
"input.getPad" => Some(Self::InputGetPad),
"input.getPadPressed" | "input.get_pad_pressed" => Some(Self::InputGetPadPressed),
"input.getPadReleased" | "input.get_pad_released" => Some(Self::InputGetPadReleased),
"input.getPadHold" | "input.get_pad_hold" => Some(Self::InputGetPadHold),
"touch.getX" | "touch.get_x" => Some(Self::TouchGetX),
"touch.getY" | "touch.get_y" => Some(Self::TouchGetY),
"touch.isDown" | "touch.is_down" => Some(Self::TouchIsDown),
"touch.isPressed" | "touch.is_pressed" => Some(Self::TouchIsPressed),
"touch.isReleased" | "touch.is_released" => Some(Self::TouchIsReleased),
"touch.getHold" | "touch.get_hold" => Some(Self::TouchGetHold),
"audio.playSample" | "audio.play_sample" => Some(Self::AudioPlaySample),
"fs.open" => Some(Self::FsOpen),
"fs.read" => Some(Self::FsRead),
"fs.write" => Some(Self::FsWrite),
"fs.close" => Some(Self::FsClose),
"fs.listDir" => Some(Self::FsListDir),
"fs.listDir" | "fs.list_dir" => Some(Self::FsListDir),
"fs.exists" => Some(Self::FsExists),
"fs.delete" => Some(Self::FsDelete),
"log.write" => Some(Self::LogWrite),
"log.writeTag" => Some(Self::LogWriteTag),
_ => None,
"log.writeTag" | "log.write_tag" => Some(Self::LogWriteTag),
_ => {
None
}
}
}
}

View File

@ -19,4 +19,4 @@ winit = "0.30.12"
pixels = "0.15.0"
cpal = "0.15.3"
ringbuf = "0.4.7"
serde_json = "1.0"
serde_json = "1.0.149"

View File

@ -0,0 +1,84 @@
pub mod audio;
pub mod runner;
pub mod fs_backend;
pub mod log_sink;
pub mod debugger;
pub mod stats;
pub mod input;
pub mod cap;
pub mod utilities;
use runner::HostRunner;
use cap::load_cap_config;
use winit::event_loop::EventLoop;
use prometeu_core::firmware::BootTarget;
pub fn run() -> Result<(), Box<dyn std::error::Error>> {
let args: Vec<String> = std::env::args().collect();
let mut fs_root = None;
let mut cap_config = None;
let mut cartridge_path = None;
let mut debug_mode = false;
let mut debug_port = 7777;
let mut i = 1; // Skip the executable name
while i < args.len() {
match args[i].as_str() {
"--run" => {
if i + 1 < args.len() {
cartridge_path = Some(args[i + 1].clone());
debug_mode = false;
i += 1;
}
}
"--debug" => {
if i + 1 < args.len() {
cartridge_path = Some(args[i + 1].clone());
debug_mode = true;
i += 1;
}
}
"--port" => {
if i + 1 < args.len() {
if let Ok(port) = args[i + 1].parse::<u16>() {
debug_port = port;
}
i += 1;
}
}
"--fs-root" => {
if i + 1 < args.len() {
fs_root = Some(args[i + 1].clone());
i += 1;
}
}
"--cap" => {
if i + 1 < args.len() {
cap_config = load_cap_config(&args[i + 1]);
i += 1;
}
}
_ => {}
}
i += 1;
}
let boot_target = if let Some(path) = cartridge_path {
BootTarget::Cartridge {
path,
debug: debug_mode,
debug_port: if debug_mode { debug_port } else { 7777 },
}
} else {
BootTarget::Hub
};
let event_loop = EventLoop::new()?;
let mut runner = HostRunner::new(fs_root, cap_config);
runner.set_boot_target(boot_target);
event_loop.run_app(&mut runner)?;
Ok(())
}

View File

@ -1,84 +1,3 @@
mod audio;
mod runner;
mod fs_backend;
mod log_sink;
mod debugger;
mod stats;
mod input;
mod cap;
mod utilities;
use crate::runner::HostRunner;
use crate::cap::load_cap_config;
use winit::event_loop::EventLoop;
use prometeu_core::firmware::BootTarget;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let args: Vec<String> = std::env::args().collect();
let mut fs_root = None;
let mut cap_config = None;
let mut cartridge_path = None;
let mut debug_mode = false;
let mut debug_port = 7777;
let mut i = 1; // Skip the executable name
while i < args.len() {
match args[i].as_str() {
"--run" => {
if i + 1 < args.len() {
cartridge_path = Some(args[i + 1].clone());
debug_mode = false;
i += 1;
}
}
"--debug" => {
if i + 1 < args.len() {
cartridge_path = Some(args[i + 1].clone());
debug_mode = true;
i += 1;
}
}
"--port" => {
if i + 1 < args.len() {
if let Ok(port) = args[i + 1].parse::<u16>() {
debug_port = port;
}
i += 1;
}
}
"--fs-root" => {
if i + 1 < args.len() {
fs_root = Some(args[i + 1].clone());
i += 1;
}
}
"--cap" => {
if i + 1 < args.len() {
cap_config = load_cap_config(&args[i + 1]);
i += 1;
}
}
_ => {}
}
i += 1;
}
let boot_target = if let Some(path) = cartridge_path {
BootTarget::Cartridge {
path,
debug: debug_mode,
debug_port: if debug_mode { debug_port } else { 7777 },
}
} else {
BootTarget::Hub
};
let event_loop = EventLoop::new()?;
let mut runner = HostRunner::new(fs_root, cap_config);
runner.set_boot_target(boot_target);
event_loop.run_app(&mut runner)?;
Ok(())
prometeu_runtime_desktop::run()
}

View File

@ -11,29 +11,22 @@ path = "src/main.rs"
[[bin]]
name = "prometeu-runtime"
path = "../prometeu-runtime-desktop/src/main.rs"
path = "src/bin/prometeu-runtime.rs"
# Future binaries (commented)
# [[bin]]
# name = "prometeuc"
# path = "../prometeuc/src/main.rs"
#
# [[bin]]
# name = "prometeup"
# path = "../prometeup/src/main.rs"
[[bin]]
name = "prometeuc"
path = "src/bin/prometeuc.rs"
[package.metadata.dist]
dist = true
include = [
"../../VERSION.txt",
"../../dist-staging/devtools-protocol"
"../../dist-staging/devtools/debugger-protocol",
"../../dist-staging/devtools/typescript-sdk"
]
[dependencies]
clap = { version = "4.5", features = ["derive"] }
prometeu-core = { path = "../prometeu-core" }
winit = "0.30.12"
pixels = "0.15.0"
cpal = "0.15.3"
ringbuf = "0.4.7"
serde_json = "1.0"
prometeu-runtime-desktop = { path = "../prometeu-runtime-desktop" }
prometeu-compiler = { path = "../prometeu-compiler" }
anyhow = "1.0.100"

View File

@ -6,8 +6,10 @@ The `prometeu` binary acts as the unified front-end for the ecosystem. It does n
- `prometeu run <cart>`: Runs a cartridge using the available runtime.
- `prometeu debug <cart> [--port <p>]`: Starts execution in debug mode.
- `prometeu build <projectDir>`: (Planned) Calls the `prometeuc` compiler.
- `prometeu build <projectDir>`: Calls the `prometeuc` compiler.
- `prometeu verify c <projectDir>`: Calls the `prometeuc` compiler.
- `prometeu pack <cartDir>`: (Planned) Calls the `prometeup` packager.
- `prometeu verify p <cartDir>`: (Planned) Calls the `prometeup` packager.
## How it works

View File

@ -0,0 +1 @@
fn main() -> Result<(), Box<dyn std::error::Error>> { prometeu_runtime_desktop::run() }

View File

@ -0,0 +1 @@
fn main() -> anyhow::Result<()> { prometeu_compiler::run() }

View File

@ -8,7 +8,7 @@ use std::process::Command;
/// The main entry point for the user. This binary does not implement
/// compilation or execution logic itself; instead, it acts as a smart
/// front-end that locates and dispatches commands to specialized
/// components like `prometeu-runtime-desktop` or `prometeuc`.
/// components like `prometeu-runtime-desktop` or `prometeu-compiler`.
#[derive(Parser)]
#[command(name = "prometeu")]
#[command(about = "Dispatcher for the Prometeu ecosystem", long_about = None)]
@ -86,14 +86,16 @@ fn main() {
&["--debug", &cart, "--port", &port.to_string()],
);
}
Some(Commands::Build { .. }) => {
not_implemented("build", "prometeuc");
Some(Commands::Build { project_dir }) => {
dispatch(&exe_dir, "prometeuc", &["build", &project_dir]);
}
Some(Commands::Pack { .. }) => {
not_implemented("pack", "prometeup");
}
Some(Commands::Verify { target }) => match target {
VerifyCommands::C { .. } => not_implemented("verify c", "prometeuc"),
VerifyCommands::C { project_dir } => {
dispatch(&exe_dir, "prometeuc", &["verify", &project_dir]);
}
VerifyCommands::P { .. } => not_implemented("verify p", "prometeup"),
},
None => {
@ -119,7 +121,7 @@ fn dispatch(exe_dir: &Path, bin_name: &str, args: &[&str]) {
eprintln!(
"prometeu: command '{}' is not yet available in this distribution on {}",
match bin_name {
"prometeu-runtime-desktop" => "run/debug",
"prometeu-runtime" => "run/debug",
"prometeuc" => "build/verify c",
"prometeup" => "pack/verify p",
_ => bin_name,

View File

@ -1,16 +0,0 @@
[package]
name = "prometeuc"
version = "0.1.0"
edition = "2021"
[dependencies]
prometeu-bytecode = { path = "../prometeu-bytecode" }
prometeu-core = { path = "../prometeu-core" }
oxc_parser = "0.48.0"
oxc_allocator = "0.48.0"
oxc_ast = "0.48.0"
oxc_span = "0.48.0"
clap = { version = "4.4", features = ["derive"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
anyhow = "1.0"

View File

@ -1,324 +0,0 @@
use anyhow::{Result, anyhow};
use oxc_ast::ast::*;
use oxc_span::{Span, GetSpan};
use prometeu_bytecode::opcode::OpCode;
use prometeu_bytecode::asm::{Asm, Operand, assemble};
use crate::compiler::Symbol;
use crate::syscall_map;
use std::collections::HashMap;
pub struct Codegen {
file_name: String,
source_text: String,
pub symbols: Vec<Symbol>,
instructions: Vec<(Asm, bool)>, // (Asm, has_symbol)
locals: HashMap<String, u32>,
next_local: u32,
label_count: u32,
}
impl Codegen {
pub fn new(file_name: String, source_text: String) -> Self {
Self {
file_name,
source_text,
symbols: Vec::new(),
instructions: Vec::new(),
locals: HashMap::new(),
next_local: 0,
label_count: 0,
}
}
pub fn compile_program(&mut self, program: &Program) -> Result<Vec<u8>> {
// Find tick function
let mut tick_fn = None;
for item in &program.body {
if let Statement::ExportNamedDeclaration(decl) = item {
if let Some(Declaration::FunctionDeclaration(f)) = &decl.declaration {
if let Some(ident) = &f.id {
if ident.name == "tick" {
tick_fn = Some(f);
break;
}
}
}
}
}
let tick_fn = tick_fn.ok_or_else(|| anyhow!("export function tick() not found"))?;
// Entry point: loop calling tick
self.emit_label("entry".to_string());
self.emit_op(OpCode::Call, vec![Operand::Label("tick".to_string()), Operand::U32(0)], Span::default());
self.emit_op(OpCode::FrameSync, vec![], Span::default());
self.emit_op(OpCode::Jmp, vec![Operand::Label("entry".to_string())], Span::default());
// Function tick
self.emit_label("tick".to_string());
self.compile_function(tick_fn)?;
self.emit_op(OpCode::Ret, vec![], Span::default());
let asm_vec: Vec<Asm> = self.instructions.iter().map(|(a, _)| a.clone()).collect();
let rom = assemble(&asm_vec).map_err(|e| anyhow!("Assemble error: {}", e))?;
// Finalize symbols (associate PC)
self.finalize_symbols();
Ok(rom)
}
fn compile_function(&mut self, f: &Function) -> Result<()> {
self.locals.clear();
self.next_local = 0;
if let Some(body) = &f.body {
for stmt in &body.statements {
self.compile_stmt(stmt)?;
}
}
Ok(())
}
fn compile_stmt(&mut self, stmt: &Statement) -> Result<()> {
match stmt {
Statement::VariableDeclaration(var) => {
for decl in &var.declarations {
if let BindingPatternKind::BindingIdentifier(ident) = &decl.id.kind {
let name = ident.name.to_string();
if let Some(init) = &decl.init {
self.compile_expr(init)?;
} else {
self.emit_op(OpCode::PushI32, vec![Operand::I32(0)], decl.span);
}
let id = self.next_local;
self.locals.insert(name, id);
self.emit_op(OpCode::SetLocal, vec![Operand::U32(id)], decl.span);
self.next_local += 1;
}
}
}
Statement::ExpressionStatement(expr_stmt) => {
self.compile_expr(&expr_stmt.expression)?;
self.emit_op(OpCode::Pop, vec![], expr_stmt.span);
}
Statement::IfStatement(if_stmt) => {
let else_label = self.new_label("else");
let end_label = self.new_label("end_if");
self.compile_expr(&if_stmt.test)?;
self.emit_op(OpCode::JmpIfFalse, vec![Operand::Label(else_label.clone())], if_stmt.span);
self.compile_stmt(&if_stmt.consequent)?;
self.emit_op(OpCode::Jmp, vec![Operand::Label(end_label.clone())], Span::default());
self.emit_label(else_label);
if let Some(alt) = &if_stmt.alternate {
self.compile_stmt(alt)?;
}
self.emit_label(end_label);
}
Statement::BlockStatement(block) => {
for stmt in &block.body {
self.compile_stmt(stmt)?;
}
}
_ => return Err(anyhow!("Unsupported statement type at {:?}", stmt.span())),
}
Ok(())
}
fn compile_expr(&mut self, expr: &Expression) -> Result<()> {
match expr {
Expression::NumericLiteral(n) => {
let val = n.value;
if val.fract() == 0.0 && val >= i32::MIN as f64 && val <= i32::MAX as f64 {
self.emit_op(OpCode::PushI32, vec![Operand::I32(val as i32)], n.span);
} else {
self.emit_op(OpCode::PushI64, vec![Operand::I64(val as i64)], n.span);
}
}
Expression::BooleanLiteral(b) => {
self.emit_op(OpCode::PushBool, vec![Operand::Bool(b.value)], b.span);
}
Expression::Identifier(ident) => {
let name = ident.name.to_string();
if let Some(&id) = self.locals.get(&name) {
self.emit_op(OpCode::GetLocal, vec![Operand::U32(id)], ident.span);
} else {
return Err(anyhow!("Undefined variable: {} at {:?}", name, ident.span));
}
}
Expression::AssignmentExpression(assign) => {
if let AssignmentTarget::AssignmentTargetIdentifier(ident) = &assign.left {
let name = ident.name.to_string();
self.compile_expr(&assign.right)?;
if let Some(&id) = self.locals.get(&name) {
self.emit_op(OpCode::Dup, vec![], assign.span);
self.emit_op(OpCode::SetLocal, vec![Operand::U32(id)], assign.span);
} else {
return Err(anyhow!("Undefined variable: {} at {:?}", name, ident.span));
}
} else {
return Err(anyhow!("Unsupported assignment target at {:?}", assign.span));
}
}
Expression::BinaryExpression(bin) => {
self.compile_expr(&bin.left)?;
self.compile_expr(&bin.right)?;
let op = match bin.operator {
BinaryOperator::Addition => OpCode::Add,
BinaryOperator::Subtraction => OpCode::Sub,
BinaryOperator::Multiplication => OpCode::Mul,
BinaryOperator::Division => OpCode::Div,
BinaryOperator::Equality => OpCode::Eq,
BinaryOperator::Inequality => OpCode::Neq,
BinaryOperator::LessThan => OpCode::Lt,
BinaryOperator::GreaterThan => OpCode::Gt,
BinaryOperator::LessEqualThan => OpCode::Lte,
BinaryOperator::GreaterEqualThan => OpCode::Gte,
_ => return Err(anyhow!("Unsupported binary operator {:?} at {:?}", bin.operator, bin.span)),
};
self.emit_op(op, vec![], bin.span);
}
Expression::LogicalExpression(log) => {
self.compile_expr(&log.left)?;
self.compile_expr(&log.right)?;
let op = match log.operator {
LogicalOperator::And => OpCode::And,
LogicalOperator::Or => OpCode::Or,
_ => return Err(anyhow!("Unsupported logical operator {:?} at {:?}", log.operator, log.span)),
};
self.emit_op(op, vec![], log.span);
}
Expression::UnaryExpression(unary) => {
self.compile_expr(&unary.argument)?;
let op = match unary.operator {
UnaryOperator::UnaryNegation => OpCode::Neg,
UnaryOperator::UnaryPlus => return Ok(()),
UnaryOperator::LogicalNot => OpCode::Not,
_ => return Err(anyhow!("Unsupported unary operator {:?} at {:?}", unary.operator, unary.span)),
};
self.emit_op(op, vec![], unary.span);
}
Expression::CallExpression(call) => {
let name = self.get_callee_name(&call.callee)?;
if let Some(syscall_id) = syscall_map::map_syscall(&name) {
if name == "input.btnA" {
self.emit_op(OpCode::PushI32, vec![Operand::I32(syscall_map::BTN_A as i32)], call.span);
} else if name == "input.btnB" {
self.emit_op(OpCode::PushI32, vec![Operand::I32(syscall_map::BTN_B as i32)], call.span);
} else {
for arg in &call.arguments {
if let Some(expr) = arg.as_expression() {
self.compile_expr(expr)?;
}
}
}
self.emit_op(OpCode::Syscall, vec![Operand::U32(syscall_id)], call.span);
} else {
return Err(anyhow!("Unsupported function call: {} at {:?}", name, call.span));
}
}
Expression::StaticMemberExpression(member) => {
let obj = self.get_callee_name_from_member_obj(&member.object)?;
let prop = member.property.name.to_string();
let full_name = format!("{}.{}", obj, prop);
// If it's used as a value (GetGlobal/GetLocal?), but for now we only support it in calls
return Err(anyhow!("Member expression outside call not supported: {} at {:?}", full_name, member.span));
}
_ => return Err(anyhow!("Unsupported expression type at {:?}", expr.span())),
}
Ok(())
}
fn get_callee_name(&self, expr: &Expression) -> Result<String> {
match expr {
Expression::Identifier(ident) => Ok(ident.name.to_string()),
Expression::StaticMemberExpression(member) => {
let obj = self.get_callee_name_from_member_obj(&member.object)?;
let prop = member.property.name.to_string();
Ok(format!("{}.{}", obj, prop))
}
_ => Err(anyhow!("Unsupported callee expression at {:?}", expr.span())),
}
}
fn get_callee_name_from_member_obj(&self, expr: &Expression) -> Result<String> {
if let Expression::Identifier(ident) = expr {
Ok(ident.name.to_string())
} else {
Err(anyhow!("Unsupported member object expression"))
}
}
fn new_label(&mut self, prefix: &str) -> String {
let label = format!("{}_{}", prefix, self.label_count);
self.label_count += 1;
label
}
fn emit_label(&mut self, name: String) {
self.instructions.push((Asm::Label(name), false));
}
fn emit_op(&mut self, opcode: OpCode, operands: Vec<Operand>, span: Span) {
let has_symbol = if !span.is_unspanned() {
let (line, col) = self.lookup_pos(span.start);
self.symbols.push(Symbol {
pc: 0,
file: self.file_name.clone(),
line,
col,
});
true
} else {
false
};
self.instructions.push((Asm::Op(opcode, operands), has_symbol));
}
fn lookup_pos(&self, pos: u32) -> (usize, usize) {
let mut line = 1;
let mut col = 1;
for (i, c) in self.source_text.char_indices() {
if i as u32 == pos {
break;
}
if c == '\n' {
line += 1;
col = 1;
} else {
col += 1;
}
}
(line, col)
}
fn finalize_symbols(&mut self) {
let mut current_pc = 0u32;
let mut symbol_ptr = 0;
for (instr, has_symbol) in &self.instructions {
match instr {
Asm::Label(_) => {}
Asm::Op(_opcode, operands) => {
if *has_symbol && symbol_ptr < self.symbols.len() {
self.symbols[symbol_ptr].pc = current_pc;
symbol_ptr += 1;
}
current_pc += 2;
for operand in operands {
match operand {
Operand::U32(_) | Operand::I32(_) | Operand::Label(_) => current_pc += 4,
Operand::I64(_) | Operand::F64(_) => current_pc += 8,
Operand::Bool(_) => current_pc += 1,
}
}
}
}
}
}
}

View File

@ -1,72 +0,0 @@
use std::path::Path;
use anyhow::{Result, Context};
use oxc_allocator::Allocator;
use oxc_parser::Parser;
use oxc_span::SourceType;
use crate::codegen::Codegen;
use std::fs;
use prometeu_bytecode::disasm::disasm;
use serde::Serialize;
#[derive(Serialize)]
pub struct Symbol {
pub pc: u32,
pub file: String,
pub line: usize,
pub col: usize,
}
pub fn compile(entry: &Path, out: &Path, emit_disasm: bool, emit_symbols: bool) -> Result<()> {
let source_text = fs::read_to_string(entry)
.with_context(|| format!("Failed to read entry file: {:?}", entry))?;
let allocator = Allocator::default();
let source_type = SourceType::from_path(entry).unwrap_or_default();
let mut codegen = Codegen::new(entry.to_string_lossy().to_string(), source_text.clone());
let rom = {
let ret = Parser::new(&allocator, &source_text, source_type).parse();
if !ret.errors.is_empty() {
for error in ret.errors {
eprintln!("{:?}", error);
}
return Err(anyhow::anyhow!("Failed to parse module"));
}
codegen.compile_program(&ret.program)?
};
fs::write(out, &rom).with_context(|| format!("Failed to write PBC to {:?}", out))?;
if emit_symbols {
let symbols_path = out.with_file_name("symbols.json");
let symbols_json = serde_json::to_string_pretty(&codegen.symbols)?;
fs::write(&symbols_path, symbols_json)?;
}
if emit_disasm {
let disasm_path = out.with_extension("disasm.txt");
let instructions = disasm(&rom).map_err(|e| anyhow::anyhow!("Disassembly failed: {}", e))?;
let mut disasm_text = String::new();
for instr in instructions {
let symbol = codegen.symbols.iter().find(|s| s.pc == instr.pc);
let comment = if let Some(s) = symbol {
format!(" ; {}:{}", s.file, s.line)
} else {
"".to_string()
};
let operands_str = instr.operands.iter()
.map(|o| format!("{:?}", o))
.collect::<Vec<_>>()
.join(" ");
disasm_text.push_str(&format!("{:08X} {:?} {}{}\n", instr.pc, instr.opcode, operands_str, comment));
}
fs::write(disasm_path, disasm_text)?;
}
Ok(())
}

View File

@ -8,9 +8,9 @@ The protocol is based on JSON, sent via a transport connection (usually TCP). Ea
## Structure
- **[protocol.json](./protocol.json)**: Formal definition of the protocol in JSON format.
- **[protocol.json](protocol.json)**: Formal definition of the protocol in JSON format.
- **[protocol.md](README.md)**: Human-readable documentation describing commands, events, and types.
- **[examples/](./examples)**: Examples of message flows (handshake, breakpoints, etc.) in JSONL format.
- **[examples/](examples)**: Examples of message flows (handshake, breakpoints, etc.) in JSONL format.
## Versioning

View File

@ -0,0 +1,6 @@
{
"name": "@prometeu/sdk",
"version": "0.1.0",
"main": "src/index.ts",
"types": "types/index.d.ts"
}

View File

@ -0,0 +1,2 @@
export const Audio = audio;
export type Audio = Prometeu.Audio;

View File

@ -0,0 +1,25 @@
export type Color565 = Prometeu.Color565;
function clamp8(n: number): number {
return n < 0 ? 0 : n > 255 ? 255 : n | 0;
}
export const Color: Prometeu.Color = {
black: 0x0000 as Color565,
white: 0xffff as Color565,
red: 0xf800 as Color565,
green: 0x07e0 as Color565,
blue: 0x001f as Color565,
yellow: 0xffe0 as Color565,
cyan: 0x07ff as Color565,
magenta: 0xf81f as Color565,
indigo: 0x4810 as Color565,
rgb(r: number, g: number, b: number): Color565 {
r = clamp8(r); g = clamp8(g); b = clamp8(b);
const r5 = (r >> 3) & 0x1f;
const g6 = (g >> 2) & 0x3f;
const b5 = (b >> 3) & 0x1f;
return ((r5 << 11) | (g6 << 5) | b5) as Color565;
},
};

View File

@ -0,0 +1,2 @@
export const Fs = fs;
export type Fs = Prometeu.Fs;

View File

@ -0,0 +1 @@
export type Gfx = Prometeu.Gfx;

View File

@ -0,0 +1,8 @@
export { Color } from "./color";
export { Pad, Touch } from "./input";
export { Gfx } from "./gfx";
export { System } from "./system";
export { Audio } from "./audio";
export { Fs } from "./fs";
export { Log, LogLevel } from "./log";
export type { Color565 } from "./color";

View File

@ -0,0 +1,4 @@
export const Pad: Prometeu.Pad = pad;
export const Touch: Prometeu.Touch = touch;

View File

@ -0,0 +1,11 @@
export const Log = log;
export type Log = Prometeu.Log;
export enum LogLevel {
Trace = 0,
Debug = 1,
Info = 2,
Warn = 3,
Error = 4,
Fatal = 5,
}

View File

@ -0,0 +1,2 @@
export const System = system;
export type System = Prometeu.System;

View File

@ -0,0 +1,4 @@
{
"compilerOptions": {
}
}

View File

@ -0,0 +1,95 @@
export {}; // that is a module, should not include any other scope here
declare global {
namespace Prometeu {
type Color565 = number & { readonly __brand: "Color565" };
interface Button {
readonly down: boolean;
readonly pressed: boolean;
readonly released: boolean;
readonly holdFrames: number;
}
interface Pad {
readonly up: Button;
readonly down: Button;
readonly left: Button;
readonly right: Button;
readonly a: Button;
readonly b: Button;
readonly x: Button;
readonly y: Button;
readonly l: Button;
readonly r: Button;
readonly start: Button;
readonly select: Button;
}
interface Touch {
readonly x: number;
readonly y: number;
readonly button: Button;
}
interface Gfx {
fillRect(x: number, y: number, w: number, h: number, color: Color565): void;
drawLine(x1: number, y1: number, x2: number, y2: number, color: Color565): void;
drawCircle(x: number, y: number, r: number, color: Color565): void;
drawDisc(x: number, y: number, r: number, borderColor: Color565, fillColor: Color565): void;
drawSquare(x: number, y: number, w: number, h: number, borderColor: Color565, fillColor: Color565): void;
clear(color: Color565): void;
}
interface Color {
readonly black: Color565;
readonly white: Color565;
readonly red: Color565;
readonly green: Color565;
readonly blue: Color565;
readonly yellow: Color565;
readonly cyan: Color565;
readonly magenta: Color565;
readonly indigo: Color565;
readonly color_key: Color565;
readonly orange: Color565;
readonly gray: Color565;
readonly grey: Color565;
rgb(r: number, g: number, b: number): Color565;
}
interface System {
hasCart(): boolean;
}
interface Audio {
playSample(sampleId: number, voiceId: number, volume: number, pan: number, pitch: number): void;
}
interface Fs {
open(path: string): number;
read(handle: number): string | null;
write(handle: number, content: string): boolean;
close(handle: number): void;
listDir(path: string): string | null;
exists(path: string): boolean;
delete(path: string): boolean;
}
interface Log {
write(level: number, msg: string): void;
writeTag(level: number, tag: number, msg: string): void;
}
}
export const pad: Prometeu.Pad;
export const touch: Prometeu.Touch;
export const gfx: Prometeu.Gfx;
export const audio: Prometeu.Audio;
export const fs: Prometeu.Fs;
export const log: Prometeu.Log;
export const color: Prometeu.Color;
export const system: Prometeu.System;
}

View File

@ -15,4 +15,4 @@ targets = ["aarch64-apple-darwin", "x86_64-apple-darwin"]
unix-archive = ".zip"
macos-universal-binaries = true
[dist.hooks]
pre-build = ["./scripts/gen-version.sh"]
pre-build = ["./scripts/pre-dist.sh"]

View File

@ -11,5 +11,5 @@ Detailed documentation on system architecture, cartridge format, VM instruction
### 🐞 [Debugger](./debugger)
Documentation on debugging tools and how to integrate new tools into the ecosystem.
### 🔌 [DevTools Protocol](../devtools-protocol)
### 🔌 [DevTools Protocol](../devtools)
Definition of the communication protocol used for real-time debugging and inspection.

View File

@ -1,8 +1,8 @@
export function tick(): void {
let color = 0x07E0; // green
if (input.btnA()) color = 0xF800; // red
if (input.btnB()) color = 0x001F; // blue
if (PInput.btnA()) color = 0xF800; // red
if (PInput.btnB()) color = 0x001F; // blue
gfx.fillRect(60, 60, 40, 40, color);
Gfx.fillRect(60, 60, 40, 40, color);
}

5
scripts/clean-all.sh Executable file
View File

@ -0,0 +1,5 @@
#!/bin/bash
set -euo pipefail
cargo clean
rm -rf dist-staging

View File

@ -1,5 +1,5 @@
#!/bin/bash
# Get version from git tag or fallback to Cargo.toml version
VERSION=$(git describe --tags --abbrev=0 2>/dev/null || grep -m 1 '^version =' crates/prometeu-runtime-desktop/Cargo.toml | cut -d '"' -f 2 || echo "0.1.0")
VERSION=$(git describe --tags --abbrev=0 2>/dev/null || grep -m 1 '^version =' crates/prometeu/Cargo.toml | cut -d '"' -f 2 || echo "0.1.0")
echo "$VERSION" > VERSION.txt
echo "Generated VERSION.txt with version $VERSION"

View File

@ -1,25 +1,33 @@
#!/bin/bash
set -e
# Generate version
./scripts/gen-version.sh
VERSION=$(cat VERSION.txt)
# Prepare staging for SDK extra files
echo "Preparing dist-staging..."
mkdir -p dist-staging/devtools-protocol
cp devtools-protocol/protocol.json dist-staging/devtools-protocol/
rm -rf dist-staging/devtools/debugger-protocol
rm -rf dist-staging/devtools/typescript-sdk
mkdir -p dist-staging/devtools/debugger-protocol
mkdir -p dist-staging/devtools/typescript-sdk
cp devtools/debugger-protocol/protocol.json dist-staging/devtools/debugger-protocol/
cp -R devtools/typescript-sdk dist-staging/devtools
cp VERSION.txt dist-staging/devtools/debugger-protocol/VERSION.txt
cp VERSION.txt dist-staging/devtools/typescript-sdk/VERSION.txt
# Clean and prepare the version-specific directory
echo "Cleaning dist-staging/stable/$VERSION..."
rm -rf "dist-staging/stable/$VERSION"
mkdir -p "dist-staging/stable/$VERSION"
echo "Cleaning dist-staging/stable..."
mkdir -p "dist-staging/stable"
rm -rf "dist-staging/stable/*"
# Build stable using cargo build
dist build
echo "Copying target/distrib content to dist-staging/stable/$VERSION..."
echo "Copying target/distrib content to dist-staging/stable..."
if [ -d "target/distrib" ] && [ "$(ls -A target/distrib)" ]; then
cp -r target/distrib/* "dist-staging/stable/$VERSION/"
cp -r target/distrib/* "dist-staging/stable/"
else
echo "Warning: target/dist directory not found or empty."
fi

80
symbols.json Normal file
View File

@ -0,0 +1,80 @@
[
{
"pc": 20,
"file": "temp_test_2.ts",
"line": 1,
"col": 1
},
{
"pc": 22,
"file": "temp_test_2.ts",
"line": 2,
"col": 13
},
{
"pc": 28,
"file": "temp_test_2.ts",
"line": 2,
"col": 17
},
{
"pc": 34,
"file": "temp_test_2.ts",
"line": 2,
"col": 13
},
{
"pc": 46,
"file": "temp_test_2.ts",
"line": 5,
"col": 8
},
{
"pc": 48,
"file": "temp_test_2.ts",
"line": 6,
"col": 10
},
{
"pc": 54,
"file": "temp_test_2.ts",
"line": 6,
"col": 14
},
{
"pc": 60,
"file": "temp_test_2.ts",
"line": 6,
"col": 5
},
{
"pc": 70,
"file": "temp_test_2.ts",
"line": 6,
"col": 5
},
{
"pc": 72,
"file": "temp_test_2.ts",
"line": 7,
"col": 15
},
{
"pc": 78,
"file": "temp_test_2.ts",
"line": 7,
"col": 18
},
{
"pc": 84,
"file": "temp_test_2.ts",
"line": 7,
"col": 5
},
{
"pc": 90,
"file": "temp_test_2.ts",
"line": 7,
"col": 5
}
]

23
temp_test_2.disasm.txt Normal file
View File

@ -0,0 +1,23 @@
00000000 Call U32(46) U32(0)
0000000A Pop
0000000C FrameSync
0000000E Jmp U32(0)
00000014 PushScope ; temp_test_2.ts:1
00000016 GetLocal U32(0) ; temp_test_2.ts:2
0000001C GetLocal U32(1) ; temp_test_2.ts:2
00000022 Add ; temp_test_2.ts:2
00000024 PopScope
00000026 PushConst U32(0)
0000002C Ret
0000002E PushScope ; temp_test_2.ts:5
00000030 PushI32 U32(10) ; temp_test_2.ts:6
00000036 PushI32 U32(20) ; temp_test_2.ts:6
0000003C Call U32(20) U32(2) ; temp_test_2.ts:6
00000046 Pop ; temp_test_2.ts:6
00000048 PushI32 U32(1) ; temp_test_2.ts:7
0000004E PushConst U32(1) ; temp_test_2.ts:7
00000054 Syscall U32(20481) ; temp_test_2.ts:7
0000005A Pop ; temp_test_2.ts:7
0000005C PopScope
0000005E PushConst U32(0)
00000064 Ret

View File

@ -0,0 +1,158 @@
00000000 Call U32(20) U32(0)
0000000A Pop
0000000C FrameSync
0000000E Jmp U32(0)
00000014 PushScope ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/main.ts:5
00000016 Call U32(428) U32(0) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/main.ts:6
00000020 Pop ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/main.ts:6
00000022 Call U32(236) U32(0) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/main.ts:7
0000002C Pop ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/main.ts:7
0000002E Call U32(362) U32(0) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/main.ts:8
00000038 Pop ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/main.ts:8
0000003A Call U32(92) U32(0) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/main.ts:9
00000044 Pop ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/main.ts:9
00000046 Call U32(644) U32(0) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/main.ts:10
00000050 Pop ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/main.ts:10
00000052 PopScope
00000054 PushConst U32(0)
0000005A Ret
0000005C PushScope ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:1
0000005E PushConst U32(1) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:2
00000064 Syscall U32(16385) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:2
0000006A GetLocal U32(0) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:3
00000070 PushI32 U32(0) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:3
00000076 Gte ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:3
00000078 JmpIfFalse U32(226) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:3
0000007E PushScope ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:3
00000080 GetLocal U32(0) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:4
00000086 PushConst U32(2) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:4
0000008C Syscall U32(16387) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:4
00000092 Pop ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:4
00000094 GetLocal U32(0) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:5
0000009A Syscall U32(16386) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:5
000000A0 GetLocal U32(1) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:6
000000A6 JmpIfFalse U32(204) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:6
000000AC PushI32 U32(2) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:6
000000B2 PushI32 U32(101) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:6
000000B8 GetLocal U32(1) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:6
000000BE Syscall U32(20482) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:6
000000C4 Pop ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:6
000000C6 Jmp U32(204)
000000CC GetLocal U32(0) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:7
000000D2 Syscall U32(16388) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:7
000000D8 Pop ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:7
000000DA PopScope ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts:3
000000DC Jmp U32(226)
000000E2 PopScope
000000E4 PushConst U32(0)
000000EA Ret
000000EC PushScope ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:1
000000EE PushI32 U32(0) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:2
000000F4 Syscall U32(8193) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:2
000000FA JmpIfFalse U32(286) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:2
00000100 PushScope ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:2
00000102 PushI32 U32(2) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:3
00000108 PushConst U32(3) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:3
0000010E Syscall U32(20481) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:3
00000114 Pop ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:3
00000116 PopScope ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:2
00000118 Jmp U32(286)
0000011E PushI32 U32(4) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:6
00000124 Syscall U32(8194) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:6
0000012A JmpIfFalse U32(352) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:6
00000130 PushScope ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:6
00000132 PushI32 U32(1) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:7
00000138 PushI32 U32(0) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:7
0000013E PushI32 U32(255) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:7
00000144 PushI32 U32(128) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:7
0000014A PushI32 U32(1) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:7
00000150 Syscall U32(12289) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:7
00000156 Pop ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:7
00000158 PopScope ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:6
0000015A Jmp U32(352)
00000160 PopScope
00000162 PushConst U32(0)
00000168 Ret
0000016A PushScope ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:11
0000016C Syscall U32(8451) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:12
00000172 JmpIfFalse U32(418) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:12
00000178 PushScope ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:12
0000017A Syscall U32(8449) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:13
00000180 Syscall U32(8450) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:13
00000186 PushI32 U32(5) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:13
0000018C PushI32 U32(65535) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:13
00000192 Syscall U32(4100) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:13
00000198 Pop ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:13
0000019A PopScope ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts:12
0000019C Jmp U32(418)
000001A2 PopScope
000001A4 PushConst U32(0)
000001AA Ret
000001AC PushScope ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:1
000001AE PushI32 U32(18448) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:2
000001B4 Syscall U32(4097) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:2
000001BA Pop ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:2
000001BC PushI32 U32(10) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:3
000001C2 PushI32 U32(10) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:3
000001C8 PushI32 U32(50) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:3
000001CE PushI32 U32(50) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:3
000001D4 PushI32 U32(63488) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:3
000001DA Syscall U32(4098) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:3
000001E0 Pop ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:3
000001E2 PushI32 U32(0) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:4
000001E8 PushI32 U32(0) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:4
000001EE PushI32 U32(128) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:4
000001F4 PushI32 U32(128) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:4
000001FA PushI32 U32(65535) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:4
00000200 Syscall U32(4099) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:4
00000206 Pop ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:4
00000208 PushI32 U32(64) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:5
0000020E PushI32 U32(64) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:5
00000214 PushI32 U32(20) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:5
0000021A PushI32 U32(31) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:5
00000220 Syscall U32(4100) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:5
00000226 Pop ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:5
00000228 PushI32 U32(100) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:6
0000022E PushI32 U32(100) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:6
00000234 PushI32 U32(10) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:6
0000023A PushI32 U32(2016) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:6
00000240 PushI32 U32(65504) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:6
00000246 Syscall U32(4101) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:6
0000024C Pop ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:6
0000024E PushI32 U32(20) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:7
00000254 PushI32 U32(100) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:7
0000025A PushI32 U32(30) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:7
00000260 PushI32 U32(30) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:7
00000266 PushI32 U32(2047) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:7
0000026C PushI32 U32(63519) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:7
00000272 Syscall U32(4102) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:7
00000278 Pop ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:7
0000027A PopScope
0000027C PushConst U32(0)
00000282 Ret
00000284 PushScope ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:10
00000286 PushI32 U32(255) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:11
0000028C PushI32 U32(3) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:11
00000292 Shr ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:11
00000294 PushI32 U32(11) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:11
0000029A Shl ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:11
0000029C PushI32 U32(128) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:11
000002A2 PushI32 U32(2) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:11
000002A8 Shr ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:11
000002AA PushI32 U32(5) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:11
000002B0 Shl ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:11
000002B2 BitOr ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:11
000002B4 PushI32 U32(0) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:11
000002BA PushI32 U32(3) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:11
000002C0 Shr ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:11
000002C2 BitOr ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:11
000002C4 PushI32 U32(0) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:12
000002CA PushI32 U32(0) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:12
000002D0 PushI32 U32(5) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:12
000002D6 PushI32 U32(5) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:12
000002DC GetLocal U32(0) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:12
000002E2 Syscall U32(4098) ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:12
000002E8 Pop ; /Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts:12
000002EA PopScope
000002EC PushConst U32(0)
000002F2 Ret

Binary file not shown.

View File

@ -0,0 +1,788 @@
[
{
"pc": 20,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/main.ts",
"line": 5,
"col": 8
},
{
"pc": 22,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/main.ts",
"line": 6,
"col": 5
},
{
"pc": 32,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/main.ts",
"line": 6,
"col": 5
},
{
"pc": 34,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/main.ts",
"line": 7,
"col": 5
},
{
"pc": 44,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/main.ts",
"line": 7,
"col": 5
},
{
"pc": 46,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/main.ts",
"line": 8,
"col": 5
},
{
"pc": 56,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/main.ts",
"line": 8,
"col": 5
},
{
"pc": 58,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/main.ts",
"line": 9,
"col": 5
},
{
"pc": 68,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/main.ts",
"line": 9,
"col": 5
},
{
"pc": 70,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/main.ts",
"line": 10,
"col": 5
},
{
"pc": 80,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/main.ts",
"line": 10,
"col": 5
},
{
"pc": 92,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts",
"line": 1,
"col": 8
},
{
"pc": 94,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts",
"line": 2,
"col": 21
},
{
"pc": 100,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts",
"line": 2,
"col": 13
},
{
"pc": 106,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts",
"line": 3,
"col": 9
},
{
"pc": 112,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts",
"line": 3,
"col": 14
},
{
"pc": 118,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts",
"line": 3,
"col": 9
},
{
"pc": 120,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts",
"line": 3,
"col": 5
},
{
"pc": 126,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts",
"line": 3,
"col": 17
},
{
"pc": 128,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts",
"line": 4,
"col": 18
},
{
"pc": 134,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts",
"line": 4,
"col": 21
},
{
"pc": 140,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts",
"line": 4,
"col": 9
},
{
"pc": 146,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts",
"line": 4,
"col": 9
},
{
"pc": 148,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts",
"line": 5,
"col": 31
},
{
"pc": 154,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts",
"line": 5,
"col": 23
},
{
"pc": 160,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts",
"line": 6,
"col": 13
},
{
"pc": 166,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts",
"line": 6,
"col": 9
},
{
"pc": 172,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts",
"line": 6,
"col": 35
},
{
"pc": 178,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts",
"line": 6,
"col": 38
},
{
"pc": 184,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts",
"line": 6,
"col": 43
},
{
"pc": 190,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts",
"line": 6,
"col": 22
},
{
"pc": 196,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts",
"line": 6,
"col": 22
},
{
"pc": 204,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts",
"line": 7,
"col": 18
},
{
"pc": 210,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts",
"line": 7,
"col": 9
},
{
"pc": 216,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts",
"line": 7,
"col": 9
},
{
"pc": 218,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_fs.ts",
"line": 3,
"col": 17
},
{
"pc": 236,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts",
"line": 1,
"col": 8
},
{
"pc": 238,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts",
"line": 2,
"col": 9
},
{
"pc": 244,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts",
"line": 2,
"col": 9
},
{
"pc": 250,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts",
"line": 2,
"col": 5
},
{
"pc": 256,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts",
"line": 2,
"col": 22
},
{
"pc": 258,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts",
"line": 3,
"col": 19
},
{
"pc": 264,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts",
"line": 3,
"col": 22
},
{
"pc": 270,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts",
"line": 3,
"col": 9
},
{
"pc": 276,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts",
"line": 3,
"col": 9
},
{
"pc": 278,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts",
"line": 2,
"col": 22
},
{
"pc": 286,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts",
"line": 6,
"col": 9
},
{
"pc": 292,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts",
"line": 6,
"col": 9
},
{
"pc": 298,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts",
"line": 6,
"col": 5
},
{
"pc": 304,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts",
"line": 6,
"col": 24
},
{
"pc": 306,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts",
"line": 7,
"col": 26
},
{
"pc": 312,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts",
"line": 7,
"col": 29
},
{
"pc": 318,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts",
"line": 7,
"col": 32
},
{
"pc": 324,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts",
"line": 7,
"col": 37
},
{
"pc": 330,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts",
"line": 7,
"col": 42
},
{
"pc": 336,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts",
"line": 7,
"col": 9
},
{
"pc": 342,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts",
"line": 7,
"col": 9
},
{
"pc": 344,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts",
"line": 6,
"col": 24
},
{
"pc": 362,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts",
"line": 11,
"col": 8
},
{
"pc": 364,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts",
"line": 12,
"col": 9
},
{
"pc": 370,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts",
"line": 12,
"col": 5
},
{
"pc": 376,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts",
"line": 12,
"col": 28
},
{
"pc": 378,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts",
"line": 13,
"col": 24
},
{
"pc": 384,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts",
"line": 13,
"col": 33
},
{
"pc": 390,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts",
"line": 13,
"col": 42
},
{
"pc": 396,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts",
"line": 13,
"col": 45
},
{
"pc": 402,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts",
"line": 13,
"col": 9
},
{
"pc": 408,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts",
"line": 13,
"col": 9
},
{
"pc": 410,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_input.ts",
"line": 12,
"col": 28
},
{
"pc": 428,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 1,
"col": 8
},
{
"pc": 430,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 2,
"col": 15
},
{
"pc": 436,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 2,
"col": 5
},
{
"pc": 442,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 2,
"col": 5
},
{
"pc": 444,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 3,
"col": 18
},
{
"pc": 450,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 3,
"col": 22
},
{
"pc": 456,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 3,
"col": 26
},
{
"pc": 462,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 3,
"col": 30
},
{
"pc": 468,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 3,
"col": 34
},
{
"pc": 474,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 3,
"col": 5
},
{
"pc": 480,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 3,
"col": 5
},
{
"pc": 482,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 4,
"col": 18
},
{
"pc": 488,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 4,
"col": 21
},
{
"pc": 494,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 4,
"col": 24
},
{
"pc": 500,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 4,
"col": 29
},
{
"pc": 506,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 4,
"col": 34
},
{
"pc": 512,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 4,
"col": 5
},
{
"pc": 518,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 4,
"col": 5
},
{
"pc": 520,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 5,
"col": 20
},
{
"pc": 526,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 5,
"col": 24
},
{
"pc": 532,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 5,
"col": 28
},
{
"pc": 538,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 5,
"col": 32
},
{
"pc": 544,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 5,
"col": 5
},
{
"pc": 550,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 5,
"col": 5
},
{
"pc": 552,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 6,
"col": 18
},
{
"pc": 558,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 6,
"col": 23
},
{
"pc": 564,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 6,
"col": 28
},
{
"pc": 570,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 6,
"col": 32
},
{
"pc": 576,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 6,
"col": 45
},
{
"pc": 582,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 6,
"col": 5
},
{
"pc": 588,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 6,
"col": 5
},
{
"pc": 590,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 7,
"col": 20
},
{
"pc": 596,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 7,
"col": 24
},
{
"pc": 602,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 7,
"col": 29
},
{
"pc": 608,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 7,
"col": 33
},
{
"pc": 614,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 7,
"col": 37
},
{
"pc": 620,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 7,
"col": 49
},
{
"pc": 626,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 7,
"col": 5
},
{
"pc": 632,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 7,
"col": 5
},
{
"pc": 644,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 10,
"col": 8
},
{
"pc": 646,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 11,
"col": 23
},
{
"pc": 652,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 11,
"col": 13
},
{
"pc": 658,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 11,
"col": 13
},
{
"pc": 660,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 11,
"col": 13
},
{
"pc": 666,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 11,
"col": 13
},
{
"pc": 668,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 11,
"col": 28
},
{
"pc": 674,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 11,
"col": 13
},
{
"pc": 680,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 11,
"col": 13
},
{
"pc": 682,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 11,
"col": 13
},
{
"pc": 688,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 11,
"col": 13
},
{
"pc": 690,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 11,
"col": 13
},
{
"pc": 692,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 11,
"col": 33
},
{
"pc": 698,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 11,
"col": 13
},
{
"pc": 704,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 11,
"col": 13
},
{
"pc": 706,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 11,
"col": 13
},
{
"pc": 708,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 12,
"col": 18
},
{
"pc": 714,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 12,
"col": 21
},
{
"pc": 720,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 12,
"col": 24
},
{
"pc": 726,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 12,
"col": 27
},
{
"pc": 732,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 12,
"col": 30
},
{
"pc": 738,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 12,
"col": 5
},
{
"pc": 744,
"file": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/test-cartridges/color-square/src/my_gfx.ts",
"line": 12,
"col": 5
}
]

Binary file not shown.

View File

@ -0,0 +1,22 @@
{
"name": "color-square",
"lockfileVersion": 3,
"requires": true,
"packages": {
"../prometeu-sdk": {
"extraneous": true
},
"node_modules/@prometeu/sdk": {
"resolved": "prometeu-sdk/typescript-sdk",
"link": true
},
"prometeu-sdk": {
"name": "@prometeu/sdk",
"version": "0.1.0"
},
"prometeu-sdk/typescript-sdk": {
"name": "@prometeu/sdk",
"version": "0.1.0"
}
}
}

1
test-cartridges/color-square/node_modules/@prometeu/sdk generated vendored Symbolic link
View File

@ -0,0 +1 @@
../../prometeu-sdk/typescript-sdk

View File

@ -0,0 +1,27 @@
{
"name": "color-square",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"dependencies": {
"@prometeu/sdk": "file:./prometeu-sdk/typescript-sdk"
}
},
"../prometeu-sdk": {
"extraneous": true
},
"node_modules/@prometeu/sdk": {
"resolved": "prometeu-sdk/typescript-sdk",
"link": true
},
"prometeu-sdk": {
"name": "@prometeu/sdk",
"version": "0.1.0"
},
"prometeu-sdk/typescript-sdk": {
"name": "@prometeu/sdk",
"version": "0.1.0"
}
}
}

View File

@ -0,0 +1,5 @@
{
"dependencies": {
"@prometeu/sdk": "file:./prometeu-sdk/typescript-sdk"
}
}

View File

@ -0,0 +1 @@
../../dist-staging/stable/prometeu-aarch64-apple-darwin/

View File

@ -0,0 +1,5 @@
#!/bin/bash
./prometeu-sdk/prometeu build .
cp build/program.pbc cartridge
./prometeu-sdk/prometeu run cartridge

View File

@ -0,0 +1,11 @@
import {do_init_gfx, print_orange} from "./my_gfx";
import {do_pad, do_touch} from "./my_input";
import {do_fs} from "./my_fs";
export function tick(): void {
do_init_gfx();
do_pad();
do_touch();
do_fs();
print_orange();
}

View File

@ -0,0 +1,9 @@
export function do_fs(): void {
let h = fs.open("test.txt");
if (h >= 0) {
fs.write(h, "Hello Prometeu!");
let content = fs.read(h);
if (content) log.writeTag(2, 101, content);
fs.close(h);
}
}

View File

@ -0,0 +1,13 @@
export function do_init_gfx(): void {
gfx.clear(color.indigo);
gfx.fillRect(10, 10, 50, 50, color.red);
gfx.drawLine(0, 0, 128, 128, color.white);
gfx.drawCircle(64, 64, 20, color.blue);
gfx.drawDisc(100, 100, 10, color.green, color.yellow);
gfx.drawSquare(20, 100, 30, 30, color.cyan, color.color_key);
}
export function print_orange(): void {
let c = color.rgb(255, 128, 0);
gfx.fillRect(0, 0, 5, 5, c);
}

View File

@ -0,0 +1,15 @@
export function do_pad(): void {
if (pad.up.down) {
log.write(2, "Up is down");
}
if (pad.a.pressed) {
audio.playSample(1, 0, 255, 128, 1.0);
}
}
export function do_touch(): void {
if (touch.button.down) {
gfx.drawCircle(touch.x, touch.y, 5, color.white);
}
}

View File

@ -0,0 +1,6 @@
{
"compilerOptions": {
"typeRoots": [
"./prometeu-sdk/types", "./node_modules/@types"]
}
}