This commit is contained in:
bQUARKz 2026-02-20 17:52:12 +00:00
parent 1a782cbb5c
commit a199857280
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8
32 changed files with 118 additions and 463 deletions

View File

@ -98,6 +98,7 @@ impl Value {
}
}
#[allow(clippy::inherent_to_string)]
pub fn to_string(&self) -> String {
match self {
Value::Int32(i) => i.to_string(),

View File

@ -1,3 +1,4 @@
#![allow(clippy::collapsible_if)]
use crate::memory_banks::{SoundBankPoolInstaller, TileBankPoolInstaller};
use prometeu_hal::AssetBridge;
use prometeu_hal::asset::{
@ -486,12 +487,12 @@ impl AssetManager {
let palette_data = &buffer[pixel_data_size..pixel_data_size + 2048];
let mut palettes = [[Color::BLACK; 16]; 64];
for p in 0..64 {
for c in 0..16 {
for (p, pal) in palettes.iter_mut().enumerate() {
for (c, slot) in pal.iter_mut().enumerate() {
let offset = (p * 16 + c) * 2;
let color_raw =
u16::from_le_bytes([palette_data[offset], palette_data[offset + 1]]);
palettes[p][c] = Color(color_raw);
*slot = Color(color_raw);
}
}
@ -687,7 +688,7 @@ impl AssetManager {
match slot.asset_type {
BankType::TILES => {
let slots = self.gfx_slots.read().unwrap();
let asset_id = slots.get(slot.index).and_then(|s| s.clone());
let asset_id = slots.get(slot.index).and_then(|s| *s);
let (bytes, asset_name) = if let Some(id) = &asset_id {
let bytes = self
@ -708,7 +709,7 @@ impl AssetManager {
}
BankType::SOUNDS => {
let slots = self.sound_slots.read().unwrap();
let asset_id = slots.get(slot.index).and_then(|s| s.clone());
let asset_id = slots.get(slot.index).and_then(|s| *s);
let (bytes, asset_name) = if let Some(id) = &asset_id {
let bytes = self

View File

@ -8,6 +8,7 @@ pub enum LoopMode {
}
pub trait AudioBridge {
#[allow(clippy::too_many_arguments)]
fn play(
&mut self,
bank_id: u8,
@ -19,6 +20,7 @@ pub trait AudioBridge {
priority: u8,
loop_mode: LoopMode,
);
#[allow(clippy::too_many_arguments)]
fn play_sample(
&mut self,
sample: Arc<Sample>,

View File

@ -27,7 +27,7 @@ pub struct Button {
impl Button {
pub fn begin_frame(&mut self, is_down_now: bool) {
let was_down = self.down;
self.down = is_down_now.clone();
self.down = is_down_now;
self.pressed = !was_down && self.down;
self.released = was_down && !self.down;

View File

@ -50,55 +50,55 @@ impl Certifier {
let mut violations = 0;
if let Some(budget) = self.config.cycles_budget_per_frame {
if telemetry.cycles_used > budget {
log_service.log(
ts_ms,
telemetry.frame_index,
LogLevel::Warn,
LogSource::Pos,
0xCA01,
format!(
"Cert: cycles_used exceeded budget ({} > {})",
telemetry.cycles_used, budget
),
);
violations += 1;
}
if let Some(budget) = self.config.cycles_budget_per_frame
&& telemetry.cycles_used > budget
{
log_service.log(
ts_ms,
telemetry.frame_index,
LogLevel::Warn,
LogSource::Pos,
0xCA01,
format!(
"Cert: cycles_used exceeded budget ({} > {})",
telemetry.cycles_used, budget
),
);
violations += 1;
}
if let Some(limit) = self.config.max_syscalls_per_frame {
if telemetry.syscalls > limit {
log_service.log(
ts_ms,
telemetry.frame_index,
LogLevel::Warn,
LogSource::Pos,
0xCA02,
format!(
"Cert: syscalls per frame exceeded limit ({} > {})",
telemetry.syscalls, limit
),
);
violations += 1;
}
if let Some(limit) = self.config.max_syscalls_per_frame
&& telemetry.syscalls > limit
{
log_service.log(
ts_ms,
telemetry.frame_index,
LogLevel::Warn,
LogSource::Pos,
0xCA02,
format!(
"Cert: syscalls per frame exceeded limit ({} > {})",
telemetry.syscalls, limit
),
);
violations += 1;
}
if let Some(limit) = self.config.max_host_cpu_us_per_frame {
if telemetry.host_cpu_time_us > limit {
log_service.log(
ts_ms,
telemetry.frame_index,
LogLevel::Warn,
LogSource::Pos,
0xCA03,
format!(
"Cert: host_cpu_time_us exceeded limit ({} > {})",
telemetry.host_cpu_time_us, limit
),
);
violations += 1;
}
if let Some(limit) = self.config.max_host_cpu_us_per_frame
&& telemetry.host_cpu_time_us > limit
{
log_service.log(
ts_ms,
telemetry.frame_index,
LogLevel::Warn,
LogSource::Pos,
0xCA03,
format!(
"Cert: host_cpu_time_us exceeded limit ({} > {})",
telemetry.host_cpu_time_us, limit
),
);
violations += 1;
}
violations

View File

@ -54,6 +54,7 @@ impl Heap {
/// Allocate a new object with the given kind and raw payload bytes.
/// Returns an opaque `HeapRef` handle.
#[cfg(test)]
pub fn allocate_object(&mut self, kind: ObjectKind, payload: &[u8]) -> HeapRef {
let header = ObjectHeader::new(kind, payload.len() as u32);
let obj = StoredObject { header, payload: payload.to_vec(), array_elems: None, closure_env: None, coroutine: None };
@ -65,6 +66,7 @@ impl Heap {
/// Allocate a new `Array` object with the given `Value` elements.
/// `payload_len` stores the element count; raw `payload` bytes are empty.
#[cfg(test)]
pub fn allocate_array(&mut self, elements: Vec<Value>) -> HeapRef {
let header = ObjectHeader::new(ObjectKind::Array, elements.len() as u32);
let obj = StoredObject { header, payload: Vec::new(), array_elems: Some(elements), closure_env: None, coroutine: None };
@ -128,6 +130,7 @@ impl Heap {
}
/// Returns a shared reference to the coroutine data for the given handle, if it is a Coroutine.
#[cfg(test)]
pub fn coroutine_data(&self, r: HeapRef) -> Option<&CoroutineData> {
let idx = r.0 as usize;
self.objects.get(idx).and_then(|slot| slot.as_ref()).and_then(|obj| obj.coroutine.as_ref())
@ -158,8 +161,8 @@ impl Heap {
.map(|o| &mut o.header)
}
/// Internal: list inner `HeapRef` children of an object without allocating.
/// Note: GC mark no longer uses this helper; kept for potential diagnostics.
// Internal: list inner `HeapRef` children of an object without allocating.
// Note: GC mark no longer uses this helper; kept for potential diagnostics.
// fn children_of(&self, r: HeapRef) -> Box<dyn Iterator<Item = HeapRef> + '_> {
// let idx = r.0 as usize;
// if let Some(Some(o)) = self.objects.get(idx) {
@ -221,6 +224,7 @@ impl Heap {
}
/// Get the captured environment slice of a closure. Returns None if kind mismatch or invalid ref.
#[cfg(test)]
pub fn closure_env_slice(&self, r: HeapRef) -> Option<&[Value]> {
let idx = r.0 as usize;
let slot = self.objects.get(idx)?.as_ref()?;
@ -261,14 +265,14 @@ impl Heap {
ObjectKind::Array => {
if let Some(elems) = obj.array_elems.as_ref() {
for val in elems.iter() {
if let Value::HeapRef(child) = val {
if self.is_valid(*child) {
let marked = self
.header(*child)
.map(|h: &ObjectHeader| h.is_marked())
.unwrap_or(false);
if !marked { stack.push(*child); }
}
if let Value::HeapRef(child) = val
&& self.is_valid(*child)
{
let marked = self
.header(*child)
.map(|h: &ObjectHeader| h.is_marked())
.unwrap_or(false);
if !marked { stack.push(*child); }
}
}
}
@ -281,14 +285,14 @@ impl Heap {
if let Some(env) = obj.closure_env.as_ref() {
debug_assert_eq!(env.len(), env_len, "closure env len must match encoded env_len");
for val in env[..env_len].iter() {
if let Value::HeapRef(child) = val {
if self.is_valid(*child) {
let marked = self
.header(*child)
.map(|h: &ObjectHeader| h.is_marked())
.unwrap_or(false);
if !marked { stack.push(*child); }
}
if let Value::HeapRef(child) = val
&& self.is_valid(*child)
{
let marked = self
.header(*child)
.map(|h: &ObjectHeader| h.is_marked())
.unwrap_or(false);
if !marked { stack.push(*child); }
}
}
}
@ -296,14 +300,14 @@ impl Heap {
ObjectKind::Coroutine => {
if let Some(co) = obj.coroutine.as_ref() {
for val in co.stack.iter() {
if let Value::HeapRef(child) = val {
if self.is_valid(*child) {
let marked = self
.header(*child)
.map(|h: &ObjectHeader| h.is_marked())
.unwrap_or(false);
if !marked { stack.push(*child); }
}
if let Value::HeapRef(child) = val
&& self.is_valid(*child)
{
let marked = self
.header(*child)
.map(|h: &ObjectHeader| h.is_marked())
.unwrap_or(false);
if !marked { stack.push(*child); }
}
}
}
@ -333,7 +337,6 @@ impl Heap {
/// Current number of allocated (live) objects.
pub fn len(&self) -> usize { self.objects.iter().filter(|s| s.is_some()).count() }
pub fn is_empty(&self) -> bool { self.len() == 0 }
/// Enumerate handles of coroutines that are currently suspended (i.e., not running):
/// Ready or Sleeping. These must be treated as GC roots by the runtime so their
@ -341,14 +344,12 @@ impl Heap {
pub fn suspended_coroutine_handles(&self) -> Vec<HeapRef> {
let mut out = Vec::new();
for (idx, slot) in self.objects.iter().enumerate() {
if let Some(obj) = slot {
if obj.header.kind == ObjectKind::Coroutine {
if let Some(co) = &obj.coroutine {
if matches!(co.state, CoroutineState::Ready | CoroutineState::Sleeping) {
out.push(HeapRef(idx as u32));
}
}
}
if let Some(obj) = slot
&& obj.header.kind == ObjectKind::Coroutine
&& let Some(co) = &obj.coroutine
&& matches!(co.state, CoroutineState::Ready | CoroutineState::Sleeping)
{
out.push(HeapRef(idx as u32));
}
}
out

View File

@ -51,12 +51,15 @@
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub enum ObjectKind {
/// Reserved/unknown kind. Should not appear in valid allocations.
#[allow(dead_code)] // Kept for stable tag layout and persisted images, even if not constructed in this crate yet
Unknown = 0,
/// UTF-8 string. `payload_len` is the number of bytes.
#[allow(dead_code)] // Public/stable tag retained; construction may live in higher layers
String = 1,
/// Homogeneous array of VM values/handles. `payload_len` is element count.
#[allow(dead_code)] // Public/stable tag retained; constructed via Heap helpers in tests
Array = 2,
/// Compiled closure/function value.
@ -69,9 +72,11 @@ pub enum ObjectKind {
Closure = 3,
/// Byte buffer / blob. `payload_len` is the number of bytes.
#[allow(dead_code)] // Public/stable tag retained for future/host APIs
Bytes = 4,
/// User-defined/native host object. Payload shape is host-defined.
#[allow(dead_code)] // Reserved for host/native integrations
UserData = 5,
/// Coroutine object: suspended execution context with its own stack/frames.

View File

@ -42,11 +42,14 @@ impl Scheduler {
self.ready_queue.pop_front()
}
#[cfg(test)]
pub fn is_ready_empty(&self) -> bool { self.ready_queue.is_empty() }
#[cfg(test)]
pub fn ready_len(&self) -> usize { self.ready_queue.len() }
// ---------- Current tracking (no switching here) ----------
pub fn set_current(&mut self, coro: Option<HeapRef>) { self.current = coro; }
#[cfg(test)]
pub fn current(&self) -> Option<HeapRef> { self.current }
pub fn clear_current(&mut self) { self.current = None; }

View File

@ -208,10 +208,8 @@ impl Verifier {
}
// Coroutine safety: forbid YIELD when operand stack is not empty (minimal rule)
if let OpCode::Yield = instr.opcode {
if in_height != 0 {
return Err(VerifierError::InvalidYieldContext { pc: func_start + pc, height: in_height });
}
if let OpCode::Yield = instr.opcode && in_height != 0 {
return Err(VerifierError::InvalidYieldContext { pc: func_start + pc, height: in_height });
}
// Compute out types vector with closure-aware rules
@ -317,7 +315,7 @@ impl Verifier {
}
}
let _pushes_final = dynamic_pushes.unwrap_or_else(|| match instr.opcode {
let _pushes_final = dynamic_pushes.unwrap_or(match instr.opcode {
OpCode::MakeClosure => 1,
OpCode::CallClosure => {
// If we reached here, we handled it above and set dynamic_pushes
@ -340,14 +338,12 @@ impl Verifier {
});
}
if instr.opcode == OpCode::Ret {
if in_height != func.return_slots {
return Err(VerifierError::BadRetStackHeight {
pc: func_start + pc,
height: in_height,
expected: func.return_slots,
});
}
if instr.opcode == OpCode::Ret && in_height != func.return_slots {
return Err(VerifierError::BadRetStackHeight {
pc: func_start + pc,
height: in_height,
expected: func.return_slots,
});
}
// Propagate to successors

View File

@ -228,7 +228,7 @@ impl VirtualMachine {
// Resolve the entrypoint: empty (defaults to func 0), numeric func_idx, or symbol name.
let pc = if entrypoint.is_empty() {
program.functions.get(0).map(|f| f.code_offset as usize).unwrap_or(0)
program.functions.first().map(|f| f.code_offset as usize).unwrap_or(0)
} else if let Ok(func_idx) = entrypoint.parse::<usize>() {
program
.functions
@ -525,7 +525,7 @@ impl VirtualMachine {
.imm_u32()
.map_err(|e| LogicalFrameEndingReason::Panic(format!("{:?}", e)))?
as usize;
let val = self.pop().map_err(|e| LogicalFrameEndingReason::Panic(e))?;
let val = self.pop().map_err(LogicalFrameEndingReason::Panic)?;
match val {
Value::Boolean(false) => {
let func_start = self
@ -551,7 +551,7 @@ impl VirtualMachine {
.imm_u32()
.map_err(|e| LogicalFrameEndingReason::Panic(format!("{:?}", e)))?
as usize;
let val = self.pop().map_err(|e| LogicalFrameEndingReason::Panic(e))?;
let val = self.pop().map_err(LogicalFrameEndingReason::Panic)?;
match val {
Value::Boolean(true) => {
let func_start = self
@ -622,7 +622,7 @@ impl VirtualMachine {
// Pop args top-first, then reverse to logical order arg1..argN
let mut args: Vec<Value> = Vec::with_capacity(arg_count);
for _ in 0..arg_count {
args.push(self.pop().map_err(|e| LogicalFrameEndingReason::Panic(e))?);
args.push(self.pop().map_err(LogicalFrameEndingReason::Panic)?);
}
args.reverse();
@ -1040,7 +1040,7 @@ impl VirtualMachine {
_ => Err(OpError::Panic("Invalid types for MOD".into())),
})?,
OpCode::BoundToInt => {
let val = self.pop().map_err(|e| LogicalFrameEndingReason::Panic(e))?;
let val = self.pop().map_err(LogicalFrameEndingReason::Panic)?;
if let Value::Bounded(b) = val {
self.push(Value::Int64(b as i64));
} else {
@ -1050,13 +1050,13 @@ impl VirtualMachine {
}
}
OpCode::IntToBoundChecked => {
let val = self.pop().map_err(|e| LogicalFrameEndingReason::Panic(e))?;
let val = self.pop().map_err(LogicalFrameEndingReason::Panic)?;
let int_val = val.as_integer().ok_or_else(|| {
LogicalFrameEndingReason::Panic(
"Expected integer for INT_TO_BOUND_CHECKED".into(),
)
})?;
if int_val < 0 || int_val > 0xFFFF {
if !(0..=0xFFFF).contains(&int_val) {
return Err(self.trap(
TRAP_OOB,
OpCode::IntToBoundChecked as u16,
@ -1101,7 +1101,7 @@ impl VirtualMachine {
_ => Err(OpError::Panic("Invalid types for OR".into())),
})?,
OpCode::Not => {
let val = self.pop().map_err(|e| LogicalFrameEndingReason::Panic(e))?;
let val = self.pop().map_err(LogicalFrameEndingReason::Panic)?;
if let Value::Boolean(b) = val {
self.push(Value::Boolean(!b));
} else {
@ -1148,7 +1148,7 @@ impl VirtualMachine {
_ => Err(OpError::Panic("Invalid types for Shr".into())),
})?,
OpCode::Neg => {
let val = self.pop().map_err(|e| LogicalFrameEndingReason::Panic(e))?;
let val = self.pop().map_err(LogicalFrameEndingReason::Panic)?;
match val {
Value::Int32(a) => self.push(Value::Int32(a.wrapping_neg())),
Value::Int64(a) => self.push(Value::Int64(a.wrapping_neg())),

View File

@ -22,7 +22,7 @@ pub fn rng_from_seed(seed: u64) -> StdRng {
/// Convenience helper that returns a RNG with a fixed well-known seed.
pub fn deterministic_rng() -> StdRng {
rng_from_seed(0xC0FFEE_5EED)
rng_from_seed(0x00C0_FFEE_5EED)
}
/// Returns the next u64 from the provided RNG.

View File

@ -1,56 +0,0 @@
# PR-9.4 — Final Cleanup & Quality Sweep
## Briefing
This PR performs the final cleanup pass.
Goal: Zero warnings. No dead code. No outdated examples.
## Target
1. Remove dead modules/files.
2. Remove unused imports and code.
3. Eliminate compiler warnings.
4. Update outdated examples.
5. Remove stale TODOs referencing removed architecture.
Optional (if present):
* Enforce `cargo clippy` clean baseline.
* Ensure `rustfmt` compliance.
## Acceptance Checklist
* [ ] No dead code.
* [ ] Zero compiler warnings.
* [ ] Clippy clean (if configured).
* [ ] Examples reflect new baseline.
* [ ] No TODO referencing RC/HIP.
## Tests
* Full test suite passes.
* Clean build with warnings denied (if configured).
## Junie Instructions
You MAY:
* Remove unused code.
* Refactor minor clarity issues.
You MUST NOT:
* Introduce new features.
* Change runtime semantics.
If cleanup requires semantic change, STOP and split into new PR.
---
## Final Definition of Done
* Architecture documented clearly.
* Public API minimal and controlled.
* No temporary flags remain.
* Codebase clean, warning-free, and aligned with the new VM baseline.

View File

@ -1,26 +0,0 @@
# PROMETEU Test Cartridges
This directory contains example cartridges and test suites to validate the behavior of the PROMETEU runtime and development tools.
## Available Cartridges
### 🟩 [color-square-ts](color-square-ts)
A simple cartridge that demonstrates:
- System initialization.
- Rendering a colored square in the framebuffer.
- Basic execution loop.
## Cartridge Structure
A PROMETEU cartridge (in its unpacked form) generally consists of:
- `manifest.json`: Application metadata (ID, title, version, mode).
- `program.pbc`: Compiled bytecode for the PROMETEU VM.
- `assets/`: Resources such as tiles, sprites, and audio samples.
## How to use
You can run any of these cartridges using the main CLI:
```bash
prometeu run test-cartridges/<cartridge_name>
```

View File

@ -1,8 +0,0 @@
{
"kind": "File",
"imports": [],
"decls": [
30,
40
]
}

View File

@ -1,20 +0,0 @@
0000 PushConst U32(1)
0006 SetLocal U32(0)
000C GetLocal U32(0)
0012 GetLocal U32(0)
0018 SetLocal U32(1)
001E SetLocal U32(0)
0024 GetLocal U32(0)
002A GetLocal U32(1)
0030 Call U32(1)
0036 SetLocal U32(2)
003C FrameSync
003E Ret
0040 GetLocal U32(0)
0046 GetLocal U32(0)
004C GetLocal U32(1)
0052 Add
0054 Mul
0056 GetLocal U32(1)
005C Mul
005E Ret

View File

@ -1,6 +0,0 @@
{
"name": "canonical",
"version": "0.1.0",
"script_fe": "pbs",
"entry": "src/main/modules/main.pbs"
}

View File

@ -1,18 +0,0 @@
declare struct Vec2(x: int, y: int)
[
(x: int, y: int): (x, y) as default
(s: int): (s, s) as square
]
[[
ZERO: square(0)
]]
{
pub fn len(self: this): int {
return x * x + y * y;
}
}
fn frame(): void {
let zero = Vec2.ZERO;
let zz = zero.len();
}

View File

@ -1,6 +0,0 @@
{
"name": "sdk",
"version": "0.1.0",
"script_fe": "pbs",
"kind": "lib"
}

View File

@ -1,8 +0,0 @@
pub declare struct Color(raw: bounded)
[[
BLACK: Color(0b),
WHITE: Color(65535b),
RED: Color(63488b),
GREEN: Color(2016b),
BLUE: Color(31b)
]]

View File

@ -1,3 +0,0 @@
pub declare contract Gfx host {
fn clear(color: Color): void;
}

View File

@ -1,6 +0,0 @@
pub declare struct Button(
pressed: bool,
released: bool,
down: bool,
hold_frames: bounded
)

View File

@ -1,20 +0,0 @@
pub declare contract Pad host {
fn up(): Button;
fn down(): Button;
fn left(): Button;
fn right(): Button;
fn a(): Button;
fn b(): Button;
fn x(): Button;
fn y(): Button;
fn l(): Button;
fn r(): Button;
fn start(): Button;
fn select(): Button;
}
pub declare contract Touch host {
fn screen_x(): int;
fn screen_y(): int;
fn finger(): Button;
}

View File

@ -1,48 +0,0 @@
// Injeção pelo hardware
declare contract LogHost host {
fn write(level: int, msg: string): void;
fn writeTag(level: int, tag: int, msg: string): void;
}
// exposicao do modulo, com sugar sintatico, nada injetado aqui
pub service Log {
fn trace(msg: string): void {
LogHost.write(0, msg);
}
fn trace(tag: int, msg: string): void {
LogHost.writeTag(0, tag, msg);
}
fn debug(msg: string): void {
LogHost.write(1, msg);
}
fn debug(tag: int, msg: string): void {
LogHost.writeTag(1, tag, msg);
}
fn info(msg: string): void {
LogHost.write(2, msg);
}
fn info(tag: int, msg: string): void {
LogHost.writeTag(2, tag, msg);
}
fn warn(msg: string): void {
LogHost.write(3, msg);
}
fn warn(tag: int, msg: string): void {
LogHost.writeTag(3, tag, msg);
}
fn err(msg: string): void {
LogHost.write(4, msg);
}
fn err(tag: int, msg: string): void {
LogHost.writeTag(4, tag, msg);
}
}

View File

@ -1,41 +0,0 @@
{
"magic": "PMTU",
"cartridge_version": 1,
"app_id": 1,
"title": "Test 1",
"app_version": "0.1.0",
"app_mode": "Game",
"entrypoint": "frame",
"asset_table": [
{
"asset_id": 0,
"asset_name": "bgm_music",
"bank_type": "SOUNDS",
"offset": 0,
"size": 88200,
"decoded_size": 88200,
"codec": "RAW",
"metadata": {
"sample_rate": 44100
}
},
{
"asset_id": 1,
"asset_name": "mouse_cursor",
"bank_type": "TILES",
"offset": 88200,
"size": 2304,
"decoded_size": 2304,
"codec": "RAW",
"metadata": {
"tile_size": 16,
"width": 16,
"height": 16
}
}
],
"preload": [
{ "asset_name": "bgm_music", "slot": 0 },
{ "asset_name": "mouse_cursor", "slot": 1 }
]
}

View File

@ -1,11 +0,0 @@
{
"name": "test01",
"version": "0.1.0",
"script_fe": "pbs",
"kind": "app",
"entry": "src/main/modules/main.pbs",
"out": "build/program.pbc",
"dependencies": {
"sdk": "../sdk"
}
}

View File

@ -1,7 +0,0 @@
#!/bin/zsh
set -e
sdk/prometeu build .
cp build/program.pbc cartridge/program.pbc
sdk/prometeu run cartridge

View File

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

View File

@ -1,3 +0,0 @@
{
"prometeuPbs.serverPath": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/target/debug/prometeu-lsp --studio"
}

View File

@ -1,66 +0,0 @@
import { Color, Gfx } from "@sdk:gfx";
import { Pad, Touch } from "@sdk:input";
import { Log } from "@sdk:log";
declare struct Vec2(x: int, y: int)
[
(x: int, y: int): (x, y) as default { }
(s: int): (s, s) as square { }
]
[[
ZERO: square(0)
]]
{
fn getX(self: this): int {
return x;
}
fn getY(self: this): int {
return y;
}
}
fn add(a: int, b: int): int {
return a + b;
}
fn is_higher(a: int, b: int): bool {
let c: int = a + b;
return c >= 30;
}
fn add2(a: int, b: int): int {
let c = add(a, b);
return c;
}
fn frame(): void {
let zero = Vec2.ZERO;
let zz = add2(zero.getX(), zero.getY());
// 1. Locals & Arithmetic
let x = 10;
let y = 20;
let z = add(x, y);
// 2. Control Flow (if)
if z == 30 {
// 3. Syscall Clear
Gfx.clear(Color.GREEN);
} else {
Gfx.clear(Color.RED);
}
// 4. Input Snapshot & Nested Member Access
let pad_a = Pad.a();
let touch_f = Touch.finger();
let is_pressed = pad_a.down || touch_f.down;
if is_pressed {
Gfx.clear(Color.BLUE);
}
if Pad.b().pressed {
Log.debug("B Pressed");
Gfx.clear(Color.RED);
}
}