M Cargo.lock => Cargo.lock +10 -10
@@ 1681,9 1681,9 @@ dependencies = [
[[package]]
name = "bytemuck_derive"
-version = "1.9.2"
+version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2ff22c2722516255d1823ce3cc4bc0b154dbc9364be5c905d6baa6eccbbc8774"
+checksum = "7ecc273b49b3205b83d648f0690daa588925572cc5063745bfe547fe7ec8e1a1"
dependencies = [
"proc-macro2",
"quote",
@@ 1927,9 1927,9 @@ dependencies = [
[[package]]
name = "clap"
-version = "4.5.33"
+version = "4.5.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2c80cae4c3350dd8f1272c73e83baff9a6ba550b8bfbe651b3c45b78cd1751e"
+checksum = "e958897981290da2a852763fe9cdb89cd36977a5d729023127095fa94d95e2ff"
dependencies = [
"clap_builder",
"clap_derive",
@@ 1937,9 1937,9 @@ dependencies = [
[[package]]
name = "clap_builder"
-version = "4.5.33"
+version = "4.5.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0123e386f691c90aa228219b5b1ee72d465e8e231c79e9c82324f016a62a741c"
+checksum = "83b0f35019843db2160b5bb19ae09b4e6411ac33fc6a712003c33e03090e2489"
dependencies = [
"anstream",
"anstyle",
@@ 2835,9 2835,9 @@ dependencies = [
[[package]]
name = "event-listener-strategy"
-version = "0.5.3"
+version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c3e4e0dd3673c1139bf041f3008816d9cf2946bbfac2945c09e523b8d7b05b2"
+checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93"
dependencies = [
"event-listener 5.4.0",
"pin-project-lite",
@@ 4956,9 4956,9 @@ dependencies = [
[[package]]
name = "once_cell"
-version = "1.21.1"
+version = "1.21.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc"
+checksum = "c2806eaa3524762875e21c3dcd057bc4b7bfa01ce4da8d46be1cd43649e1cc6b"
[[package]]
name = "oorandom"
M crates/api/src/routes/sign_save.rs => crates/api/src/routes/sign_save.rs +2 -2
@@ 24,7 24,7 @@ use actix_web::{
use log::error;
use serde::{Deserialize, Serialize};
use starkingdoms_common::{
- __noverify__unpack_savefile, pack_savefile, unpack_savefile, PartType, SaveModule,
+ __noverify_unpack_savefile, pack_savefile, unpack_savefile, PartType, SaveModule,
};
use std::collections::HashMap;
use std::hash::Hash;
@@ 63,7 63,7 @@ pub async fn sign_save_req(
state: Data<AppState>,
) -> JsonAPIResponse<SignSaveResponse> {
let old_save = handle_error!(unpack_savefile(&state.key_raw, req.old_save.clone()));
- let new_save = handle_error!(__noverify__unpack_savefile(req.new_partial.clone()));
+ let new_save = handle_error!(__noverify_unpack_savefile(req.new_partial.clone()));
// ensure part counts are the same
let mut part_counts_old: HashMap<PartType, u64> = HashMap::new();
R crates/client/src/shaders/fragment.glsl => crates/client/src/assets/shaders/fragment.glsl +0 -0
R crates/client/src/shaders/vertex.glsl => crates/client/src/assets/shaders/vertex.glsl +0 -0
R crates/client/src/assets/autoplr_cfg.svg => crates/client/src/assets/textures/autoplr_cfg.svg +0 -0
R crates/client/src/assets/autoplr_error.svg => crates/client/src/assets/textures/autoplr_error.svg +0 -0
R crates/client/src/assets/autoplr_on.svg => crates/client/src/assets/textures/autoplr_on.svg +0 -0
R crates/client/src/assets/cargo_off.svg => crates/client/src/assets/textures/cargo_off.svg +0 -0
R crates/client/src/assets/cargo_on.svg => crates/client/src/assets/textures/cargo_on.svg +0 -0
R crates/client/src/assets/chassis.svg => crates/client/src/assets/textures/chassis.svg +0 -0
R crates/client/src/assets/earth.svg => crates/client/src/assets/textures/earth.svg +0 -0
R crates/client/src/assets/earth_icon.svg => crates/client/src/assets/textures/earth_icon.svg +0 -0
R crates/client/src/assets/ecothruster_on.svg => crates/client/src/assets/textures/ecothruster_on.svg +0 -0
R crates/client/src/assets/editor_direction.svg => crates/client/src/assets/textures/editor_direction.svg +0 -0
R crates/client/src/assets/f.png => crates/client/src/assets/textures/f.png +0 -0
R crates/client/src/assets/happy-tree.png => crates/client/src/assets/textures/happy-tree.png +0 -0
R crates/client/src/assets/hearty.svg => crates/client/src/assets/textures/hearty.svg +0 -0
R crates/client/src/assets/hearty_ferris.svg => crates/client/src/assets/textures/hearty_ferris.svg +0 -0
R crates/client/src/assets/hearty_party.svg => crates/client/src/assets/textures/hearty_party.svg +0 -0
R crates/client/src/assets/hub_off.svg => crates/client/src/assets/textures/hub_off.svg +0 -0
R crates/client/src/assets/hub_on.svg => crates/client/src/assets/textures/hub_on.svg +0 -0
R crates/client/src/assets/jupiter.svg => crates/client/src/assets/textures/jupiter.svg +0 -0
R crates/client/src/assets/landingleg.svg => crates/client/src/assets/textures/landingleg.svg +0 -0
R crates/client/src/assets/landingthruster_off.svg => crates/client/src/assets/textures/landingthruster_off.svg +0 -0
R crates/client/src/assets/landingthruster_on.svg => crates/client/src/assets/textures/landingthruster_on.svg +0 -0
R crates/client/src/assets/mars.svg => crates/client/src/assets/textures/mars.svg +0 -0
R crates/client/src/assets/mars_icon.svg => crates/client/src/assets/textures/mars_icon.svg +0 -0
R crates/client/src/assets/mercury_NEEDS_4_1_1.svg => crates/client/src/assets/textures/mercury_NEEDS_4_1_1.svg +0 -0
R crates/client/src/assets/missing.svg => crates/client/src/assets/textures/missing.svg +0 -0
R crates/client/src/assets/moon.svg => crates/client/src/assets/textures/moon.svg +0 -0
R crates/client/src/assets/moon_icon.svg => crates/client/src/assets/textures/moon_icon.svg +0 -0
R crates/client/src/assets/powerhub_off.svg => crates/client/src/assets/textures/powerhub_off.svg +0 -0
R crates/client/src/assets/powerhub_on.svg => crates/client/src/assets/textures/powerhub_on.svg +0 -0
R crates/client/src/assets/starfield.svg => crates/client/src/assets/textures/starfield.svg +0 -0
R crates/client/src/assets/starfield_dim.svg => crates/client/src/assets/textures/starfield_dim.svg +0 -0
R crates/client/src/assets/starfield_transp.svg => crates/client/src/assets/textures/starfield_transp.svg +0 -0
R crates/client/src/assets/sun.svg => crates/client/src/assets/textures/sun.svg +0 -0
R crates/client/src/assets/sun_rings.svg => crates/client/src/assets/textures/sun_rings.svg +0 -0
R crates/client/src/assets/superthruster_off.svg => crates/client/src/assets/textures/superthruster_off.svg +0 -0
R crates/client/src/assets/superthruster_on.svg => crates/client/src/assets/textures/superthruster_on.svg +0 -0
R crates/client/src/assets/thruster_off.svg => crates/client/src/assets/textures/thruster_off.svg +0 -0
R crates/client/src/assets/thruster_on.svg => crates/client/src/assets/textures/thruster_on.svg +0 -0
R crates/client/src/assets/trackindicator.svg => crates/client/src/assets/textures/trackindicator.svg +0 -0
R crates/client/src/assets/uv.png => crates/client/src/assets/textures/uv.png +0 -0
R crates/client/src/assets/venus.svg => crates/client/src/assets/textures/venus.svg +0 -0
M crates/client/src/components.rs => crates/client/src/components.rs +1 -1
@@ 16,7 16,7 @@ pub struct Transform {
#[derive(Resource, Debug)]
pub struct PlayerResources {
pub fuel_amount: u32,
- pub fuel_max: u32
+ pub fuel_max: u32,
}
impl Transform {
M crates/client/src/lib.rs => crates/client/src/lib.rs +9 -8
@@ 1,12 1,14 @@
+use crate::components::PlayerResources;
use bevy_ecs::{event::Events, world::World};
-use components::{Camera, Chat, Menu, Part, Player, RecvPacket, SendPacket, Texture, Transform};
-use nalgebra::{Rotation2, Rotation3, Scale2, Scale3, Translation2, Translation3, Vector3};
-use networking::ws::Ws;
-use rendering::{assets::Assets, App};
-use starkingdoms_common::packet::Packet;
+use components::{Camera, Chat, Part, Player, RecvPacket, SendPacket, Texture, Transform};
+use nalgebra::{Rotation2, Scale3, Translation3};
+use platform::websocket::Ws;
+use crate::networking::websocket::Websocket;
+use platform::assets::Assets;
+use rendering::assets::AssetLoader;
+use rendering::App;
use tracing::info;
use winit::event_loop::{ControlFlow, EventLoop};
-use crate::components::PlayerResources;
#[cfg(target_arch = "wasm32")]
#[path = "wasm/mod.rs"]
@@ 50,8 52,7 @@ pub fn start() {
fuel_max: 0,
});
world.insert_resource(Chat {
- messages: vec![
- ],
+ messages: vec![],
textbox: String::new(),
});
R crates/client/src/rendering/assets_native.rs => crates/client/src/native/assets.rs +1 -1
@@ 18,7 18,7 @@ impl Assets {
}
pub fn get(&self, local_path: impl Into<String>) -> Option<ImgData> {
let local_path = local_path.into();
- let bytes = std::fs::read(format!("src/assets/{}", local_path)).unwrap();
+ let bytes = std::fs::read(format!("src/assets/textures/{}", local_path)).unwrap();
if local_path.ends_with(".svg") {
let opt = usvg::Options {
default_size: usvg::Size::from_wh(20.0, 20.0).unwrap(),
M crates/client/src/native/mod.rs => crates/client/src/native/mod.rs +3 -0
@@ 1,3 1,6 @@
+pub mod assets;
+pub mod websocket;
+
/// --- IMPORTANT: THIS IS A DUAL TARGET CRATE ---
/// THIS WILL ONLY EXECUTE ON NATIVE
/// DO ONLY PLATFORM SPECIFIC INITIALIZATION HERE
R crates/client/src/networking/ws_native.rs => crates/client/src/native/websocket.rs +8 -10
@@ 7,13 7,11 @@ use bevy_ecs::system::Resource;
use crossbeam::channel::{unbounded, Receiver, Sender};
use starkingdoms_common::packet::{MsgFromError, Packet};
use tungstenite::{connect, stream::MaybeTlsStream, Message, WebSocket};
-
-pub trait PacketMessageConvert {
- fn from_message(value: &Message) -> Result<Packet, MsgFromError>;
- fn into_message(&self) -> Message;
-}
+use crate::networking::websocket::{PacketMessageConvert, Websocket};
impl PacketMessageConvert for Packet {
+ type M = Message;
+
fn from_message(value: &Message) -> Result<Packet, MsgFromError> {
match value {
Message::Text(s) => serde_json::from_str(s).map_err(MsgFromError::JSONError),
@@ 24,7 22,7 @@ impl PacketMessageConvert for Packet {
}
}
}
- fn into_message(&self) -> Message {
+ fn as_message(&self) -> Message {
Message::Text(
serde_json::to_string(self)
.expect("failed to serialize packet to json")
@@ 40,8 38,8 @@ pub struct Ws {
pub receiver: Receiver<Packet>,
packet_receiver: Receiver<Packet>,
}
-impl Ws {
- pub fn new() -> Self {
+impl Websocket for Ws {
+ fn new() -> Self {
let (socket, _) = connect("ws://localhost:3000").expect("Failed to connect to server");
let socket = Arc::new(Mutex::new(socket));
let (packet_sender, receiver) = unbounded();
@@ 68,11 66,11 @@ impl Ws {
packet_receiver,
}
}
- pub fn send_packet(&mut self, packet: &Packet) {
+ fn send_packet(&mut self, packet: Packet) {
self.socket
.lock()
.unwrap()
- .send(packet.into_message())
+ .send(packet.as_message())
.expect("Couldn't send packet to server");
}
}
M crates/client/src/networking/mod.rs => crates/client/src/networking/mod.rs +15 -20
@@ 6,17 6,15 @@ use bevy_ecs::{
query::{QuerySingleError, With},
world::World,
};
-use nalgebra::{Rotation2, Scale2, Scale3, Translation3};
+use nalgebra::{Rotation2, Scale3, Translation3};
use starkingdoms_common::{packet::Packet, PartType, PlanetType};
-use crate::components::{Camera, Chat, Menu, Part, Planet, Player, PlayerResources, RecvPacket, SendPacket, ServerId, SpriteBundle, Texture, Transform};
+use crate::components::{
+ Camera, Chat, Menu, Part, Player, PlayerResources, RecvPacket, SendPacket, ServerId,
+ SpriteBundle, Texture, Transform,
+};
-#[cfg(target_arch = "wasm32")]
-#[path = "ws_wasm.rs"]
-pub mod ws;
-#[cfg(not(target_arch = "wasm32"))]
-#[path = "ws_native.rs"]
-pub mod ws;
+pub mod websocket;
fn texture_name(part_type: PartType, attached: bool) -> String {
use PartType::*;
@@ 45,7 43,7 @@ fn texture_name(part_type: PartType, attached: bool) -> String {
pub fn process_packets(
world: &mut World,
- send_packet_events: &mut Events<SendPacket>,
+ _send_packet_events: &mut Events<SendPacket>,
recv_packet_events: &mut Events<RecvPacket>,
planet_types: &mut HashMap<PlanetType, (Entity, u32)>,
) {
@@ 76,7 74,7 @@ pub fn process_packets(
));
}
}
- SpawnPlayer { id, username } => {
+ SpawnPlayer { id, .. } => {
// username sync, eventually
world.spawn((
Transform {
@@ 112,10 110,10 @@ pub fn process_packets(
let server_id = match player_query.get_single(world) {
Ok(player) => player,
Err(e) => match e {
- QuerySingleError::NoEntities(s) => {
+ QuerySingleError::NoEntities(_) => {
continue;
}
- QuerySingleError::MultipleEntities(s) => {
+ QuerySingleError::MultipleEntities(_) => {
panic!("There should never multiple players marked as players");
}
},
@@ 130,7 128,7 @@ pub fn process_packets(
world
.query::<(Entity, &ServerId, &mut Transform, &mut Texture, &mut Part)>(
);
- for (entity, server_id, mut transform, mut texture, mut bevy_part) in
+ for (_, server_id, mut transform, mut texture, mut bevy_part) in
part_query.iter_mut(world)
{
if server_id.0 == *id {
@@ 151,7 149,6 @@ pub fn process_packets(
}
PlanetPositions { planets } => {
for (server_id, planet) in planets {
- let mut planet_query = world.query_filtered::<&mut Transform, With<Planet>>();
if !planet_types.contains_key(&planet.planet_type) {
let entity = world.spawn(SpriteBundle {
transform: Transform {
@@ 195,10 192,7 @@ pub fn process_packets(
}
}
}
- EnergyUpdate {
- amount,
- max,
- } => {
+ EnergyUpdate { amount, max } => {
let mut r = world.resource_mut::<PlayerResources>();
r.fuel_amount = *amount;
r.fuel_max = *max;
@@ 215,9 209,10 @@ pub fn process_packets(
world.entity_mut(id).insert(Menu);
}
}
- Message { message_type, actor, content } => {
+ Message { actor, content, .. } => {
let mut chat = world.get_resource_mut::<Chat>().unwrap();
- chat.messages.push(format!("{}: {}", actor.clone(), content.clone()));
+ chat.messages
+ .push(format!("{}: {}", actor.clone(), content.clone()));
}
PlayerLeave { id } => {
let mut part_query = world.query_filtered::<(Entity, &ServerId), With<Part>>();
A crates/client/src/networking/websocket.rs => crates/client/src/networking/websocket.rs +13 -0
@@ 0,0 1,13 @@
+use starkingdoms_common::packet::{MsgFromError, Packet};
+
+pub trait Websocket {
+ fn new() -> Self;
+ fn send_packet(&mut self, packet: Packet);
+}
+
+pub trait PacketMessageConvert {
+ type M;
+
+ fn from_message(value: &Self::M) -> Result<Packet, MsgFromError>;
+ fn as_message(&self) -> Self::M;
+}<
\ No newline at end of file
A crates/client/src/rendering/assets.rs => crates/client/src/rendering/assets.rs +28 -0
@@ 0,0 1,28 @@
+use std::fmt::Display;
+
+#[derive(Debug, Clone)]
+pub enum AssetError {
+ AssetNotFound,
+ ResponseNotOk(u16),
+}
+impl Display for AssetError {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ match self {
+ AssetError::AssetNotFound => write!(f, "Asset not found"),
+ AssetError::ResponseNotOk(code) => write!(f, "Server response was not ok {}", code),
+ }
+ }
+}
+impl std::error::Error for AssetError {}
+
+#[derive(Debug, Clone)]
+pub struct ImgData {
+ pub bytes: Vec<u8>,
+ pub width: u32,
+ pub height: u32,
+}
+
+pub trait AssetLoader {
+ fn new() -> Self;
+ fn get(&self, local_path: impl Into<String>) -> Option<ImgData>;
+}
M crates/client/src/rendering/mod.rs => crates/client/src/rendering/mod.rs +48 -39
@@ 2,12 2,10 @@ use std::collections::HashMap;
use std::num::NonZeroU32;
use std::sync::Arc;
-use assets::Assets;
use bevy_ecs::entity::Entity;
use bevy_ecs::event::Events;
use bevy_ecs::query::With;
use bevy_ecs::world::World;
-use egui::{Label, ProgressBar};
use egui_glow::EguiGlow;
use glow::{HasContext, PixelUnpackData};
#[cfg(not(target_arch = "wasm32"))]
@@ 21,7 19,7 @@ use glutin::{
};
#[cfg(not(target_arch = "wasm32"))]
use glutin_winit::{DisplayBuilder, GlWindow};
-use nalgebra::{Matrix4, Scale3, Translation2, Translation3, Vector3, Vector4};
+use nalgebra::{Scale3, Translation3, Vector3};
use starkingdoms_common::packet::{ButtonType, Packet};
use starkingdoms_common::PlanetType;
#[cfg(target_arch = "wasm32")]
@@ 35,24 33,17 @@ use winit::keyboard::{KeyCode, PhysicalKey};
#[cfg(target_arch = "wasm32")]
use winit::platform::web::{WindowAttributesExtWebSys, WindowExtWebSys};
use winit::{
- application::ApplicationHandler,
- dpi::LogicalSize,
- event::WindowEvent,
- event_loop::ActiveEventLoop,
- raw_window_handle::HasWindowHandle,
- window::{Window, WindowAttributes},
+ application::ApplicationHandler, dpi::LogicalSize, event::WindowEvent,
+ event_loop::ActiveEventLoop, raw_window_handle::HasWindowHandle, window::Window,
};
use crate::components::{Camera, Menu, Player, RecvPacket, SendPacket, Texture, Transform};
use crate::networking::process_packets;
-use crate::networking::ws::Ws;
+use crate::platform::websocket::Ws;
use crate::ui::{draw_ui, init_ui};
+use assets::AssetLoader;
+use crate::networking::websocket::Websocket;
-#[cfg(not(target_arch = "wasm32"))]
-#[path = "assets_native.rs"]
-pub mod assets;
-#[cfg(target_arch = "wasm32")]
-#[path = "assets_wasm.rs"]
pub mod assets;
#[derive(Default)]
@@ 223,12 214,12 @@ impl ApplicationHandler for App {
let shaders = [
(
"vertex",
- include_str!("../shaders/vertex.glsl"),
+ include_str!("../assets/shaders/vertex.glsl"),
glow::VERTEX_SHADER,
),
(
"fragment",
- include_str!("../shaders/fragment.glsl"),
+ include_str!("../assets/shaders/fragment.glsl"),
glow::FRAGMENT_SHADER,
),
];
@@ 341,7 332,7 @@ impl ApplicationHandler for App {
fn window_event(
&mut self,
event_loop: &ActiveEventLoop,
- window_id: winit::window::WindowId,
+ _window_id: winit::window::WindowId,
event: winit::event::WindowEvent,
) {
let event_response = self
@@ 491,9 482,10 @@ impl ApplicationHandler for App {
self.recv_packet_events.send(RecvPacket(packet));
}
#[cfg(not(target_arch = "wasm32"))]
- for packet in ws.receiver.iter() {
+ while let Ok(packet) = ws.receiver.try_recv() {
self.recv_packet_events.send(RecvPacket(packet));
}
+
self.send_packet_events.update();
self.recv_packet_events.update();
@@ 504,11 496,10 @@ impl ApplicationHandler for App {
&mut self.planet_types,
);
- let window = self.window.as_ref().unwrap();
let gl = self.gl.as_ref().unwrap();
- let mut player = self.world.query_filtered::<&Transform, With<Player>>();
- let player = player.single(&self.world);
+ let player = self.world.query_filtered::<&Transform, With<Player>>();
+
self.egui_glow
.as_mut()
.unwrap()
@@ 559,36 550,54 @@ impl ApplicationHandler for App {
gl.uniform_matrix_4_f32_slice(view_loc.as_ref(), true, view);
if !self.textures.contains_key("starfield.svg") {
- let assets = self.world.resource::<Assets>();
+ let assets = self.world.resource::<crate::platform::assets::Assets>();
match assets.get("starfield.svg") {
Some(image) => {
- let texture_object = gl.create_texture().expect("Failed to create texture object");
+ let texture_object = gl
+ .create_texture()
+ .expect("Failed to create texture object");
gl.bind_texture(glow::TEXTURE_2D, Some(texture_object));
- gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_MIN_FILTER, glow::LINEAR_MIPMAP_LINEAR as i32);
- gl.tex_image_2d(glow::TEXTURE_2D, 0, glow::RGBA as i32,
- image.width as i32, image.height as i32, 0, glow::RGBA,
- glow::UNSIGNED_BYTE, PixelUnpackData::Slice(Some(&image.bytes)));
+ gl.tex_parameter_i32(
+ glow::TEXTURE_2D,
+ glow::TEXTURE_MIN_FILTER,
+ glow::LINEAR_MIPMAP_LINEAR as i32,
+ );
+ gl.tex_image_2d(
+ glow::TEXTURE_2D,
+ 0,
+ glow::RGBA as i32,
+ image.width as i32,
+ image.height as i32,
+ 0,
+ glow::RGBA,
+ glow::UNSIGNED_BYTE,
+ PixelUnpackData::Slice(Some(&image.bytes)),
+ );
gl.generate_mipmap(glow::TEXTURE_2D);
- self.textures.insert("starfield.svg".to_string(), texture_object);
+ self.textures
+ .insert("starfield.svg".to_string(), texture_object);
}
None => {}
}
}
if self.textures.contains_key("starfield.svg") {
- gl.bind_texture(glow::TEXTURE_2D, self.textures.get("starfield.svg").copied());
+ gl.bind_texture(
+ glow::TEXTURE_2D,
+ self.textures.get("starfield.svg").copied(),
+ );
let camera = self.world.get_resource::<Camera>().unwrap();
- let x = -(camera.x + camera.x.signum() * 200.0)
- + camera.x % 400.0;
- let y = -(camera.y + camera.y.signum() * 200.0)
- + camera.y % 400.0;
+ let x = -(camera.x + camera.x.signum() * 200.0) + camera.x % 400.0;
+ let y = -(camera.y + camera.y.signum() * 200.0) + camera.y % 400.0;
let x_range = camera.width as f32 / camera.zoom / 400.0;
let y_range = camera.height as f32 / camera.zoom / 400.0;
- for i in ((-x_range/2.0) as i32 - 1)..=((x_range/2.0) as i32 + 1) {
- for j in ((-y_range/2.0) as i32 - 1)..=((y_range/2.0) as i32 + 1) {
- let model = Translation3::new(x + (i*400) as f32, y + (j*400) as f32, 0.0).to_homogeneous()
- * Scale3::new(200.0, 200.0, 1.0).to_homogeneous();
+ for i in ((-x_range / 2.0) as i32 - 1)..=((x_range / 2.0) as i32 + 1) {
+ for j in ((-y_range / 2.0) as i32 - 1)..=((y_range / 2.0) as i32 + 1) {
+ let model =
+ Translation3::new(x + (i * 400) as f32, y + (j * 400) as f32, 0.0)
+ .to_homogeneous()
+ * Scale3::new(200.0, 200.0, 1.0).to_homogeneous();
gl.uniform_matrix_4_f32_slice(model_loc.as_ref(), false, model.as_slice());
gl.draw_elements(glow::TRIANGLES, 6, glow::UNSIGNED_INT, 0);
}
@@ 597,7 606,7 @@ impl ApplicationHandler for App {
for (transform, texture) in sprites {
if !self.textures.contains_key(&texture.name) {
- let assets = self.world.resource::<Assets>();
+ let assets = self.world.resource::<crate::platform::assets::Assets>();
let image = match assets.get(texture.name.clone()) {
Some(t) => t,
None => continue,
M crates/client/src/ui/colors.rs => crates/client/src/ui/colors.rs +2 -1
@@ 1,5 1,6 @@
macro_rules! color {
($n:ident,rgb($r:expr, $g:expr, $b:expr)) => {
+ #[allow(dead_code)]
pub const $n: ::egui::Color32 = ::egui::Color32::from_rgb($r, $g, $b);
};
}
@@ 29,4 30,4 @@ color!(SURFACE_1, rgb(69, 71, 90));
color!(SURFACE_0, rgb(49, 50, 68));
color!(BASE, rgb(30, 30, 46));
color!(MANTLE, rgb(24, 24, 37));
-color!(CRUST, rgb(17, 17, 27));>
\ No newline at end of file
+color!(CRUST, rgb(17, 17, 27));
M crates/client/src/ui/mod.rs => crates/client/src/ui/mod.rs +38 -22
@@ 3,14 3,14 @@ mod widgets;
use std::f32;
+use crate::components::{Camera, Chat, Menu, Player, PlayerResources, SendPacket, Transform};
+use crate::ui::widgets::{progress_bar, RichTextExt};
use bevy_ecs::entity::Entity;
use bevy_ecs::event::Events;
use bevy_ecs::prelude::With;
use bevy_ecs::world::World;
-use egui::{Align, Align2, CornerRadius, CursorIcon, Layout, Margin, Order, ProgressBar, RichText, Shadow, Stroke, Visuals};
+use egui::{Align, Align2, CursorIcon, Layout, Margin, Order, RichText, Shadow, Visuals};
use starkingdoms_common::packet::Packet;
-use crate::components::{Camera, Chat, Menu, Player, PlayerResources, SendPacket, Transform};
-use crate::ui::widgets::{progress_bar, RichTextExt};
pub fn init_ui(ctx: egui::Context) {
// set colors
@@ 19,7 19,6 @@ pub fn init_ui(ctx: egui::Context) {
let mut visuals = Visuals::default();
visuals.dark_mode = true;
-
// TODO(core): code_bg_colors
visuals.warn_fg_color = colors::YELLOW; // used for warning text
@@ 43,17 42,18 @@ pub fn init_ui(ctx: egui::Context) {
visuals.hyperlink_color = colors::BLUE;
-
-
visuals.widgets.noninteractive.fg_stroke.color = colors::TEXT; // standard text color
-
style.visuals = visuals;
ctx.set_style(style);
}
-pub fn draw_ui(ctx: &egui::Context, world: &mut World, send_packet_events: &mut Events<SendPacket>) {
+pub fn draw_ui(
+ ctx: &egui::Context,
+ world: &mut World,
+ send_packet_events: &mut Events<SendPacket>,
+) {
draw_status_bar(ctx, world);
draw_chat(ctx, world, send_packet_events);
draw_crafting(ctx, world);
@@ 71,11 71,14 @@ pub fn draw_status_bar(ctx: &egui::Context, world: &mut World) {
.order(Order::Foreground)
.anchor(Align2::CENTER_BOTTOM, [0.0, -5.0])
.show(ctx, |ui| {
-
ui.horizontal(|ui| {
ui.vertical(|ui| {
ui.label(RichText::new("Position:").stk_weak());
- ui.label(RichText::new(format!("{:.0}, {:.0}", player_position.translation.x / 10.0, player_position.translation.y / 10.0)))
+ ui.label(RichText::new(format!(
+ "{:.0}, {:.0}",
+ player_position.translation.x / 10.0,
+ player_position.translation.y / 10.0
+ )))
});
ui.add_space(8.0);
@@ 84,20 87,30 @@ pub fn draw_status_bar(ctx: &egui::Context, world: &mut World) {
ui.horizontal(|ui| {
ui.label(RichText::new("Fuel:").stk_weak());
ui.with_layout(Layout::right_to_left(Align::Center), |ui| {
- ui.label(RichText::new(format!("{}/{} ({:.2}%)", player_resources.fuel_amount, player_resources.fuel_max, player_resources.fuel_amount as f32 / player_resources.fuel_max as f32 * 100.0)))
+ ui.label(RichText::new(format!(
+ "{}/{} ({:.2}%)",
+ player_resources.fuel_amount,
+ player_resources.fuel_max,
+ player_resources.fuel_amount as f32
+ / player_resources.fuel_max as f32
+ * 100.0
+ )))
});
-
});
- ui.add(
- progress_bar(player_resources.fuel_amount as f32 / player_resources.fuel_max as f32)
- );
+ ui.add(progress_bar(
+ player_resources.fuel_amount as f32 / player_resources.fuel_max as f32,
+ ));
})
});
});
}
-pub fn draw_chat(ctx: &egui::Context, world: &mut World, send_packet_events: &mut Events<SendPacket>) {
+pub fn draw_chat(
+ ctx: &egui::Context,
+ world: &mut World,
+ send_packet_events: &mut Events<SendPacket>,
+) {
let mut chat = world.get_resource_mut::<Chat>().unwrap();
egui::Window::new("Chat")
@@ 122,8 135,10 @@ pub fn draw_chat(ctx: &egui::Context, world: &mut World, send_packet_events: &mu
});
ui.horizontal(|ui| {
let output = egui::TextEdit::singleline(&mut chat.textbox).show(ui);
- if ui.button("Send").clicked() ||
- (ctx.input(|i| i.key_pressed(egui::Key::Enter)) && output.response.lost_focus()) {
+ if ui.button("Send").clicked()
+ || (ctx.input(|i| i.key_pressed(egui::Key::Enter))
+ && output.response.lost_focus())
+ {
send_packet_events.send(SendPacket(Packet::SendMessage {
target: None,
content: chat.textbox.clone(),
@@ 141,9 156,10 @@ pub fn draw_crafting(ctx: &egui::Context, world: &mut World) {
egui::Window::new("Crafting")
.id(format!("Crafting{}", entity.index()).into())
.pivot(Align2::LEFT_BOTTOM)
- .fixed_pos(((menu.translation.x + camera.x) * camera.zoom + camera.width as f32 / 2.0,
- (menu.translation.y + camera.y) * camera.zoom + camera.height as f32 / 2.0))
- .show(ctx, |ui| {
- });
+ .fixed_pos((
+ (menu.translation.x + camera.x) * camera.zoom + camera.width as f32 / 2.0,
+ (menu.translation.y + camera.y) * camera.zoom + camera.height as f32 / 2.0,
+ ))
+ .show(ctx, |ui| {});
}
}
M crates/client/src/ui/widgets.rs => crates/client/src/ui/widgets.rs +1 -1
@@ 13,4 13,4 @@ impl RichTextExt for RichText {
fn stk_weak(self) -> Self {
self.color(super::colors::OVERLAY_2)
}
-}>
\ No newline at end of file
+}
R crates/client/src/rendering/assets_wasm.rs => crates/client/src/wasm/assets.rs +5 -26
@@ 4,47 4,26 @@ use std::{
sync::{Arc, Mutex},
};
+use crate::rendering::assets::{AssetLoader, ImgData};
use bevy_ecs::system::Resource;
use image::EncodableLayout;
use poll_promise::Promise;
use resvg::{tiny_skia, usvg};
-#[derive(Debug, Clone)]
-pub enum AssetError {
- AssetNotFound,
- ResponseNotOk(u16),
-}
-impl Display for AssetError {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- match self {
- AssetError::AssetNotFound => write!(f, "Asset not found"),
- AssetError::ResponseNotOk(code) => write!(f, "Server response was not ok {}", code),
- }
- }
-}
-impl std::error::Error for AssetError {}
-
-#[derive(Debug, Clone)]
-pub struct ImgData {
- pub bytes: Vec<u8>,
- pub width: u32,
- pub height: u32,
-}
-
#[derive(Resource)]
pub struct Assets {
texture_promises: Arc<Mutex<HashMap<String, Promise<ImgData>>>>,
textures: Arc<Mutex<HashMap<String, ImgData>>>,
}
-impl Assets {
- pub fn new() -> Self {
+impl AssetLoader for Assets {
+ fn new() -> Self {
Assets {
textures: Arc::new(Mutex::new(HashMap::new())),
texture_promises: Arc::new(Mutex::new(HashMap::new())),
}
}
- pub fn get(&self, local_path: impl Into<String>) -> Option<ImgData> {
+ fn get(&self, local_path: impl Into<String>) -> Option<ImgData> {
let local_path = local_path.into();
let contains_texture = { self.textures.lock().unwrap().contains_key(&local_path) };
let contains_texture_promise = {
@@ 58,7 37,7 @@ impl Assets {
let request_promise = poll_promise::Promise::spawn_local(async move {
let window = web_sys::window().unwrap();
let request = ehttp::Request::get(format!(
- "{}/src/assets/{}",
+ "{}/src/assets/textures/{}",
window.location().origin().unwrap(),
local_path_clone
));
M crates/client/src/wasm/mod.rs => crates/client/src/wasm/mod.rs +3 -0
@@ 4,6 4,9 @@ use tracing_subscriber::prelude::*;
use tracing_web::{performance_layer, MakeWebConsoleWriter};
use wasm_bindgen::prelude::wasm_bindgen;
+pub mod assets;
+pub mod websocket;
+
/// --- IMPORTANT: THIS IS A DUAL TARGET CRATE ---
/// THIS WILL ONLY EXECUTE ON WEBASSEMBLY
/// DO ONLY PLATFORM SPECIFIC INITIALIZATION HERE
R crates/client/src/networking/ws_wasm.rs => crates/client/src/wasm/websocket.rs +4 -14
@@ 10,6 10,7 @@ use starkingdoms_common::packet::Packet;
use wasm_bindgen::{prelude::Closure, JsCast, JsValue};
use wasm_bindgen_futures::spawn_local;
use web_sys::{MessageEvent, WebSocket};
+use crate::networking::websocket::Websocket;
const PORT: u16 = 3000;
@@ 26,8 27,8 @@ pub struct Ws {
packet_receiver: UnboundedReceiver<Packet>,
}
-impl Ws {
- pub fn new() -> Self {
+impl Websocket for Ws {
+ fn new() -> Self {
let window = web_sys::window().unwrap();
/*let ws = WebSocket::new(&format!(
"ws://{}:{}",
@@ 80,18 81,7 @@ impl Ws {
packet_receiver,
}
}
- pub fn send_all_packets_from_channel(&mut self) {
- //for packet in self.packet_receiver.iter() {
- while let Ok(Some(packet)) = self.packet_receiver.try_next() {
- self.socket
- .0
- .send_with_str(
- &serde_json::to_string(&packet).expect("Couldn't convert packet to json"),
- )
- .expect("Couldn't send packet to server");
- }
- }
- pub fn send_packet(&mut self, packet: Packet) {
+ fn send_packet(&mut self, packet: Packet) {
let socket = self.socket.0.clone();
spawn_local(async move {
//while socket.ready_state() != 1 { }
M crates/common/src/lib.rs => crates/common/src/lib.rs +1 -1
@@ 110,7 110,7 @@ pub fn unpack_savefile(key: &[u8], file: String) -> Result<SaveData, Box<dyn Err
Ok(save_data)
}
-pub fn __noverify__unpack_savefile(file: String) -> Result<SaveData, Box<dyn Error>> {
+pub fn __noverify_unpack_savefile(file: String) -> Result<SaveData, Box<dyn Error>> {
// << reverse! <<
let savefile_bytes = base64::engine::general_purpose::STANDARD
.decode(file)
M crates/kabel/src/ast.rs => crates/kabel/src/ast.rs +7 -8
@@ 11,9 11,9 @@ pub enum ASTType {
// statements
Function(Name, Vec<Name>, Box<AST>), // name, args, block
- Return(Box<Option<AST>>), // expression
- Loop(Box<AST>), // block
- While(Box<AST>, Box<AST>), // condition, block
+ Return(Box<Option<AST>>), // expression
+ Loop(Box<AST>), // block
+ While(Box<AST>, Box<AST>), // condition, block
For(
Box<Option<AST>>,
Box<Option<AST>>,
@@ 22,10 22,10 @@ pub enum ASTType {
), // expr1, expr2, expr3, block
Break,
Continue,
- If(Box<AST>, Box<AST>, Box<Option<AST>>), // condition, block, else/else if
- Block(Vec<AST>), // statements
- Decl(Name, Box<AST>), // identifier, expression
- Expr(Box<AST>), // expr
+ If(Box<AST>, Box<AST>, Box<Option<AST>>), // condition, block, else/else if
+ Block(Vec<AST>), // statements
+ Decl(Name, Box<AST>), // identifier, expression
+ Expr(Box<AST>), // expr
// REMOVE LATER
Print(Box<AST>),
@@ 93,4 93,3 @@ pub enum LhsAssignType {
Ident(String),
Subscript(Box<AST>, Box<AST>),
}
-
M crates/kabel/src/codegen.rs => crates/kabel/src/codegen.rs +356 -140
@@ 1,4 1,10 @@
-use crate::{ast::{ASTType, BinOp, LhsAssign, LhsAssignType, Lit, Name, UnOp, AST}, codegen_binary, codegen_unary, extension::Extension, opcodes::OpCode, vm::{Function, Unit, Value, VM}};
+use crate::{
+ ast::{ASTType, BinOp, LhsAssign, LhsAssignType, Lit, Name, UnOp, AST},
+ codegen_binary, codegen_unary,
+ extension::Extension,
+ opcodes::OpCode,
+ vm::{Function, Unit, Value, VM},
+};
pub struct Codegen {
pub vm: VM,
@@ 10,8 16,7 @@ pub struct Codegen {
impl Codegen {
pub fn new(text: String) -> Self {
Codegen {
- vm: VM::new(Vec::new(), Vec::new(),
- Vec::new(), text),
+ vm: VM::new(Vec::new(), Vec::new(), Vec::new(), text),
scopes: vec![(ScopeType::Main, 0)],
break_stack: Vec::new(),
continue_stack: Vec::new(),
@@ 88,24 93,32 @@ impl Codegen {
self.vm.units.push(Unit::new_empty());
// add function to constant pool and add a load expression in its place
- let new_unit_ptr = self.vm.units.len()-1;
+ let new_unit_ptr = self.vm.units.len() - 1;
self.vm.variables.push(Value::Fun(Function {
unit_ptr: new_unit_ptr,
arity: args.len(),
}));
- self.scopes.last_mut().expect("codegen scopes vec was empty").1 += 1;
+ self.scopes
+ .last_mut()
+ .expect("codegen scopes vec was empty")
+ .1 += 1;
let old_unit_ptr = self.vm.unit_ptr;
let old_ip = self.vm.ip;
// set unit to write to
self.vm.unit_ptr = new_unit_ptr;
self.vm.ip = 0;
- self.vm.units[self.vm.unit_ptr].pool.push(Value::Fun(Function {
- unit_ptr: new_unit_ptr,
- arity: args.len(),
- }));
- self.scopes.last_mut().expect("codegen scopes vec was empty").1 += args.len();
-
+ self.vm.units[self.vm.unit_ptr]
+ .pool
+ .push(Value::Fun(Function {
+ unit_ptr: new_unit_ptr,
+ arity: args.len(),
+ }));
+ self.scopes
+ .last_mut()
+ .expect("codegen scopes vec was empty")
+ .1 += args.len();
+
if let ASTType::Block(ref stmts) = block.kind {
self.visit_block(&block, stmts.clone(), ScopeType::Function);
}
@@ 113,12 126,18 @@ impl Codegen {
Some(instr) => {
if *instr != <OpCode as Into<u8>>::into(OpCode::RET) {
self.vm.units[self.vm.unit_ptr].pool.push(Value::Null);
- self.vm.units[self.vm.unit_ptr].code.push(OpCode::LOAD.into());
- let loc = (self.vm.units[self.vm.unit_ptr].pool.len()-1) as u8;
+ self.vm.units[self.vm.unit_ptr]
+ .code
+ .push(OpCode::LOAD.into());
+ let loc = (self.vm.units[self.vm.unit_ptr].pool.len() - 1) as u8;
self.vm.units[self.vm.unit_ptr].code.push(loc);
- self.vm.units[self.vm.unit_ptr].code.push(OpCode::RET.into());
+ self.vm.units[self.vm.unit_ptr]
+ .code
+ .push(OpCode::RET.into());
if self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != block.end_line {
- self.vm.units[self.vm.unit_ptr].lines.push((block.end_line, 3));
+ self.vm.units[self.vm.unit_ptr]
+ .lines
+ .push((block.end_line, 3));
} else {
self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 3;
}
@@ 126,12 145,18 @@ impl Codegen {
}
None => {
self.vm.units[self.vm.unit_ptr].pool.push(Value::Null);
- self.vm.units[self.vm.unit_ptr].code.push(OpCode::LOAD.into());
- let loc = (self.vm.units[self.vm.unit_ptr].pool.len()-1) as u8;
+ self.vm.units[self.vm.unit_ptr]
+ .code
+ .push(OpCode::LOAD.into());
+ let loc = (self.vm.units[self.vm.unit_ptr].pool.len() - 1) as u8;
self.vm.units[self.vm.unit_ptr].code.push(loc);
- self.vm.units[self.vm.unit_ptr].code.push(OpCode::RET.into());
+ self.vm.units[self.vm.unit_ptr]
+ .code
+ .push(OpCode::RET.into());
if self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != block.end_line {
- self.vm.units[self.vm.unit_ptr].lines.push((block.end_line, 3));
+ self.vm.units[self.vm.unit_ptr]
+ .lines
+ .push((block.end_line, 3));
} else {
self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 3;
}
@@ 145,18 170,26 @@ impl Codegen {
self.visit(expr);
} else {
self.vm.units[self.vm.unit_ptr].pool.push(Value::Null);
- self.vm.units[self.vm.unit_ptr].code.push(OpCode::LOAD.into());
- let loc = (self.vm.units[self.vm.unit_ptr].pool.len()-1) as u8;
+ self.vm.units[self.vm.unit_ptr]
+ .code
+ .push(OpCode::LOAD.into());
+ let loc = (self.vm.units[self.vm.unit_ptr].pool.len() - 1) as u8;
self.vm.units[self.vm.unit_ptr].code.push(loc);
if self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != ast.end_line {
- self.vm.units[self.vm.unit_ptr].lines.push((ast.end_line, 2));
+ self.vm.units[self.vm.unit_ptr]
+ .lines
+ .push((ast.end_line, 2));
} else {
self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 2;
}
}
- self.vm.units[self.vm.unit_ptr].code.push(OpCode::RET.into());
+ self.vm.units[self.vm.unit_ptr]
+ .code
+ .push(OpCode::RET.into());
if self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != ast.end_line {
- self.vm.units[self.vm.unit_ptr].lines.push((ast.end_line, 1));
+ self.vm.units[self.vm.unit_ptr]
+ .lines
+ .push((ast.end_line, 1));
} else {
self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 1;
}
@@ 167,25 200,37 @@ impl Codegen {
let end_jmp = self.vm.units[self.vm.unit_ptr].code.len();
self.visit(condition.clone());
- self.vm.units[self.vm.unit_ptr].code.push(OpCode::JNE.into());
+ self.vm.units[self.vm.unit_ptr]
+ .code
+ .push(OpCode::JNE.into());
self.vm.units[self.vm.unit_ptr].code.push(0xFF); // placeholder
self.vm.units[self.vm.unit_ptr].code.push(0xFF); // placeholder
- let start_jmp_loc = self.vm.units[self.vm.unit_ptr].code.len()-2;
+ let start_jmp_loc = self.vm.units[self.vm.unit_ptr].code.len() - 2;
if self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != condition.end_line {
- self.vm.units[self.vm.unit_ptr].lines.push((condition.end_line, 3));
+ self.vm.units[self.vm.unit_ptr]
+ .lines
+ .push((condition.end_line, 3));
} else {
self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 3;
}
if let ASTType::Block(ref stmts) = block.kind {
self.visit_block(&block, stmts.clone(), ScopeType::Loop);
}
- self.vm.units[self.vm.unit_ptr].code.push(OpCode::JMP_UP.into());
- let current = self.vm.units[self.vm.unit_ptr].code.len()+2;
+ self.vm.units[self.vm.unit_ptr]
+ .code
+ .push(OpCode::JMP_UP.into());
+ let current = self.vm.units[self.vm.unit_ptr].code.len() + 2;
let current_to_start = current - end_jmp;
- self.vm.units[self.vm.unit_ptr].code.push(((current_to_start >> 8) & 0xFF) as u8);
- self.vm.units[self.vm.unit_ptr].code.push((current_to_start & 0xFF) as u8);
+ self.vm.units[self.vm.unit_ptr]
+ .code
+ .push(((current_to_start >> 8) & 0xFF) as u8);
+ self.vm.units[self.vm.unit_ptr]
+ .code
+ .push((current_to_start & 0xFF) as u8);
if self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != block.end_line {
- self.vm.units[self.vm.unit_ptr].lines.push((block.end_line, 3));
+ self.vm.units[self.vm.unit_ptr]
+ .lines
+ .push((block.end_line, 3));
} else {
self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 3;
}
@@ 195,15 240,23 @@ impl Codegen {
for loc in breaks {
self.patch_jump(loc, 0);
}
- let continues = self.continue_stack.pop().expect("continue stack empty on pop");
+ let continues = self
+ .continue_stack
+ .pop()
+ .expect("continue stack empty on pop");
for loc in continues {
let jump = loc - end_jmp + 2;
self.vm.units[self.vm.unit_ptr].code[loc] = ((jump >> 8) & 0xFF) as u8;
self.vm.units[self.vm.unit_ptr].code[loc + 1] = (jump & 0xFF) as u8;
}
}
- pub fn visit_for(&mut self, expr1: Option<AST>, expr2: Option<AST>,
- expr3: Option<AST>, block: AST) {
+ pub fn visit_for(
+ &mut self,
+ expr1: Option<AST>,
+ expr2: Option<AST>,
+ expr3: Option<AST>,
+ block: AST,
+ ) {
self.scopes.push((ScopeType::Other, 0));
self.break_stack.push(Vec::new());
@@ 216,12 269,16 @@ impl Codegen {
let mut start_jmp_loc = None;
if let Some(expr2) = expr2 {
self.visit(expr2.clone());
- self.vm.units[self.vm.unit_ptr].code.push(OpCode::JNE.into());
+ self.vm.units[self.vm.unit_ptr]
+ .code
+ .push(OpCode::JNE.into());
self.vm.units[self.vm.unit_ptr].code.push(0xFF); // placeholder
self.vm.units[self.vm.unit_ptr].code.push(0xFF); // placeholder
- start_jmp_loc = Some(self.vm.units[self.vm.unit_ptr].code.len()-2);
+ start_jmp_loc = Some(self.vm.units[self.vm.unit_ptr].code.len() - 2);
if self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != expr2.end_line {
- self.vm.units[self.vm.unit_ptr].lines.push((expr2.end_line, 3));
+ self.vm.units[self.vm.unit_ptr]
+ .lines
+ .push((expr2.end_line, 3));
} else {
self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 3;
}
@@ 229,7 286,10 @@ impl Codegen {
if let ASTType::Block(ref stmts) = block.kind {
self.visit_block(&block, stmts.clone(), ScopeType::Loop);
}
- let continues = self.continue_stack.pop().expect("continue stack empty on pop");
+ let continues = self
+ .continue_stack
+ .pop()
+ .expect("continue stack empty on pop");
for loc in continues {
/*let jump = loc - end_jmp + 2;
self.vm.units[self.vm.unit_ptr].code[loc] = ((jump >> 8) & 0xFF) as u8;
@@ 238,23 298,35 @@ impl Codegen {
}
if let Some(expr3) = expr3 {
self.visit(expr3);
- self.vm.units[self.vm.unit_ptr].code.push(OpCode::POP.into());
+ self.vm.units[self.vm.unit_ptr]
+ .code
+ .push(OpCode::POP.into());
self.vm.units[self.vm.unit_ptr].code.push(0x01);
if self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != block.end_line {
- self.vm.units[self.vm.unit_ptr].lines.push((block.end_line, 2));
+ self.vm.units[self.vm.unit_ptr]
+ .lines
+ .push((block.end_line, 2));
} else {
self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 2;
}
}
// write instruction to loop
- self.vm.units[self.vm.unit_ptr].code.push(OpCode::JMP_UP.into());
- let current = self.vm.units[self.vm.unit_ptr].code.len()+2;
+ self.vm.units[self.vm.unit_ptr]
+ .code
+ .push(OpCode::JMP_UP.into());
+ let current = self.vm.units[self.vm.unit_ptr].code.len() + 2;
let current_to_start = current - end_jmp;
- self.vm.units[self.vm.unit_ptr].code.push(((current_to_start >> 8) & 0xFF) as u8);
- self.vm.units[self.vm.unit_ptr].code.push((current_to_start & 0xFF) as u8);
+ self.vm.units[self.vm.unit_ptr]
+ .code
+ .push(((current_to_start >> 8) & 0xFF) as u8);
+ self.vm.units[self.vm.unit_ptr]
+ .code
+ .push((current_to_start & 0xFF) as u8);
if self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != block.end_line {
- self.vm.units[self.vm.unit_ptr].lines.push((block.end_line, 3));
+ self.vm.units[self.vm.unit_ptr]
+ .lines
+ .push((block.end_line, 3));
} else {
self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 3;
}
@@ 264,20 336,22 @@ impl Codegen {
self.patch_jump(loc, 0);
}
-
if let Some(loc) = start_jmp_loc {
self.patch_jump(loc, 0);
}
let (_scope_type, variables) = self.scopes.pop().expect("popped scope in block");
- self.vm.units[self.vm.unit_ptr].code.push(OpCode::POP.into());
+ self.vm.units[self.vm.unit_ptr]
+ .code
+ .push(OpCode::POP.into());
self.vm.units[self.vm.unit_ptr].code.push(variables as u8);
if self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != block.end_line {
- self.vm.units[self.vm.unit_ptr].lines.push((block.end_line, 2));
+ self.vm.units[self.vm.unit_ptr]
+ .lines
+ .push((block.end_line, 2));
} else {
self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 2;
}
-
}
pub fn visit_break(&mut self, ast: &AST) {
let mut scopes = self.scopes.clone();
@@ 289,18 363,27 @@ impl Codegen {
break;
}
}
- self.vm.units[self.vm.unit_ptr].code.push(OpCode::POP.into());
+ self.vm.units[self.vm.unit_ptr]
+ .code
+ .push(OpCode::POP.into());
self.vm.units[self.vm.unit_ptr].code.push(pop_count as u8);
- self.vm.units[self.vm.unit_ptr].code.push(OpCode::JMP.into());
+ self.vm.units[self.vm.unit_ptr]
+ .code
+ .push(OpCode::JMP.into());
self.vm.units[self.vm.unit_ptr].code.push(0xFF);
self.vm.units[self.vm.unit_ptr].code.push(0xFF);
if self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != ast.end_line {
- self.vm.units[self.vm.unit_ptr].lines.push((ast.end_line, 5));
+ self.vm.units[self.vm.unit_ptr]
+ .lines
+ .push((ast.end_line, 5));
} else {
self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 5;
}
- self.break_stack.last_mut().expect("break not in a loop").push(self.vm.units[self.vm.unit_ptr].code.len()-2);
+ self.break_stack
+ .last_mut()
+ .expect("break not in a loop")
+ .push(self.vm.units[self.vm.unit_ptr].code.len() - 2);
}
pub fn visit_continue(&mut self, ast: &AST) {
let mut scopes = self.scopes.clone();
@@ 312,27 395,40 @@ impl Codegen {
break;
}
}
- self.vm.units[self.vm.unit_ptr].code.push(OpCode::POP.into());
+ self.vm.units[self.vm.unit_ptr]
+ .code
+ .push(OpCode::POP.into());
self.vm.units[self.vm.unit_ptr].code.push(pop_count as u8);
- self.vm.units[self.vm.unit_ptr].code.push(OpCode::JMP.into());
+ self.vm.units[self.vm.unit_ptr]
+ .code
+ .push(OpCode::JMP.into());
self.vm.units[self.vm.unit_ptr].code.push(0xFF);
self.vm.units[self.vm.unit_ptr].code.push(0xFF);
if self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != ast.end_line {
- self.vm.units[self.vm.unit_ptr].lines.push((ast.end_line, 5));
+ self.vm.units[self.vm.unit_ptr]
+ .lines
+ .push((ast.end_line, 5));
} else {
self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 5;
}
- self.continue_stack.last_mut().expect("continue not in a loop").push(self.vm.units[self.vm.unit_ptr].code.len()-2);
+ self.continue_stack
+ .last_mut()
+ .expect("continue not in a loop")
+ .push(self.vm.units[self.vm.unit_ptr].code.len() - 2);
}
pub fn visit_if(&mut self, condition: AST, block: AST, else_expr: Option<AST>) {
self.visit(condition.clone());
- self.vm.units[self.vm.unit_ptr].code.push(OpCode::JNE.into());
+ self.vm.units[self.vm.unit_ptr]
+ .code
+ .push(OpCode::JNE.into());
self.vm.units[self.vm.unit_ptr].code.push(0xFF); // placeholder
self.vm.units[self.vm.unit_ptr].code.push(0xFF); // placeholder
- let start_jmp_loc = self.vm.units[self.vm.unit_ptr].code.len()-2;
+ let start_jmp_loc = self.vm.units[self.vm.unit_ptr].code.len() - 2;
if self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != condition.end_line {
- self.vm.units[self.vm.unit_ptr].lines.push((condition.end_line, 5));
+ self.vm.units[self.vm.unit_ptr]
+ .lines
+ .push((condition.end_line, 5));
} else {
self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 5;
}
@@ 342,39 438,48 @@ impl Codegen {
if let Some(ast) = else_expr {
match ast.kind {
ASTType::If(_, _, _) => {
- self.vm.units[self.vm.unit_ptr].code.push(OpCode::JMP.into());
+ self.vm.units[self.vm.unit_ptr]
+ .code
+ .push(OpCode::JMP.into());
self.vm.units[self.vm.unit_ptr].code.push(0xFF); // placeholder
self.vm.units[self.vm.unit_ptr].code.push(0xFF); // placeholder
- let end_jmp_loc = self.vm.units[self.vm.unit_ptr].code.len()-2;
+ let end_jmp_loc = self.vm.units[self.vm.unit_ptr].code.len() - 2;
if self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != ast.end_line {
- self.vm.units[self.vm.unit_ptr].lines.push((ast.end_line, 3));
+ self.vm.units[self.vm.unit_ptr]
+ .lines
+ .push((ast.end_line, 3));
} else {
self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 3;
}
-
+
self.patch_jump(start_jmp_loc, 0);
self.visit(ast);
self.patch_jump(end_jmp_loc, 0);
}
ASTType::Block(_) => {
-
- self.vm.units[self.vm.unit_ptr].code.push(OpCode::JMP.into());
+ self.vm.units[self.vm.unit_ptr]
+ .code
+ .push(OpCode::JMP.into());
self.vm.units[self.vm.unit_ptr].code.push(0xFF); // placeholder
self.vm.units[self.vm.unit_ptr].code.push(0xFF); // placeholder
if self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != ast.end_line {
- self.vm.units[self.vm.unit_ptr].lines.push((ast.end_line, 3));
+ self.vm.units[self.vm.unit_ptr]
+ .lines
+ .push((ast.end_line, 3));
} else {
self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 3;
}
-
- let end_jmp_loc = self.vm.units[self.vm.unit_ptr].code.len()-2;
+
+ let end_jmp_loc = self.vm.units[self.vm.unit_ptr].code.len() - 2;
self.patch_jump(start_jmp_loc, 0); // jmp to else
if let ASTType::Block(ref stmts) = ast.kind {
self.visit_block(&ast, stmts.clone(), ScopeType::If);
}
self.patch_jump(end_jmp_loc, 0); // jmp to after else
}
- _ => { println!("unimplemented"); }
+ _ => {
+ println!("unimplemented");
+ }
}
} else {
self.patch_jump(start_jmp_loc, 0);
@@ 386,36 491,55 @@ impl Codegen {
self.visit(stmt);
}
let (_scope_type, variables) = self.scopes.pop().expect("popped scope in block");
- self.vm.units[self.vm.unit_ptr].code.push(OpCode::POP.into());
+ self.vm.units[self.vm.unit_ptr]
+ .code
+ .push(OpCode::POP.into());
self.vm.units[self.vm.unit_ptr].code.push(variables as u8);
match self.vm.units[self.vm.unit_ptr].lines.last() {
- Some(last) => if last.0 != ast.end_line {
- self.vm.units[self.vm.unit_ptr].lines.push((ast.end_line, 2));
- } else {
- self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 2;
+ Some(last) => {
+ if last.0 != ast.end_line {
+ self.vm.units[self.vm.unit_ptr]
+ .lines
+ .push((ast.end_line, 2));
+ } else {
+ self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 2;
+ }
}
- None => self.vm.units[self.vm.unit_ptr].lines.push((ast.end_line, 2))
+ None => self.vm.units[self.vm.unit_ptr]
+ .lines
+ .push((ast.end_line, 2)),
}
}
pub fn visit_decl(&mut self, ast: &AST, _name: Name, expr: AST) {
self.visit(expr);
- self.vm.units[self.vm.unit_ptr].code.push(OpCode::DECL.into());
+ self.vm.units[self.vm.unit_ptr]
+ .code
+ .push(OpCode::DECL.into());
if self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != ast.end_line {
- self.vm.units[self.vm.unit_ptr].lines.push((ast.end_line, 1));
+ self.vm.units[self.vm.unit_ptr]
+ .lines
+ .push((ast.end_line, 1));
} else {
self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 1;
}
#[allow(irrefutable_let_patterns)]
if let Extension::Resolution(_scope, _ptr) = ast.extensions[0] {
- self.scopes.last_mut().expect("codegen scopes vec was empty").1 += 1;
+ self.scopes
+ .last_mut()
+ .expect("codegen scopes vec was empty")
+ .1 += 1;
}
}
pub fn visit_expr_stmt(&mut self, ast: &AST, expr: AST) {
self.visit(expr);
- self.vm.units[self.vm.unit_ptr].code.push(OpCode::POP.into());
+ self.vm.units[self.vm.unit_ptr]
+ .code
+ .push(OpCode::POP.into());
self.vm.units[self.vm.unit_ptr].code.push(0x01);
if self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != ast.end_line {
- self.vm.units[self.vm.unit_ptr].lines.push((ast.end_line, 2));
+ self.vm.units[self.vm.unit_ptr]
+ .lines
+ .push((ast.end_line, 2));
} else {
self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 2;
}
@@ 423,9 547,13 @@ impl Codegen {
// REMOVE LATER
pub fn visit_print(&mut self, ast: &AST, expr: AST) {
self.visit(expr);
- self.vm.units[self.vm.unit_ptr].code.push(OpCode::PRINT.into());
+ self.vm.units[self.vm.unit_ptr]
+ .code
+ .push(OpCode::PRINT.into());
if self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != ast.end_line {
- self.vm.units[self.vm.unit_ptr].lines.push((ast.end_line, 1));
+ self.vm.units[self.vm.unit_ptr]
+ .lines
+ .push((ast.end_line, 1));
} else {
self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 1;
}
@@ 437,10 565,14 @@ impl Codegen {
LhsAssignType::Ident(_) => {
#[allow(irrefutable_let_patterns)]
if let Extension::Resolution(_scope, ptr) = ast.extensions[0] {
- self.vm.units[self.vm.unit_ptr].code.push(OpCode::ASN.into());
+ self.vm.units[self.vm.unit_ptr]
+ .code
+ .push(OpCode::ASN.into());
self.vm.units[self.vm.unit_ptr].code.push(ptr as u8);
if self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != ast.end_line {
- self.vm.units[self.vm.unit_ptr].lines.push((ast.end_line, 2));
+ self.vm.units[self.vm.unit_ptr]
+ .lines
+ .push((ast.end_line, 2));
} else {
self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 2;
}
@@ 451,10 583,14 @@ impl Codegen {
#[allow(irrefutable_let_patterns)]
if let Extension::Resolution(_scope, ptr) = name.extensions[0] {
- self.vm.units[self.vm.unit_ptr].code.push(OpCode::REF.into());
+ self.vm.units[self.vm.unit_ptr]
+ .code
+ .push(OpCode::REF.into());
self.vm.units[self.vm.unit_ptr].code.push(ptr as u8);
if self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != ast.end_line {
- self.vm.units[self.vm.unit_ptr].lines.push((ast.end_line, 2));
+ self.vm.units[self.vm.unit_ptr]
+ .lines
+ .push((ast.end_line, 2));
} else {
self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 2;
}
@@ 462,10 598,14 @@ impl Codegen {
panic!("Subscript assignment should always have a Resolution");
}
- self.vm.units[self.vm.unit_ptr].code.push(OpCode::ASNARR.into());
+ self.vm.units[self.vm.unit_ptr]
+ .code
+ .push(OpCode::ASNARR.into());
if self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != ast.end_line {
- self.vm.units[self.vm.unit_ptr].lines.push((ast.end_line, 1));
+ self.vm.units[self.vm.unit_ptr]
+ .lines
+ .push((ast.end_line, 1));
} else {
self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 1;
}
@@ 475,21 615,32 @@ impl Codegen {
pub fn visit_anonymous(&mut self, params: Vec<Name>, block: AST) {
self.vm.units.push(Unit::new_empty());
- let new_unit_ptr = self.vm.units.len()-1;
- self.vm.units[self.vm.unit_ptr].pool.push(Value::Fun(Function {
- unit_ptr: new_unit_ptr,
- arity: params.len(),
- }));
+ let new_unit_ptr = self.vm.units.len() - 1;
+ self.vm.units[self.vm.unit_ptr]
+ .pool
+ .push(Value::Fun(Function {
+ unit_ptr: new_unit_ptr,
+ arity: params.len(),
+ }));
// load function to stack
- self.vm.units[self.vm.unit_ptr].code.push(OpCode::LOAD.into());
- let loc = (self.vm.units[self.vm.unit_ptr].pool.len()-1) as u8;
+ self.vm.units[self.vm.unit_ptr]
+ .code
+ .push(OpCode::LOAD.into());
+ let loc = (self.vm.units[self.vm.unit_ptr].pool.len() - 1) as u8;
self.vm.units[self.vm.unit_ptr].code.push(loc);
- if self.vm.units[self.vm.unit_ptr].lines.len() == 0 || self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != block.end_line {
- self.vm.units[self.vm.unit_ptr].lines.push((block.end_line, 2));
+ if self.vm.units[self.vm.unit_ptr].lines.len() == 0
+ || self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != block.end_line
+ {
+ self.vm.units[self.vm.unit_ptr]
+ .lines
+ .push((block.end_line, 2));
} else {
self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 2;
}
- self.scopes.last_mut().expect("codegen scopes vec was empty").1 += 1;
+ self.scopes
+ .last_mut()
+ .expect("codegen scopes vec was empty")
+ .1 += 1;
// enter function unit
let old_unit_ptr = self.vm.unit_ptr;
@@ 498,8 649,11 @@ impl Codegen {
self.vm.ip = 0;
// update scopes with number of parameters
- self.scopes.last_mut().expect("codegen scopes vec was empty").1 += params.len();
-
+ self.scopes
+ .last_mut()
+ .expect("codegen scopes vec was empty")
+ .1 += params.len();
+
if let ASTType::Block(ref stmts) = block.kind {
self.visit_block(&block, stmts.clone(), ScopeType::Function);
}
@@ 508,12 662,18 @@ impl Codegen {
Some(instr) => {
if *instr != <OpCode as Into<u8>>::into(OpCode::RET) {
self.vm.units[self.vm.unit_ptr].pool.push(Value::Null);
- self.vm.units[self.vm.unit_ptr].code.push(OpCode::LOAD.into());
- let loc = (self.vm.units[self.vm.unit_ptr].pool.len()-1) as u8;
+ self.vm.units[self.vm.unit_ptr]
+ .code
+ .push(OpCode::LOAD.into());
+ let loc = (self.vm.units[self.vm.unit_ptr].pool.len() - 1) as u8;
self.vm.units[self.vm.unit_ptr].code.push(loc);
- self.vm.units[self.vm.unit_ptr].code.push(OpCode::RET.into());
+ self.vm.units[self.vm.unit_ptr]
+ .code
+ .push(OpCode::RET.into());
if self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != block.end_line {
- self.vm.units[self.vm.unit_ptr].lines.push((block.end_line, 3));
+ self.vm.units[self.vm.unit_ptr]
+ .lines
+ .push((block.end_line, 3));
} else {
self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 3;
}
@@ 521,36 681,48 @@ impl Codegen {
}
None => {
self.vm.units[self.vm.unit_ptr].pool.push(Value::Null);
- self.vm.units[self.vm.unit_ptr].code.push(OpCode::LOAD.into());
- let loc = (self.vm.units[self.vm.unit_ptr].pool.len()-1) as u8;
+ self.vm.units[self.vm.unit_ptr]
+ .code
+ .push(OpCode::LOAD.into());
+ let loc = (self.vm.units[self.vm.unit_ptr].pool.len() - 1) as u8;
self.vm.units[self.vm.unit_ptr].code.push(loc);
- self.vm.units[self.vm.unit_ptr].code.push(OpCode::RET.into());
+ self.vm.units[self.vm.unit_ptr]
+ .code
+ .push(OpCode::RET.into());
if self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != block.end_line {
- self.vm.units[self.vm.unit_ptr].lines.push((block.end_line, 3));
+ self.vm.units[self.vm.unit_ptr]
+ .lines
+ .push((block.end_line, 3));
} else {
self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 3;
}
}
};
-
+
self.vm.unit_ptr = old_unit_ptr;
self.vm.ip = old_ip;
}
pub fn visit_subscript(&mut self, ast: &AST, left: AST, right: AST) {
self.visit(left);
self.visit(right);
- self.vm.units[self.vm.unit_ptr].code.push(OpCode::SCR.into());
+ self.vm.units[self.vm.unit_ptr]
+ .code
+ .push(OpCode::SCR.into());
if self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != ast.end_line {
- self.vm.units[self.vm.unit_ptr].lines.push((ast.end_line, 1));
+ self.vm.units[self.vm.unit_ptr]
+ .lines
+ .push((ast.end_line, 1));
} else {
self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 1;
}
}
pub fn visit_binary(&mut self, left: AST, oper: BinOp, right: AST) {
use crate::ast::BinOp::*;
- codegen_binary!(self, left, right, oper, Add, ADD, Sub, SUB, Mul, MUL,
- Div, DIV, Mod, MOD, BitAnd, BITAND, BitXor, BITXOR, BitOr, BITOR,
- Eq, EQ, Ne, NE, Gr, GR, Ge, GE, Ls, LS, Le, LE, Or, OR, And, AND);
+ codegen_binary!(
+ self, left, right, oper, Add, ADD, Sub, SUB, Mul, MUL, Div, DIV, Mod, MOD, BitAnd,
+ BITAND, BitXor, BITXOR, BitOr, BITOR, Eq, EQ, Ne, NE, Gr, GR, Ge, GE, Ls, LS, Le, LE,
+ Or, OR, And, AND
+ );
}
pub fn visit_unary(&mut self, oper: UnOp, right: AST) {
use crate::ast::UnOp::*;
@@ 560,33 732,55 @@ impl Codegen {
match lit {
Lit::Num(value) => {
self.vm.units[self.vm.unit_ptr].pool.push(Value::Num(value));
- self.vm.units[self.vm.unit_ptr].code.push(OpCode::LOAD.into());
- let loc = (self.vm.units[self.vm.unit_ptr].pool.len()-1) as u8;
+ self.vm.units[self.vm.unit_ptr]
+ .code
+ .push(OpCode::LOAD.into());
+ let loc = (self.vm.units[self.vm.unit_ptr].pool.len() - 1) as u8;
self.vm.units[self.vm.unit_ptr].code.push(loc);
- if self.vm.units[self.vm.unit_ptr].lines.len() == 0 || self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != ast.end_line {
- self.vm.units[self.vm.unit_ptr].lines.push((ast.end_line, 2));
+ if self.vm.units[self.vm.unit_ptr].lines.len() == 0
+ || self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != ast.end_line
+ {
+ self.vm.units[self.vm.unit_ptr]
+ .lines
+ .push((ast.end_line, 2));
} else {
self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 2;
}
}
Lit::Str(value) => {
- self.vm.units[self.vm.unit_ptr].pool.push(Value::Str(value.into()));
- self.vm.units[self.vm.unit_ptr].code.push(OpCode::LOAD.into());
- let loc = (self.vm.units[self.vm.unit_ptr].pool.len()-1) as u8;
+ self.vm.units[self.vm.unit_ptr]
+ .pool
+ .push(Value::Str(value.into()));
+ self.vm.units[self.vm.unit_ptr]
+ .code
+ .push(OpCode::LOAD.into());
+ let loc = (self.vm.units[self.vm.unit_ptr].pool.len() - 1) as u8;
self.vm.units[self.vm.unit_ptr].code.push(loc);
- if self.vm.units[self.vm.unit_ptr].lines.len() == 0 || self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != ast.end_line {
- self.vm.units[self.vm.unit_ptr].lines.push((ast.end_line, 2));
+ if self.vm.units[self.vm.unit_ptr].lines.len() == 0
+ || self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != ast.end_line
+ {
+ self.vm.units[self.vm.unit_ptr]
+ .lines
+ .push((ast.end_line, 2));
} else {
self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 2;
}
}
Lit::Bool(value) => {
- self.vm.units[self.vm.unit_ptr].pool.push(Value::Bool(value));
- self.vm.units[self.vm.unit_ptr].code.push(OpCode::LOAD.into());
- let loc = (self.vm.units[self.vm.unit_ptr].pool.len()-1) as u8;
+ self.vm.units[self.vm.unit_ptr]
+ .pool
+ .push(Value::Bool(value));
+ self.vm.units[self.vm.unit_ptr]
+ .code
+ .push(OpCode::LOAD.into());
+ let loc = (self.vm.units[self.vm.unit_ptr].pool.len() - 1) as u8;
self.vm.units[self.vm.unit_ptr].code.push(loc);
- if self.vm.units[self.vm.unit_ptr].lines.len() == 0 || self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != ast.end_line {
- self.vm.units[self.vm.unit_ptr].lines.push((ast.end_line, 2));
+ if self.vm.units[self.vm.unit_ptr].lines.len() == 0
+ || self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != ast.end_line
+ {
+ self.vm.units[self.vm.unit_ptr]
+ .lines
+ .push((ast.end_line, 2));
} else {
self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 2;
}
@@ 595,16 789,24 @@ impl Codegen {
for expr in &exprs {
self.visit(expr.clone());
}
- self.vm.units[self.vm.unit_ptr].code.push(OpCode::LIST.into());
+ self.vm.units[self.vm.unit_ptr]
+ .code
+ .push(OpCode::LIST.into());
self.vm.units[self.vm.unit_ptr].code.push(exprs.len() as u8);
- if self.vm.units[self.vm.unit_ptr].lines.len() == 0 || self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != ast.end_line {
- self.vm.units[self.vm.unit_ptr].lines.push((ast.end_line, 2));
+ if self.vm.units[self.vm.unit_ptr].lines.len() == 0
+ || self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != ast.end_line
+ {
+ self.vm.units[self.vm.unit_ptr]
+ .lines
+ .push((ast.end_line, 2));
} else {
self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 2;
}
}
Lit::Ident(_name) => {
- self.vm.units[self.vm.unit_ptr].code.push(OpCode::VAR.into());
+ self.vm.units[self.vm.unit_ptr]
+ .code
+ .push(OpCode::VAR.into());
#[allow(irrefutable_let_patterns)]
if let Extension::Resolution(_scope, ptr) = ast.extensions[0] {
/*println!("line: {} ptr: {} locals: {:?}", ast.end_line, ptr, self.locals);
@@ 612,8 814,12 @@ impl Codegen {
println!("slot: {}", *slot);
self.vm.units[self.vm.unit_ptr].code.push(*slot);*/
self.vm.units[self.vm.unit_ptr].code.push(ptr as u8);
- if self.vm.units[self.vm.unit_ptr].lines.len() == 0 || self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != ast.end_line {
- self.vm.units[self.vm.unit_ptr].lines.push((ast.end_line, 2));
+ if self.vm.units[self.vm.unit_ptr].lines.len() == 0
+ || self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != ast.end_line
+ {
+ self.vm.units[self.vm.unit_ptr]
+ .lines
+ .push((ast.end_line, 2));
} else {
self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 2;
}
@@ 627,10 833,16 @@ impl Codegen {
self.visit(arg.clone());
}
self.visit(ident);
- self.vm.units[self.vm.unit_ptr].code.push(OpCode::CALL.into());
+ self.vm.units[self.vm.unit_ptr]
+ .code
+ .push(OpCode::CALL.into());
self.vm.units[self.vm.unit_ptr].code.push(args.len() as u8);
- if self.vm.units[self.vm.unit_ptr].lines.len() == 0 || self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != ast.end_line {
- self.vm.units[self.vm.unit_ptr].lines.push((ast.end_line, 2));
+ if self.vm.units[self.vm.unit_ptr].lines.len() == 0
+ || self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != ast.end_line
+ {
+ self.vm.units[self.vm.unit_ptr]
+ .lines
+ .push((ast.end_line, 2));
} else {
self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 2;
}
@@ 645,5 857,9 @@ impl Codegen {
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ScopeType {
- Main, Function, Loop, If, Other,
+ Main,
+ Function,
+ Loop,
+ If,
+ Other,
}
M crates/kabel/src/debug.rs => crates/kabel/src/debug.rs +74 -47
@@ 1,4 1,9 @@
-use crate::{ast::{LhsAssignType, AST}, lexer::Token, push_codegen, push_output, vm::{Value, VM}};
+use crate::{
+ ast::{LhsAssignType, AST},
+ lexer::Token,
+ push_codegen, push_output,
+ vm::{Value, VM},
+};
pub fn debug_token_array(tokens: Vec<Token>) -> String {
let mut output = "".to_string();
@@ 6,13 11,13 @@ pub fn debug_token_array(tokens: Vec<Token>) -> String {
output += &token.token_type.to_string();
output += "\n";
}
- output[..output.len()-1].to_string()
+ output[..output.len() - 1].to_string()
}
pub fn debug_ast(ast: AST, level: usize) -> String {
use crate::ast::ASTType::*;
use crate::ast::BinOp::*;
- use crate::ast::UnOp::*;
use crate::ast::Lit::*;
+ use crate::ast::UnOp::*;
let mut output = "".to_string();
match ast.kind {
Program(asts) => {
@@ 20,7 25,7 @@ pub fn debug_ast(ast: AST, level: usize) -> String {
output += "Program";
for ast in asts {
output += "\n";
- output += &debug_ast(ast, level+1);
+ output += &debug_ast(ast, level + 1);
}
}
Function(name, params, block) => {
@@ 32,47 37,47 @@ pub fn debug_ast(ast: AST, level: usize) -> String {
}
output += &format!(" {:?}", ast.extensions);
output += "\n";
- output += &debug_ast(*block, level+1);
+ output += &debug_ast(*block, level + 1);
}
Return(expr) => {
output += &"| ".repeat(level);
output += "Return";
if let Some(expr) = *expr {
output += "\n";
- output += &debug_ast(expr, level+1);
+ output += &debug_ast(expr, level + 1);
}
}
Loop(block) => {
output += &"| ".repeat(level);
output += "Loop";
output += "\n";
- output += &debug_ast(*block, level+1);
+ output += &debug_ast(*block, level + 1);
}
While(condition, block) => {
output += &"| ".repeat(level);
output += "While";
output += "\n";
- output += &debug_ast(*condition, level+1);
+ output += &debug_ast(*condition, level + 1);
output += "\n";
- output += &debug_ast(*block, level+1);
+ output += &debug_ast(*block, level + 1);
}
For(expr1, expr2, expr3, block) => {
output += &"| ".repeat(level);
output += "For";
if let Some(expr1) = *expr1 {
output += "\n";
- output += &debug_ast(expr1, level+1);
+ output += &debug_ast(expr1, level + 1);
}
if let Some(expr2) = *expr2 {
output += "\n";
- output += &debug_ast(expr2, level+1);
+ output += &debug_ast(expr2, level + 1);
}
if let Some(expr3) = *expr3 {
output += "\n";
- output += &debug_ast(expr3, level+1);
+ output += &debug_ast(expr3, level + 1);
}
output += "\n";
- output += &debug_ast(*block, level+1);
+ output += &debug_ast(*block, level + 1);
}
Break => {
output += &"| ".repeat(level);
@@ 85,15 90,15 @@ pub fn debug_ast(ast: AST, level: usize) -> String {
If(condition, block, else_expr) => {
output += &"| ".repeat(level);
output += "If\n";
- output += &debug_ast(*condition, level+1);
+ output += &debug_ast(*condition, level + 1);
output += "\n";
- output += &debug_ast(*block, level+1);
+ output += &debug_ast(*block, level + 1);
if let Some(else_expr) = *else_expr {
output += "\n";
output += &"| ".repeat(level);
output += "Else";
output += "\n";
- output += &debug_ast(else_expr, level+1);
+ output += &debug_ast(else_expr, level + 1);
}
}
Block(asts) => {
@@ 101,19 106,19 @@ pub fn debug_ast(ast: AST, level: usize) -> String {
output += "Block";
for ast in asts {
output += "\n";
- output += &debug_ast(ast, level+1);
+ output += &debug_ast(ast, level + 1);
}
}
Expr(expr) => {
output += &"| ".repeat(level);
output += "Expr\n";
- output += &debug_ast(*expr, level+1);
+ output += &debug_ast(*expr, level + 1);
}
// REMOVE LATER
Print(expr) => {
output += &"| ".repeat(level);
output += "Print\n";
- output += &debug_ast(*expr, level+1);
+ output += &debug_ast(*expr, level + 1);
}
Decl(name, expr) => {
output += &"| ".repeat(level);
@@ 121,7 126,7 @@ pub fn debug_ast(ast: AST, level: usize) -> String {
output += &name.name;
output += &format!(" {:?}", ast.extensions);
output += "\n";
- output += &debug_ast(*expr, level+1);
+ output += &debug_ast(*expr, level + 1);
}
Assign(lhs, expr) => {
output += &"| ".repeat(level);
@@ 132,16 137,16 @@ pub fn debug_ast(ast: AST, level: usize) -> String {
}
LhsAssignType::Subscript(name, index) => {
output += "\n";
- output += &"| ".repeat(level+1);
+ output += &"| ".repeat(level + 1);
output += "Subscript\n";
- output += &debug_ast(*name, level+2);
+ output += &debug_ast(*name, level + 2);
output += "\n";
- output += &debug_ast(*index, level+2);
+ output += &debug_ast(*index, level + 2);
}
}
output += &format!(" {:?}", ast.extensions);
output += "\n";
- output += &debug_ast(*expr, level+1);
+ output += &debug_ast(*expr, level + 1);
}
Anonymous(params, block) => {
output += &"| ".repeat(level);
@@ 150,42 155,42 @@ pub fn debug_ast(ast: AST, level: usize) -> String {
output += &(" ".to_string() + ¶m.name);
}
output += "\n";
- output += &debug_ast(*block, level+1);
+ output += &debug_ast(*block, level + 1);
}
Ternary(condition, true_expr, false_expr) => {
output += &"| ".repeat(level);
output += "Ternary\n";
- output += &debug_ast(*condition, level+1);
+ output += &debug_ast(*condition, level + 1);
output += "\n";
- output += &debug_ast(*true_expr, level+1);
+ output += &debug_ast(*true_expr, level + 1);
output += "\n";
- output += &debug_ast(*false_expr, level+1);
+ output += &debug_ast(*false_expr, level + 1);
}
Subscript(array, index) => {
output += &"| ".repeat(level);
output += "Subscript\n";
- output += &debug_ast(*array, level+1);
+ output += &debug_ast(*array, level + 1);
output += "\n";
- output += &debug_ast(*index, level+1);
+ output += &debug_ast(*index, level + 1);
}
Binary(left, oper, right) => {
output += &"| ".repeat(level);
output += "Binary ";
- push_output!(oper, output,
- Add, Sub, Mul, Div, Mod, BitAnd, BitXor, BitOr,
- Eq, Ne, Gr, Ge, Ls, Le, Or, And);
+ push_output!(
+ oper, output, Add, Sub, Mul, Div, Mod, BitAnd, BitXor, BitOr, Eq, Ne, Gr, Ge, Ls,
+ Le, Or, And
+ );
output += "\n";
- output += &debug_ast(*left, level+1);
+ output += &debug_ast(*left, level + 1);
output += "\n";
- output += &debug_ast(*right, level+1);
+ output += &debug_ast(*right, level + 1);
}
Unary(oper, right) => {
output += &"| ".repeat(level);
output += "Unary ";
- push_output!(oper, output,
- Not, Neg);
+ push_output!(oper, output, Not, Neg);
output += "\n";
- output += &debug_ast(*right, level+1);
+ output += &debug_ast(*right, level + 1);
}
Lit(lit) => {
output += &"| ".repeat(level);
@@ 207,7 212,7 @@ pub fn debug_ast(ast: AST, level: usize) -> String {
Array(value) => {
for value in value {
output += "\n";
- output += &debug_ast(value, level+1);
+ output += &debug_ast(value, level + 1);
}
}
}
@@ 215,18 220,18 @@ pub fn debug_ast(ast: AST, level: usize) -> String {
Call(name, args) => {
output += &"| ".repeat(level);
output += "Call\n";
- output += &debug_ast(*name, level+1);
+ output += &debug_ast(*name, level + 1);
for arg in args {
output += "\n";
- output += &debug_ast(arg, level+1);
+ output += &debug_ast(arg, level + 1);
}
}
Member(left, right) => {
output += &"| ".repeat(level);
output += "Member\n";
- output += &debug_ast(*left, level+1);
+ output += &debug_ast(*left, level + 1);
output += "\n";
- output += &debug_ast(*right, level+1);
+ output += &debug_ast(*right, level + 1);
}
}
output
@@ 239,9 244,31 @@ pub fn debug_bytecode(vm: &VM) -> String {
let mut vm = vm.clone();
while vm.ip < vm.units[vm.unit_ptr].code.len() {
// remove PRINT later
- push_codegen!(vm.units[vm.unit_ptr].code[vm.ip].into(), vm, output, ADD, SUB, MUL, DIV, MOD, BITAND,
- BITXOR, BITOR, EQ, NE, GR, GE, LS, LE, OR, AND, NOT, NEG,
- PRINT, ERR);
+ push_codegen!(
+ vm.units[vm.unit_ptr].code[vm.ip].into(),
+ vm,
+ output,
+ ADD,
+ SUB,
+ MUL,
+ DIV,
+ MOD,
+ BITAND,
+ BITXOR,
+ BITOR,
+ EQ,
+ NE,
+ GR,
+ GE,
+ LS,
+ LE,
+ OR,
+ AND,
+ NOT,
+ NEG,
+ PRINT,
+ ERR
+ );
match vm.units[vm.unit_ptr].code[vm.ip].into() {
LOAD => {
output += &vm.ip.to_string();
@@ 270,7 297,7 @@ pub fn debug_bytecode(vm: &VM) -> String {
output += &vm.units[vm.unit_ptr].code[vm.ip].to_string();
output += "\n";
}
- ASN => {
+ ASN => {
output += &vm.ip.to_string();
output += " ";
output += &vm.find_line().to_string();
M crates/kabel/src/error.rs => crates/kabel/src/error.rs +8 -1
@@ 9,7 9,14 @@ pub struct KabelError {
}
impl KabelError {
- pub fn new(kind: ErrorKind, message: String, hint: Option<String>, line: usize, column: usize, code: String) -> Self {
+ pub fn new(
+ kind: ErrorKind,
+ message: String,
+ hint: Option<String>,
+ line: usize,
+ column: usize,
+ code: String,
+ ) -> Self {
Self {
kind,
message,
M crates/kabel/src/lexer.rs => crates/kabel/src/lexer.rs +61 -10
@@ 53,7 53,10 @@ impl Lexer {
let result = self.read_next_token();
match result {
Ok(b) => b,
- Err(e) => { self.errors.push(e); true }
+ Err(e) => {
+ self.errors.push(e);
+ true
+ }
}
}
@@ 429,15 432,63 @@ pub enum TokenType {
impl Display for TokenType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use TokenType::*;
- token_display!(*self, f, Function, Return, Loop, While, For,
- Break, Continue, If, Else, Var, True, False, Print,
- Star, StarEqual, Slash, SlashEqual, Percent, PercentEqual,
- Plus, PlusPlus, PlusEqual, Minus, MinusMinus, MinusEqual,
- LeftParen, RightParen, LeftBrace, RightBrace,
- LeftSquare, RightSquare, Equal, EqualEqual,
- Bang, BangEqual, Greater, GreaterEqual, Less,
- LessEqual, And, AndEqual, AndAnd, Or, OrEqual, OrOr,
- Caret, CaretEqual, Period, Comma, Semicolon, Colon, Question, Arrow);
+ token_display!(
+ *self,
+ f,
+ Function,
+ Return,
+ Loop,
+ While,
+ For,
+ Break,
+ Continue,
+ If,
+ Else,
+ Var,
+ True,
+ False,
+ Print,
+ Star,
+ StarEqual,
+ Slash,
+ SlashEqual,
+ Percent,
+ PercentEqual,
+ Plus,
+ PlusPlus,
+ PlusEqual,
+ Minus,
+ MinusMinus,
+ MinusEqual,
+ LeftParen,
+ RightParen,
+ LeftBrace,
+ RightBrace,
+ LeftSquare,
+ RightSquare,
+ Equal,
+ EqualEqual,
+ Bang,
+ BangEqual,
+ Greater,
+ GreaterEqual,
+ Less,
+ LessEqual,
+ And,
+ AndEqual,
+ AndAnd,
+ Or,
+ OrEqual,
+ OrOr,
+ Caret,
+ CaretEqual,
+ Period,
+ Comma,
+ Semicolon,
+ Colon,
+ Question,
+ Arrow
+ );
match *self {
Ident(ref name) => {
f.write_str("Ident ")?;
M crates/kabel/src/lib.rs => crates/kabel/src/lib.rs +7 -7
@@ 4,22 4,22 @@ use std::time::Instant;
use ast::AST;
use codegen::Codegen;
use lexer::{Lexer, Token};
-use parser::Parser;
use name_resolution::Resolver;
+use parser::Parser;
+pub mod ast;
+pub mod codegen;
pub mod debug;
pub mod error;
-pub mod runtime_error;
+pub mod extension;
pub mod lexer;
pub mod macros;
-pub mod parser;
-pub mod ast;
pub mod name_resolution;
pub mod opcodes;
-pub mod codegen;
-pub mod vm;
+pub mod parser;
+pub mod runtime_error;
pub mod test;
-pub mod extension;
+pub mod vm;
pub fn run_lexer(input: String) -> Lexer {
let mut lexer = Lexer::new(input);
M crates/kabel/src/macros.rs => crates/kabel/src/macros.rs +14 -5
@@ 1,7 1,7 @@
#[macro_export]
macro_rules! token {
($self:expr, $token:expr) => {
- crate::lexer::Token {
+ $crate::lexer::Token {
token_type: $token,
start_column: $self.start,
end_column: $self.line_current,
@@ 123,13 123,15 @@ macro_rules! push_output {
}
}
-
#[macro_export]
macro_rules! unexpected_token {
($self:expr, $message:expr, $token:expr, $hint:expr) => {
$crate::error::KabelError::new(
$crate::error::ErrorKind::UnexpectedToken,
- format!($message, $self.text[$token.line][$token.start_column..$token.end_column].to_string()),
+ format!(
+ $message,
+ $self.text[$token.line][$token.start_column..$token.end_column].to_string()
+ ),
Some($hint),
$token.line,
$token.start_column,
@@ 139,7 141,10 @@ macro_rules! unexpected_token {
($self:expr, $message:expr, $token:expr) => {
$crate::error::KabelError::new(
$crate::error::ErrorKind::UnexpectedToken,
- format!($message, $self.text[$token.line][$token.start_column..$token.end_column].to_string()),
+ format!(
+ $message,
+ $self.text[$token.line][$token.start_column..$token.end_column].to_string()
+ ),
None,
$token.line,
$token.start_column,
@@ 268,7 273,11 @@ macro_rules! wrong_type {
#[macro_export]
macro_rules! collect_lines {
($string:expr) => {
- $string.iter().fold("".to_string(), |acc, string| acc + string + "\n").trim_end().to_string()
+ $string
+ .iter()
+ .fold("".to_string(), |acc, string| acc + string + "\n")
+ .trim_end()
+ .to_string()
};
}
M crates/kabel/src/main.rs => crates/kabel/src/main.rs +5 -3
@@ 2,7 2,10 @@
use std::{env, fs, process::exit};
-use kabel::{debug::{debug_ast, debug_bytecode, debug_stack, debug_token_array}, run_codegen, run_lexer, run_parser, run_semantic_analysis};
+use kabel::{
+ debug::{debug_ast, debug_bytecode},
+ run_codegen, run_lexer, run_parser, run_semantic_analysis,
+};
fn main() {
let args: Vec<String> = env::args().collect();
@@ 10,8 13,7 @@ fn main() {
println!("Must provide kabel file to run");
exit(1);
}
- let program =
- fs::read_to_string(args[1].clone()).unwrap();
+ let program = fs::read_to_string(args[1].clone()).unwrap();
let mut output = "".to_string();
M crates/kabel/src/name_resolution.rs => crates/kabel/src/name_resolution.rs +182 -35
@@ 1,11 1,17 @@
use std::collections::HashMap;
-use crate::{ast::{ASTType, LhsAssign, LhsAssignType, AST}, ast_error, ast_from_ast, error::{ErrorKind, KabelError}, extension::Extension, out_of_scope_var};
+use crate::{
+ ast::{ASTType, LhsAssign, LhsAssignType, AST},
+ ast_error, ast_from_ast,
+ error::{ErrorKind, KabelError},
+ extension::Extension,
+ out_of_scope_var,
+};
pub struct Resolver {
text: Vec<String>,
symbol_table: Vec<HashMap<String, (Symbol, usize)>>, // (Symbol, reference to locals)
- pub locals: Vec<Vec<usize>>, // scope
+ pub locals: Vec<Vec<usize>>, // scope
pub scope: usize,
pub errors: Vec<KabelError>,
}
@@ 13,7 19,12 @@ pub struct Resolver {
impl Resolver {
pub fn new(text: String) -> Self {
Self {
- text: text.lines().collect::<Vec<&str>>().iter().map(|s| s.to_string()).collect(),
+ text: text
+ .lines()
+ .collect::<Vec<&str>>()
+ .iter()
+ .map(|s| s.to_string())
+ .collect(),
symbol_table: vec![HashMap::new()],
locals: vec![Vec::new()],
scope: 0,
@@ 58,27 69,72 @@ impl Resolver {
ErrorKind::FunctionAlreadyDeclaredFunction, ast,
"Function \"{}\" already declared", name ;
"hint: has function \"{}\" already been declared?", name.name));
- } else {}
+ }
}
}
- self.locals.last_mut().expect("locals last in function push").push(self.scope);
- self.symbol_table.last_mut().unwrap().insert(name.name.clone(),
- (Symbol::Function(args.len()), self.locals.last().expect("locals last in function symbol len").len()-1));
+ self.locals
+ .last_mut()
+ .expect("locals last in function push")
+ .push(self.scope);
+ self.symbol_table.last_mut().unwrap().insert(
+ name.name.clone(),
+ (
+ Symbol::Function(args.len()),
+ self.locals
+ .last()
+ .expect("locals last in function symbol len")
+ .len()
+ - 1,
+ ),
+ );
self.locals.push(Vec::new());
self.symbol_table.push(HashMap::new());
- self.locals.last_mut().expect("locals last in function self-reference push").push(self.scope+1);
- self.symbol_table.last_mut().unwrap().insert(name.name.clone(), (Symbol::Var,self.locals.last().expect("locals last in function self-reference len").len()-1));
+ self.locals
+ .last_mut()
+ .expect("locals last in function self-reference push")
+ .push(self.scope + 1);
+ self.symbol_table.last_mut().unwrap().insert(
+ name.name.clone(),
+ (
+ Symbol::Var,
+ self.locals
+ .last()
+ .expect("locals last in function self-reference len")
+ .len()
+ - 1,
+ ),
+ );
for arg in args.clone() {
- self.locals.last_mut().expect("locals last in function arg push").push(self.scope+1);
- self.symbol_table.last_mut().unwrap().insert(arg.name, (Symbol::Var,self.locals.last().expect("locals last in function arg len").len()-1));
+ self.locals
+ .last_mut()
+ .expect("locals last in function arg push")
+ .push(self.scope + 1);
+ self.symbol_table.last_mut().unwrap().insert(
+ arg.name,
+ (
+ Symbol::Var,
+ self.locals
+ .last()
+ .expect("locals last in function arg len")
+ .len()
+ - 1,
+ ),
+ );
}
let block = self.visit(*block);
self.symbol_table.pop();
self.locals.pop();
AST {
kind: Function(name, args, Box::new(block)),
- extensions: vec![Extension::Resolution(self.scope, self.locals.last().expect("locals last in function ast len").len()-1)],
+ extensions: vec![Extension::Resolution(
+ self.scope,
+ self.locals
+ .last()
+ .expect("locals last in function ast len")
+ .len()
+ - 1,
+ )],
start_line: ast.start_line,
end_line: ast.end_line,
start_column: ast.start_column,
@@ 101,8 157,12 @@ impl Resolver {
let block = self.visit(*block);
ast_from_ast!(AST, While(Box::new(condition), Box::new(block)), ast, ast)
}
- Break => { ast_from_ast!(AST, Break, ast, ast) }
- Continue => { ast_from_ast!(AST, Continue, ast, ast) }
+ Break => {
+ ast_from_ast!(AST, Break, ast, ast)
+ }
+ Continue => {
+ ast_from_ast!(AST, Continue, ast, ast)
+ }
For(expr1, expr2, expr3, block) => {
self.symbol_table.push(HashMap::new());
self.scope += 1;
@@ 121,14 181,27 @@ impl Resolver {
let block = self.visit(*block);
while let Some(scope) = self.locals.last().expect("locals failed in For").last() {
if self.scope == *scope {
- self.locals.last_mut().expect("locals failed in For pop").pop();
+ self.locals
+ .last_mut()
+ .expect("locals failed in For pop")
+ .pop();
} else {
break;
}
}
self.scope -= 1;
self.symbol_table.pop();
- ast_from_ast!(AST, For(Box::new(n_expr1), Box::new(n_expr2), Box::new(n_expr3), Box::new(block)), ast, ast)
+ ast_from_ast!(
+ AST,
+ For(
+ Box::new(n_expr1),
+ Box::new(n_expr2),
+ Box::new(n_expr3),
+ Box::new(block)
+ ),
+ ast,
+ ast
+ )
}
If(condition, block, else_expr) => {
let condition = self.visit(*condition);
@@ 137,7 210,12 @@ impl Resolver {
if let Some(else_expr) = *else_expr {
n_else_expr = Some(self.visit(else_expr));
}
- ast_from_ast!(AST, If(Box::new(condition), Box::new(block), Box::new(n_else_expr)), ast, ast)
+ ast_from_ast!(
+ AST,
+ If(Box::new(condition), Box::new(block), Box::new(n_else_expr)),
+ ast,
+ ast
+ )
}
Block(stmts) => {
self.symbol_table.push(HashMap::new());
@@ 153,7 231,10 @@ impl Resolver {
}*/
while let Some(scope) = self.locals.last().expect("locals last in block").last() {
if self.scope == *scope {
- self.locals.last_mut().expect("locals last in block pop").pop();
+ self.locals
+ .last_mut()
+ .expect("locals last in block pop")
+ .pop();
} else {
break;
}
@@ 164,7 245,10 @@ impl Resolver {
}
Decl(name, expr) => {
let expr = self.visit(*expr);
- self.locals.last_mut().expect("locals last in decl push").push(self.scope);
+ self.locals
+ .last_mut()
+ .expect("locals last in decl push")
+ .push(self.scope);
let resolution = self.resolve_var(&name.name);
if resolution.0 && resolution.2 == self.scope {
self.errors.push(out_of_scope_var!(self,
@@ 185,13 269,26 @@ impl Resolver {
ErrorKind::VariableAlreadyDeclaredFunction, ast,
"Variable \"{}\" already declared", name ;
"hint: has function \"{}\" already been declared?", name.name));
- } else {}
+ }
}
}
- self.symbol_table.last_mut().unwrap().insert(name.name.clone(), (Symbol::Var, self.locals.last().expect("locals last in decl symbol").len()-1));
+ self.symbol_table.last_mut().unwrap().insert(
+ name.name.clone(),
+ (
+ Symbol::Var,
+ self.locals
+ .last()
+ .expect("locals last in decl symbol")
+ .len()
+ - 1,
+ ),
+ );
AST {
kind: Decl(name, Box::new(expr)),
- extensions: vec![Extension::Resolution(self.scope, self.locals.last().expect("locals last in decl ast").len()-1)],
+ extensions: vec![Extension::Resolution(
+ self.scope,
+ self.locals.last().expect("locals last in decl ast").len() - 1,
+ )],
start_line: ast.start_line,
end_line: ast.end_line,
start_column: ast.start_column,
@@ 207,15 304,19 @@ impl Resolver {
let expr = self.visit(*expr);
ast_from_ast!(AST, Print(Box::new(expr)), ast, ast)
}
- Assign(lhs , expr) => {
+ Assign(lhs, expr) => {
let expr = self.visit(*expr);
match lhs.kind.clone() {
LhsAssignType::Ident(name) => {
let resolution = self.resolve_var(&name);
if !resolution.0 {
- self.errors.push(out_of_scope_var!(self,
- ErrorKind::OutOfScope, lhs,
- "Variable \"{}\" not in scope", name));
+ self.errors.push(out_of_scope_var!(
+ self,
+ ErrorKind::OutOfScope,
+ lhs,
+ "Variable \"{}\" not in scope",
+ name
+ ));
}
AST {
kind: Assign(lhs, Box::new(expr)),
@@ 230,7 331,15 @@ impl Resolver {
let name = self.visit(*name);
let index = self.visit(*index);
AST {
- kind: Assign(ast_from_ast!(LhsAssign, LhsAssignType::Subscript(Box::new(name), Box::new(index)), lhs, lhs), Box::new(expr)),
+ kind: Assign(
+ ast_from_ast!(
+ LhsAssign,
+ LhsAssignType::Subscript(Box::new(name), Box::new(index)),
+ lhs,
+ lhs
+ ),
+ Box::new(expr),
+ ),
extensions: Vec::new(),
start_line: ast.start_line,
end_line: ast.end_line,
@@ 243,10 352,26 @@ impl Resolver {
Anonymous(params, block) => {
self.locals.push(Vec::new());
self.symbol_table.push(HashMap::new());
- self.locals.last_mut().expect("locals last in anonymous self-reference push").push(self.scope);
+ self.locals
+ .last_mut()
+ .expect("locals last in anonymous self-reference push")
+ .push(self.scope);
for param in params.clone() {
- self.locals.last_mut().expect("locals last in anonymous param push").push(self.scope+1);
- self.symbol_table.last_mut().unwrap().insert(param.name, (Symbol::Var,self.locals.last().expect("locals last in anonymous param len").len()-1));
+ self.locals
+ .last_mut()
+ .expect("locals last in anonymous param push")
+ .push(self.scope + 1);
+ self.symbol_table.last_mut().unwrap().insert(
+ param.name,
+ (
+ Symbol::Var,
+ self.locals
+ .last()
+ .expect("locals last in anonymous param len")
+ .len()
+ - 1,
+ ),
+ );
}
let block = self.visit(*block);
self.symbol_table.pop();
@@ 257,7 382,16 @@ impl Resolver {
let condition = self.visit(*condition);
let true_expr = self.visit(*true_expr);
let false_expr = self.visit(*false_expr);
- ast_from_ast!(AST, Ternary(Box::new(condition), Box::new(true_expr), Box::new(false_expr)), ast, ast)
+ ast_from_ast!(
+ AST,
+ Ternary(
+ Box::new(condition),
+ Box::new(true_expr),
+ Box::new(false_expr)
+ ),
+ ast,
+ ast
+ )
}
Subscript(array, index) => {
let array = self.visit(*array);
@@ 279,7 413,13 @@ impl Resolver {
crate::ast::Lit::Ident(ref name) => {
let resolution = self.resolve_var(name);
if !resolution.0 {
- self.errors.push(ast_error!(self, ErrorKind::OutOfScope, ast, "Variable \"{}\" not in scope", name))
+ self.errors.push(ast_error!(
+ self,
+ ErrorKind::OutOfScope,
+ ast,
+ "Variable \"{}\" not in scope",
+ name
+ ))
} else {
return AST {
kind: Lit(lit),
@@ 313,7 453,9 @@ impl Resolver {
/*Member(left, right) => {
self.visit_member(*left, *right);
}*/
- _ => { panic!("not implemented") } // not implemented
+ _ => {
+ panic!("not implemented")
+ } // not implemented
}
}
// TODO: make visit_member not throw out of scope errors
@@ 323,13 465,18 @@ impl Resolver {
}*/
fn resolve_var(&self, name: &String) -> (bool, usize, usize) {
for (scope_num, scope) in self.symbol_table.iter().enumerate().rev() {
- if let Some((Symbol::Var, place)) | Some((Symbol::Function(_), place)) = scope.get(name) {
+ if let Some((Symbol::Var, place)) | Some((Symbol::Function(_), place)) = scope.get(name)
+ {
return (true, *place, scope_num);
}
}
(false, 0, 0)
}
- fn resolve_function(&mut self, name: &String, arity: usize) -> Result<usize, (ErrorKind, Option<usize>, Option<usize>)>{
+ fn resolve_function(
+ &mut self,
+ name: &String,
+ arity: usize,
+ ) -> Result<usize, (ErrorKind, Option<usize>, Option<usize>)> {
for scope in self.symbol_table.iter().rev() {
if let Some((Symbol::Function(f_arity), place)) = scope.get(name) {
if *f_arity == arity {
M crates/kabel/src/opcodes.rs => crates/kabel/src/opcodes.rs +43 -42
@@ 48,52 48,53 @@ impl From<OpCode> for u8 {
fn from(value: OpCode) -> Self {
use OpCode::*;
match value {
- LOAD => 0x00,
- VAR => 0x01,
- REF => 0x02,
- ASN => 0x03,
- ASNARR => 0x04,
- DECL => 0x05,
-
- ADD => 0x06,
- SUB => 0x07,
- MUL => 0x08,
- DIV => 0x09,
- MOD => 0x0A,
- BITAND => 0x0B,
- BITXOR => 0x0C,
- BITOR => 0x0D,
- EQ => 0x0E,
- NE => 0x0F,
- GR => 0x10,
- GE => 0x11,
- LS => 0x12,
- LE => 0x13,
- OR => 0x14,
- AND => 0x15,
-
- NOT => 0x16,
- NEG => 0x17,
-
- JMP => 0x18,
- JMP_UP => 0x19,
- JNE => 0x1A,
-
- CALL => 0x1B,
- RET => 0x1C,
-
- LIST => 0x1D,
- SCR => 0x1E,
-
- POP => 0xFD,
- PRINT => 0xFE,
- ERR => 0xFF
+ LOAD => 0x00,
+ VAR => 0x01,
+ REF => 0x02,
+ ASN => 0x03,
+ ASNARR => 0x04,
+ DECL => 0x05,
+
+ ADD => 0x06,
+ SUB => 0x07,
+ MUL => 0x08,
+ DIV => 0x09,
+ MOD => 0x0A,
+ BITAND => 0x0B,
+ BITXOR => 0x0C,
+ BITOR => 0x0D,
+ EQ => 0x0E,
+ NE => 0x0F,
+ GR => 0x10,
+ GE => 0x11,
+ LS => 0x12,
+ LE => 0x13,
+ OR => 0x14,
+ AND => 0x15,
+
+ NOT => 0x16,
+ NEG => 0x17,
+
+ JMP => 0x18,
+ JMP_UP => 0x19,
+ JNE => 0x1A,
+
+ CALL => 0x1B,
+ RET => 0x1C,
+
+ LIST => 0x1D,
+ SCR => 0x1E,
+
+ POP => 0xFD,
+ PRINT => 0xFE,
+ ERR => 0xFF,
}
}
}
impl From<u8> for OpCode {
fn from(value: u8) -> Self {
- use OpCode::*; match value {
+ use OpCode::*;
+ match value {
0x00 => LOAD,
0x01 => VAR,
0x02 => REF,
@@ 133,7 134,7 @@ impl From<u8> for OpCode {
0xFD => POP,
0xFE => PRINT,
- _ => ERR
+ _ => ERR,
}
}
}
M crates/kabel/src/parser.rs => crates/kabel/src/parser.rs +309 -112
@@ 1,7 1,11 @@
+use crate::ast::{ASTType, BinOp, Lit, UnOp, AST};
use crate::{
- ast::{LhsAssign, LhsAssignType}, ast_from_ast, ast_from_ast_token, ast_from_token, ast_from_token_ast, collect_lines, error::{ErrorKind, KabelError}, lexer::{Token, TokenType}, lit, name, unexpected_token
+ ast::{LhsAssign, LhsAssignType},
+ ast_from_ast, ast_from_ast_token, ast_from_token, ast_from_token_ast, collect_lines,
+ error::{ErrorKind, KabelError},
+ lexer::{Token, TokenType},
+ lit, name, unexpected_token,
};
-use crate::ast::{AST, ASTType, BinOp, UnOp, Lit};
pub struct Parser {
input: Vec<Token>,
@@ 15,7 19,12 @@ impl Parser {
pub fn new(text: String, input: Vec<Token>) -> Self {
Self {
input: input.clone(),
- text: text.lines().collect::<Vec<&str>>().iter().map(|s| s.to_string()).collect(),
+ text: text
+ .lines()
+ .collect::<Vec<&str>>()
+ .iter()
+ .map(|s| s.to_string())
+ .collect(),
current: 0,
token: input[0].clone(),
errors: Vec::new(),
@@ 72,7 81,11 @@ impl Parser {
if let TokenType::Ident(name) = ident.token_type {
expressions.push(name!(name, ident));
} else {
- return Err(unexpected_token!(self, "Expected identifier but found {}", ident));
+ return Err(unexpected_token!(
+ self,
+ "Expected identifier but found {}",
+ ident
+ ));
}
if let TokenType::Comma = self.peek()?.token_type {
self.read_token()?;
@@ 81,20 94,25 @@ impl Parser {
let right_paren = self.read_token()?;
if let TokenType::RightParen = right_paren.token_type {
let block = self.block()?;
- return Ok(ast_from_token_ast!(AST,
- ASTType::Function(
- name!(name, ident),
- expressions,
- Box::new(block.clone())
- ),
+ return Ok(ast_from_token_ast!(
+ AST,
+ ASTType::Function(name!(name, ident), expressions, Box::new(block.clone())),
function_ident,
block
));
} else {
- return Err(unexpected_token!(self, "Expected ) but found {}", right_paren));
+ return Err(unexpected_token!(
+ self,
+ "Expected ) but found {}",
+ right_paren
+ ));
}
} else {
- return Err(unexpected_token!(self, "Expected ( but found {}", left_paren));
+ return Err(unexpected_token!(
+ self,
+ "Expected ( but found {}",
+ left_paren
+ ));
}
} else {
return Err(unexpected_token!(
@@ 109,7 127,8 @@ impl Parser {
let return_ident = self.read_token()?;
if let TokenType::Semicolon = self.peek()?.token_type {
let semicolon = self.read_token()?;
- return Ok(ast_from_token!(AST,
+ return Ok(ast_from_token!(
+ AST,
ASTType::Return(Box::new(None)),
return_ident,
semicolon
@@ 118,20 137,26 @@ impl Parser {
let expression = self.expression()?;
let semicolon = self.read_token()?;
if let TokenType::Semicolon = semicolon.token_type {
- Ok(ast_from_token!(AST,
+ Ok(ast_from_token!(
+ AST,
ASTType::Return(Box::new(Some(expression))),
return_ident,
semicolon
))
} else {
- return Err(unexpected_token!(self, "Expected ; but found {}", semicolon));
+ return Err(unexpected_token!(
+ self,
+ "Expected ; but found {}",
+ semicolon
+ ));
}
}
pub fn loop_statement(&mut self) -> Result<AST, KabelError> {
let loop_ident = self.read_token()?;
let block = self.block()?;
- Ok(ast_from_token_ast!(AST,
+ Ok(ast_from_token_ast!(
+ AST,
ASTType::Loop(Box::new(block.clone())),
loop_ident,
block
@@ 146,16 171,25 @@ impl Parser {
let right_paren = self.read_token()?;
if let TokenType::RightParen = right_paren.token_type {
let block = self.block()?;
- return Ok(ast_from_token_ast!(AST,
+ return Ok(ast_from_token_ast!(
+ AST,
ASTType::While(Box::new(condition), Box::new(block.clone())),
while_ident,
block
));
} else {
- return Err(unexpected_token!(self, "Expected ) but found {}", right_paren));
+ return Err(unexpected_token!(
+ self,
+ "Expected ) but found {}",
+ right_paren
+ ));
}
} else {
- return Err(unexpected_token!(self, "Expected ( but found {}", left_paren));
+ return Err(unexpected_token!(
+ self,
+ "Expected ( but found {}",
+ left_paren
+ ));
}
}
@@ 166,18 200,22 @@ impl Parser {
let expression1;
if let TokenType::Semicolon = self.peek()?.token_type {
expression1 = None;
- } else {
- if let TokenType::Var = self.peek()?.token_type {
+ } else if let TokenType::Var = self.peek()?.token_type {
expression1 = Some(self.declaration()?);
} else {
expression1 = Some(self.expression()?);
let semicolon = self.read_token()?;
- if let TokenType::Semicolon = semicolon.token_type {} else {
+ if let TokenType::Semicolon = semicolon.token_type {
+ } else {
self.current -= 1;
- return Err(unexpected_token!(self, "Expected ; but found {}", semicolon));
+ return Err(unexpected_token!(
+ self,
+ "Expected ; but found {}",
+ semicolon
+ ));
}
}
- }
+
let expression2;
if let TokenType::Semicolon = self.peek()?.token_type {
expression2 = None;
@@ 188,14 226,16 @@ impl Parser {
if let TokenType::Semicolon = semicolon_2.token_type {
let expression3;
if let TokenType::RightParen = self.peek()?.token_type {
- expression3 = None; } else {
+ expression3 = None;
+ } else {
expression3 = Some(self.expression()?);
}
let right_paren = self.read_token()?;
if let TokenType::RightParen = right_paren.token_type {
let block = self.block()?;
//return Ok(Self::build_for(for_ident, semicolon_2, expression1, expression2, expression3, block));
- return Ok(ast_from_token_ast!(AST,
+ return Ok(ast_from_token_ast!(
+ AST,
ASTType::For(
Box::new(expression1),
Box::new(expression2),
@@ 206,13 246,25 @@ impl Parser {
block
));
} else {
- return Err(unexpected_token!(self, "Expected ) but found {}", right_paren));
+ return Err(unexpected_token!(
+ self,
+ "Expected ) but found {}",
+ right_paren
+ ));
}
} else {
- return Err(unexpected_token!(self, "Expected ; but found {}", semicolon_2));
+ return Err(unexpected_token!(
+ self,
+ "Expected ; but found {}",
+ semicolon_2
+ ));
}
} else {
- return Err(unexpected_token!(self, "Expected ( but found {}", left_paren));
+ return Err(unexpected_token!(
+ self,
+ "Expected ( but found {}",
+ left_paren
+ ));
}
}
/*fn build_for(for_ident: Token, semicolon_2: Token, expression1: Option<AST>, expression2: Option<AST>, expression3: Option<AST>, block: AST) -> AST {
@@ 243,7 295,11 @@ impl Parser {
if let TokenType::Semicolon = semicolon.token_type {
Ok(ast_from_token!(AST, ASTType::Break, break_ident, semicolon))
} else {
- Err(unexpected_token!(self, "Expected ; but found {}", semicolon))
+ Err(unexpected_token!(
+ self,
+ "Expected ; but found {}",
+ semicolon
+ ))
}
}
@@ 251,9 307,18 @@ impl Parser {
let continue_ident = self.read_token()?;
let semicolon = self.read_token()?;
if let TokenType::Semicolon = semicolon.token_type {
- Ok(ast_from_token!(AST, ASTType::Continue, continue_ident, semicolon))
+ Ok(ast_from_token!(
+ AST,
+ ASTType::Continue,
+ continue_ident,
+ semicolon
+ ))
} else {
- Err(unexpected_token!(self, "Expected ; but found {}", semicolon))
+ Err(unexpected_token!(
+ self,
+ "Expected ; but found {}",
+ semicolon
+ ))
}
}
@@ 271,7 336,8 @@ impl Parser {
self.read_token()?;
if let TokenType::LeftBrace = self.peek()?.token_type {
let else_block = self.block()?;
- return Ok(ast_from_token_ast!(AST,
+ return Ok(ast_from_token_ast!(
+ AST,
ASTType::If(
Box::new(condition),
Box::new(block.clone()),
@@ 284,7 350,8 @@ impl Parser {
let else_if_ident = self.peek()?;
if let TokenType::If = else_if_ident.token_type {
let else_if = self.if_statement()?;
- return Ok(ast_from_token_ast!(AST,
+ return Ok(ast_from_token_ast!(
+ AST,
ASTType::If(
Box::new(condition),
Box::new(block.clone()),
@@ 297,16 364,25 @@ impl Parser {
return Err(unexpected_token!(self, "Unexpected token {}", else_ident));
}
}
- return Ok(ast_from_token_ast!(AST,
+ return Ok(ast_from_token_ast!(
+ AST,
ASTType::If(Box::new(condition), Box::new(block.clone()), Box::new(None)),
if_ident,
block
));
} else {
- return Err(unexpected_token!(self, "Expected ) but found {}", right_paren));
+ return Err(unexpected_token!(
+ self,
+ "Expected ) but found {}",
+ right_paren
+ ));
}
} else {
- return Err(unexpected_token!(self, "Expected ( but found {}", left_paren));
+ return Err(unexpected_token!(
+ self,
+ "Expected ( but found {}",
+ left_paren
+ ));
}
}
@@ 318,9 394,18 @@ impl Parser {
stmts.push(self.statement()?);
}
let right_brace = self.read_token()?;
- return Ok(ast_from_token!(AST, ASTType::Block(stmts), left_brace, right_brace));
+ return Ok(ast_from_token!(
+ AST,
+ ASTType::Block(stmts),
+ left_brace,
+ right_brace
+ ));
} else {
- return Err(unexpected_token!(self, "Expected {{ but found {}", left_brace));
+ return Err(unexpected_token!(
+ self,
+ "Expected {{ but found {}",
+ left_brace
+ ));
}
}
@@ 333,7 418,8 @@ impl Parser {
let expr = self.expression()?;
let semicolon = self.read_token()?;
if let TokenType::Semicolon = semicolon.token_type {
- return Ok(ast_from_token!(AST,
+ return Ok(ast_from_token!(
+ AST,
ASTType::Decl(name!(name, ident), Box::new(expr.clone())),
var,
semicolon
@@ 359,9 445,18 @@ impl Parser {
let expression = self.expression()?;
let semicolon = self.read_token()?;
if matches!(semicolon.token_type, TokenType::Semicolon) {
- Ok(ast_from_token!(AST, ASTType::Print(Box::new(expression)), print_ident, semicolon))
+ Ok(ast_from_token!(
+ AST,
+ ASTType::Print(Box::new(expression)),
+ print_ident,
+ semicolon
+ ))
} else {
- Err(unexpected_token!(self, "Expected ; but found {}", semicolon))
+ Err(unexpected_token!(
+ self,
+ "Expected ; but found {}",
+ semicolon
+ ))
}
}
@@ 380,11 475,19 @@ impl Parser {
}
let semicolon = self.read_token()?;
if let TokenType::Semicolon = semicolon.token_type {
- return Ok(ast_from_ast_token!(AST, ASTType::Expr(Box::new(expression.clone())),
- expression, semicolon));
+ return Ok(ast_from_ast_token!(
+ AST,
+ ASTType::Expr(Box::new(expression.clone())),
+ expression,
+ semicolon
+ ));
} else {
self.current -= 1;
- return Err(unexpected_token!(self, "Expected ; but found {}", semicolon));
+ return Err(unexpected_token!(
+ self,
+ "Expected ; but found {}",
+ semicolon
+ ));
}
}
@@ 401,9 504,18 @@ impl Parser {
self.read_token()?;
let index = self.expression()?;
let right_square = self.read_token()?;
- lhs_type = ast_from_token!(LhsAssign, LhsAssignType::Subscript(Box::new(lit!(Ident, name.clone(), ident)), Box::new(index)), ident, right_square);
+ lhs_type = ast_from_token!(
+ LhsAssign,
+ LhsAssignType::Subscript(
+ Box::new(lit!(Ident, name.clone(), ident)),
+ Box::new(index)
+ ),
+ ident,
+ right_square
+ );
} else {
- lhs_type = ast_from_token!(LhsAssign, LhsAssignType::Ident(name.clone()), ident, ident);
+ lhs_type =
+ ast_from_token!(LhsAssign, LhsAssignType::Ident(name.clone()), ident, ident);
}
if self.current >= self.input.len() {
self.current -= 1;
@@ 422,20 534,20 @@ impl Parser {
let binop = self.read_token()?;
let expr = self.expression()?;
if binop.token_type == TokenType::Equal {
- return Ok(ast_from_token_ast!(AST,
- ASTType::Assign(
- lhs_type,
- Box::new(expr.clone())
- ),
+ return Ok(ast_from_token_ast!(
+ AST,
+ ASTType::Assign(lhs_type, Box::new(expr.clone())),
ident,
expr
));
} else if binop.token_type == TokenType::PlusEqual {
- return Ok(ast_from_token_ast!(AST,
+ return Ok(ast_from_token_ast!(
+ AST,
ASTType::Assign(
lhs_type,
Box::new(
- ast_from_ast!(AST,
+ ast_from_ast!(
+ AST,
ASTType::Binary(
Box::new(lit!(Ident, name, ident)),
BinOp::Add,
@@ 451,11 563,13 @@ impl Parser {
expr
));
} else if binop.token_type == TokenType::MinusEqual {
- return Ok(ast_from_token_ast!(AST,
+ return Ok(ast_from_token_ast!(
+ AST,
ASTType::Assign(
lhs_type,
Box::new(
- ast_from_ast!(AST,
+ ast_from_ast!(
+ AST,
ASTType::Binary(
Box::new(lit!(Ident, name, ident)),
BinOp::Sub,
@@ 471,11 585,13 @@ impl Parser {
expr
));
} else if binop.token_type == TokenType::StarEqual {
- return Ok(ast_from_token_ast!(AST,
+ return Ok(ast_from_token_ast!(
+ AST,
ASTType::Assign(
lhs_type,
Box::new(
- ast_from_ast!(AST,
+ ast_from_ast!(
+ AST,
ASTType::Binary(
Box::new(lit!(Ident, name, ident)),
BinOp::Mul,
@@ 491,11 607,13 @@ impl Parser {
expr
));
} else if binop.token_type == TokenType::SlashEqual {
- return Ok(ast_from_token_ast!(AST,
+ return Ok(ast_from_token_ast!(
+ AST,
ASTType::Assign(
lhs_type,
Box::new(
- ast_from_ast!(AST,
+ ast_from_ast!(
+ AST,
ASTType::Binary(
Box::new(lit!(Ident, name, ident)),
BinOp::Div,
@@ 511,11 629,13 @@ impl Parser {
expr
));
} else if binop.token_type == TokenType::PercentEqual {
- return Ok(ast_from_token_ast!(AST,
+ return Ok(ast_from_token_ast!(
+ AST,
ASTType::Assign(
lhs_type,
Box::new(
- ast_from_ast!(AST,
+ ast_from_ast!(
+ AST,
ASTType::Binary(
Box::new(lit!(Ident, name, ident)),
BinOp::Mod,
@@ 531,11 651,13 @@ impl Parser {
expr
));
} else if binop.token_type == TokenType::AndEqual {
- return Ok(ast_from_token_ast!(AST,
+ return Ok(ast_from_token_ast!(
+ AST,
ASTType::Assign(
lhs_type,
Box::new(
- ast_from_ast!(AST,
+ ast_from_ast!(
+ AST,
ASTType::Binary(
Box::new(lit!(Ident, name, ident)),
BinOp::BitAnd,
@@ 551,11 673,13 @@ impl Parser {
expr
));
} else if binop.token_type == TokenType::CaretEqual {
- return Ok(ast_from_token_ast!(AST,
+ return Ok(ast_from_token_ast!(
+ AST,
ASTType::Assign(
lhs_type,
Box::new(
- ast_from_ast!(AST,
+ ast_from_ast!(
+ AST,
ASTType::Binary(
Box::new(lit!(Ident, name, ident)),
BinOp::BitXor,
@@ 571,11 695,13 @@ impl Parser {
expr
));
} else {
- return Ok(ast_from_token_ast!(AST,
+ return Ok(ast_from_token_ast!(
+ AST,
ASTType::Assign(
lhs_type,
Box::new(
- ast_from_ast!(AST,
+ ast_from_ast!(
+ AST,
ASTType::Binary(
Box::new(lit!(Ident, name, ident)),
BinOp::BitOr,
@@ 613,7 739,11 @@ impl Parser {
if let TokenType::Ident(name) = ident.token_type {
params.push(name!(name, ident));
} else {
- return Err(unexpected_token!(self, "Expected identifier but found {}", ident));
+ return Err(unexpected_token!(
+ self,
+ "Expected identifier but found {}",
+ ident
+ ));
}
if let TokenType::Comma = self.peek()?.token_type {
self.read_token()?;
@@ 624,10 754,19 @@ impl Parser {
self.read_token()?;
if let TokenType::LeftBrace = self.peek()?.token_type {
let block = self.block()?;
- return Ok(ast_from_token_ast!(AST, ASTType::Anonymous(params, Box::new(block.clone())), left_paren, block));
+ return Ok(ast_from_token_ast!(
+ AST,
+ ASTType::Anonymous(params, Box::new(block.clone())),
+ left_paren,
+ block
+ ));
} else {
let left_brace = self.read_token()?;
- return Err(unexpected_token!(self, "Expected {{ but found {}", left_brace));
+ return Err(unexpected_token!(
+ self,
+ "Expected {{ but found {}",
+ left_brace
+ ));
}
} else {
let arrow = self.read_token()?;
@@ 640,10 779,19 @@ impl Parser {
self.read_token()?;
if let TokenType::LeftBrace = self.peek()?.token_type {
let block = self.block()?;
- return Ok(ast_from_token_ast!(AST, ASTType::Anonymous(params, Box::new(block.clone())), left_paren, block));
+ return Ok(ast_from_token_ast!(
+ AST,
+ ASTType::Anonymous(params, Box::new(block.clone())),
+ left_paren,
+ block
+ ));
} else {
let left_brace = self.read_token()?;
- return Err(unexpected_token!(self, "Expected {{ but found {}", left_brace));
+ return Err(unexpected_token!(
+ self,
+ "Expected {{ but found {}",
+ left_brace
+ ));
}
} else {
let arrow = self.read_token()?;
@@ 659,7 807,12 @@ impl Parser {
if let TokenType::Arrow = self.peek()?.token_type {
self.read_token()?;
let block = self.block()?;
- return Ok(ast_from_token_ast!(AST, ASTType::Anonymous(Vec::new(), Box::new(block.clone())), left_paren, block));
+ return Ok(ast_from_token_ast!(
+ AST,
+ ASTType::Anonymous(Vec::new(), Box::new(block.clone())),
+ left_paren,
+ block
+ ));
} else {
let arrow = self.read_token()?;
return Err(unexpected_token!(self, "Expected => but found {}", arrow));
@@ 682,7 835,8 @@ impl Parser {
if let TokenType::Colon = self.peek()?.token_type {
self.read_token()?;
let false_expr = self.expression()?;
- return Ok(ast_from_ast!(AST,
+ return Ok(ast_from_ast!(
+ AST,
ASTType::Ternary(
Box::new(condition.clone()),
Box::new(true_expr),
@@ 692,7 846,11 @@ impl Parser {
false_expr
));
} else {
- return Err(unexpected_token!(self, "Expected : but found {}", self.token));
+ return Err(unexpected_token!(
+ self,
+ "Expected : but found {}",
+ self.token
+ ));
}
}
@@ 705,7 863,8 @@ impl Parser {
while self.current < self.input.len() && self.peek()?.token_type == TokenType::OrOr {
self.read_token()?;
let right = self.logical_and()?;
- left = ast_from_ast!(AST,
+ left = ast_from_ast!(
+ AST,
ASTType::Binary(Box::new(left.clone()), BinOp::Or, Box::new(right.clone())),
left,
right
@@ 720,7 879,8 @@ impl Parser {
while self.current < self.input.len() && self.peek()?.token_type == TokenType::AndAnd {
self.read_token()?;
let right = self.bit_and()?;
- left = ast_from_ast!(AST,
+ left = ast_from_ast!(
+ AST,
ASTType::Binary(Box::new(left.clone()), BinOp::And, Box::new(right.clone())),
left,
right
@@ 735,7 895,8 @@ impl Parser {
while self.current < self.input.len() && self.peek()?.token_type == TokenType::And {
self.read_token()?;
let right = self.bit_xor()?;
- left = ast_from_ast!(AST,
+ left = ast_from_ast!(
+ AST,
ASTType::Binary(
Box::new(left.clone()),
BinOp::BitAnd,
@@ 754,7 915,8 @@ impl Parser {
while self.current < self.input.len() && self.peek()?.token_type == TokenType::Caret {
self.read_token()?;
let right = self.bit_or()?;
- left = ast_from_ast!(AST,
+ left = ast_from_ast!(
+ AST,
ASTType::Binary(
Box::new(left.clone()),
BinOp::BitXor,
@@ 773,7 935,8 @@ impl Parser {
while self.current < self.input.len() && self.peek()?.token_type == TokenType::Or {
self.read_token()?;
let right = self.equality()?;
- left = ast_from_ast!(AST,
+ left = ast_from_ast!(
+ AST,
ASTType::Binary(
Box::new(left.clone()),
BinOp::BitOr,
@@ 796,13 959,15 @@ impl Parser {
let binop = self.read_token()?;
let right = self.comparison()?;
if binop.token_type == TokenType::EqualEqual {
- left = ast_from_ast!(AST,
+ left = ast_from_ast!(
+ AST,
ASTType::Binary(Box::new(left.clone()), BinOp::Eq, Box::new(right.clone())),
left,
right
);
} else {
- left = ast_from_ast!(AST,
+ left = ast_from_ast!(
+ AST,
ASTType::Binary(Box::new(left.clone()), BinOp::Ne, Box::new(right.clone())),
left,
right
@@ 825,25 990,29 @@ impl Parser {
let binop = self.read_token()?;
let right = self.term()?;
if binop.token_type == TokenType::Less {
- left = ast_from_ast!(AST,
+ left = ast_from_ast!(
+ AST,
ASTType::Binary(Box::new(left.clone()), BinOp::Ls, Box::new(right.clone())),
left,
right
);
} else if binop.token_type == TokenType::LessEqual {
- left = ast_from_ast!(AST,
+ left = ast_from_ast!(
+ AST,
ASTType::Binary(Box::new(left.clone()), BinOp::Le, Box::new(right.clone())),
left,
right
);
} else if binop.token_type == TokenType::Greater {
- left = ast_from_ast!(AST,
+ left = ast_from_ast!(
+ AST,
ASTType::Binary(Box::new(left.clone()), BinOp::Gr, Box::new(right.clone())),
left,
right
);
} else {
- left = ast_from_ast!(AST,
+ left = ast_from_ast!(
+ AST,
ASTType::Binary(Box::new(left.clone()), BinOp::Ge, Box::new(right.clone())),
left,
right
@@ 865,13 1034,15 @@ impl Parser {
let right = self.factor()?;
if binop.token_type == TokenType::Plus {
- left = ast_from_ast!(AST,
+ left = ast_from_ast!(
+ AST,
ASTType::Binary(Box::new(left.clone()), BinOp::Add, Box::new(right.clone())),
left,
right
);
} else {
- left = ast_from_ast!(AST,
+ left = ast_from_ast!(
+ AST,
ASTType::Binary(Box::new(left.clone()), BinOp::Sub, Box::new(right.clone())),
left,
right
@@ 892,19 1063,22 @@ impl Parser {
let right = self.unary()?;
if binop.token_type == TokenType::Star {
- left = ast_from_ast!(AST,
+ left = ast_from_ast!(
+ AST,
ASTType::Binary(Box::new(left.clone()), BinOp::Mul, Box::new(right.clone())),
left,
right
);
} else if binop.token_type == TokenType::Slash {
- left = ast_from_ast!(AST,
+ left = ast_from_ast!(
+ AST,
ASTType::Binary(Box::new(left.clone()), BinOp::Div, Box::new(right.clone())),
left,
right
);
} else {
- left = ast_from_ast!(AST,
+ left = ast_from_ast!(
+ AST,
ASTType::Binary(Box::new(left.clone()), BinOp::Mod, Box::new(right.clone())),
left,
right
@@ 918,13 1092,15 @@ impl Parser {
let token = self.read_token()?;
let unary = self.unary()?;
if token.token_type == TokenType::Bang {
- return Ok(ast_from_token_ast!(AST,
+ return Ok(ast_from_token_ast!(
+ AST,
ASTType::Unary(UnOp::Not, Box::new(unary.clone())),
token,
unary
));
} else {
- return Ok(ast_from_token_ast!(AST,
+ return Ok(ast_from_token_ast!(
+ AST,
ASTType::Unary(UnOp::Neg, Box::new(unary.clone())),
token,
unary
@@ 942,13 1118,18 @@ impl Parser {
let expr = self.expression()?;
let right_brace = self.read_token()?;
if let TokenType::RightSquare = right_brace.token_type {
- primary = ast_from_ast_token!(AST,
+ primary = ast_from_ast_token!(
+ AST,
ASTType::Subscript(Box::new(primary.clone()), Box::new(expr)),
primary,
right_brace
);
} else {
- return Err(unexpected_token!(self, "Expected ] but found {}", right_brace));
+ return Err(unexpected_token!(
+ self,
+ "Expected ] but found {}",
+ right_brace
+ ));
}
}
@@ 1001,7 1182,8 @@ impl Parser {
}
}
let right_square = self.read_token()?;
- Ok(ast_from_token!(AST,
+ Ok(ast_from_token!(
+ AST,
ASTType::Lit(Lit::Array(expressions)),
left_square,
right_square
@@ 1018,7 1200,8 @@ impl Parser {
if self.current < self.input.len() {
if let TokenType::LeftParen = self.peek()?.token_type {
let call = self.call(child)?;
- expr = ast_from_ast!(AST,
+ expr = ast_from_ast!(
+ AST,
ASTType::Member(Box::new(expr.clone()), Box::new(call.clone())),
expr,
call
@@ 1029,7 1212,8 @@ impl Parser {
continue;
}
}
- expr = ast_from_ast_token!(AST,
+ expr = ast_from_ast_token!(
+ AST,
ASTType::Member(
Box::new(expr.clone()),
Box::new(lit!(Ident, child_str, child))
@@ 1060,7 1244,8 @@ impl Parser {
}
let right_paren = self.read_token()?;
if let TokenType::Ident(name) = ident.token_type {
- return Ok(ast_from_token!(AST,
+ return Ok(ast_from_token!(
+ AST,
ASTType::Call(Box::new(lit!(Ident, name, ident)), expressions),
ident,
right_paren
@@ 1072,10 1257,17 @@ impl Parser {
if let TokenType::Ident(name) = ident.token_type {
let oper = self.read_token()?;
if oper.token_type == TokenType::PlusPlus {
- return Ok(ast_from_token!(AST,
+ return Ok(ast_from_token!(
+ AST,
ASTType::Assign(
- ast_from_token!(LhsAssign, LhsAssignType::Ident(name.clone()), ident, ident),
- Box::new(ast_from_token!(AST,
+ ast_from_token!(
+ LhsAssign,
+ LhsAssignType::Ident(name.clone()),
+ ident,
+ ident
+ ),
+ Box::new(ast_from_token!(
+ AST,
ASTType::Binary(
Box::new(lit!(Ident, name, ident)),
BinOp::Add,
@@ 1089,10 1281,17 @@ impl Parser {
oper
));
} else {
- return Ok(ast_from_token!(AST,
+ return Ok(ast_from_token!(
+ AST,
ASTType::Assign(
- ast_from_token!(LhsAssign, LhsAssignType::Ident(name.clone()), ident, ident),
- Box::new(ast_from_token!(AST,
+ ast_from_token!(
+ LhsAssign,
+ LhsAssignType::Ident(name.clone()),
+ ident,
+ ident
+ ),
+ Box::new(ast_from_token!(
+ AST,
ASTType::Binary(
Box::new(lit!(Ident, name, ident)),
BinOp::Sub,
@@ 1121,15 1320,13 @@ impl Parser {
None,
right_paren.line,
right_paren.start_column,
- self.text[left_paren.line..right_paren.line].iter().fold("".to_string(), |acc, string| acc + string + "\n"),
+ self.text[left_paren.line..right_paren.line]
+ .iter()
+ .fold("".to_string(), |acc, string| acc + string + "\n"),
));
}
self.read_token()?;
- return Ok(ast_from_token!(AST,
- expr.kind,
- left_paren,
- right_paren
- ));
+ return Ok(ast_from_token!(AST, expr.kind, left_paren, right_paren));
}
if let Err(e) = right_paren {
return Err(KabelError::new(
M crates/kabel/src/runtime_error.rs => crates/kabel/src/runtime_error.rs +7 -1
@@ 8,7 8,13 @@ pub struct KabelRuntimeError {
}
impl KabelRuntimeError {
- pub fn new(kind: RuntimeErrorKind, message: String, hint: Option<String>, line: usize, code: String) -> Self {
+ pub fn new(
+ kind: RuntimeErrorKind,
+ message: String,
+ hint: Option<String>,
+ line: usize,
+ code: String,
+ ) -> Self {
Self {
kind,
message,
M crates/kabel/src/test.rs => crates/kabel/src/test.rs +4 -1
@@ 1,6 1,9 @@
use test_each_file::test_each_file;
-use crate::{debug::{debug_ast, debug_token_array}, run_lexer, run_parser};
+use crate::{
+ debug::{debug_ast, debug_token_array},
+ run_lexer, run_parser,
+};
test_each_file! { for ["kab", "out"] in "./crates/kabel/test/runtime/" => test }
test_each_file! { for ["kab", "out"] in "./crates/kabel/test/lexer/" => test_lexer }
M crates/kabel/src/vm.rs => crates/kabel/src/vm.rs +447 -112
@@ 1,6 1,8 @@
-
-use crate::{runtime_error::{KabelRuntimeError, RuntimeErrorKind}, vm_boolean_comparison, vm_boolean_equality};
use crate::vm_error;
+use crate::{
+ runtime_error::{KabelRuntimeError, RuntimeErrorKind},
+ vm_boolean_comparison, vm_boolean_equality,
+};
#[derive(Debug, Clone)]
pub struct Unit {
@@ 10,11 12,7 @@ pub struct Unit {
}
impl Unit {
pub fn new(code: Vec<u8>, pool: Vec<Value>, lines: Vec<(usize, usize)>) -> Self {
- Self {
- code,
- pool,
- lines,
- }
+ Self { code, pool, lines }
}
pub fn new_empty() -> Self {
Self {
@@ 34,12 32,16 @@ pub struct VM {
pub stack: Vec<Value>,
pub variables: Vec<Value>,
pub variables_offset: usize,
- text: Vec<String>
+ text: Vec<String>,
}
impl VM {
- pub fn new(bytecode: Vec<u8>, lines: Vec<(usize, usize)>, pool: Vec<Value>,
- text: String) -> Self {
+ pub fn new(
+ bytecode: Vec<u8>,
+ lines: Vec<(usize, usize)>,
+ pool: Vec<Value>,
+ text: String,
+ ) -> Self {
Self {
ip: 0,
unit_ptr: 0,
@@ 55,35 57,45 @@ impl VM {
use Value::*;
while self.ip < self.units[self.unit_ptr].code.len() {
match self.read() {
- 0x00 => { // LOAD
+ 0x00 => {
+ // LOAD
let byte = self.read() as usize;
println!("ip: {}", self.ip);
let value = self.units[self.unit_ptr].pool[byte].clone();
self.stack.push(value);
}
- 0x01 => { // VAR
+ 0x01 => {
+ // VAR
let ptr = self.read() as usize;
- let value = self.variables[ptr+self.variables_offset].clone();
+ let value = self.variables[ptr + self.variables_offset].clone();
self.stack.push(value);
}
- 0x02 => { // REF
+ 0x02 => {
+ // REF
let ptr = self.read() as usize;
self.stack.push(Ref(ptr));
}
- 0x03 => { // ASN
+ 0x03 => {
+ // ASN
let value = self.stack.pop().unwrap();
let ptr = self.read();
let offset = self.call_stack.last().expect("var call stack last").2;
self.variables[ptr as usize + offset] = value.clone();
self.stack.push(value);
}
- 0x04 => { // ASNARR
+ 0x04 => {
+ // ASNARR
let listref = self.stack.pop().unwrap();
let index = self.stack.pop().unwrap();
let value = self.stack.pop().unwrap();
if let Value::Num(index) = index {
if index.fract() != 0.0 {
- return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Subscript index must be an integer but found {}", index))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Subscript index must be an integer but found {}",
+ index
+ ));
}
let index = index as usize;
if let Value::Ref(listref) = listref {
@@ 91,166 103,333 @@ impl VM {
if let Value::List(ref mut list) = list {
let len = list.len();
if index > len {
- return Err(vm_error!(self, RuntimeErrorKind::ArrayOutOfBounds, "List length is {} but found index {}", len, index))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::ArrayOutOfBounds,
+ "List length is {} but found index {}",
+ len,
+ index
+ ));
}
println!("index: {}", index);
list[index] = value.clone();
self.stack.push(value);
} else {
let type_str = list.type_str();
- return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to subscript non-list type {}", type_str))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Tried to subscript non-list type {}",
+ type_str
+ ));
}
} else {
panic!("Something went wrong in kabel, listref was not a Ref");
}
} else {
- return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to use non-integer type {} to subscript list", index.type_str()))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Tried to use non-integer type {} to subscript list",
+ index.type_str()
+ ));
}
}
- 0x05 => { // DECL
+ 0x05 => {
+ // DECL
let value = self.stack.pop().unwrap();
self.variables.push(value);
}
- 0x06 => { // ADD
+ 0x06 => {
+ // ADD
match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) {
(Num(v1), Num(v2)) => self.stack.push(Num(v1 + v2)),
(Str(v1), Str(v2)) => {
self.stack.push(Str(v1.clone() + &v2));
- },
+ }
(Bool(_v1), Bool(_v2)) => {
- return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot add booleans"))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Cannot add booleans"
+ ))
}
(v1, v2) => {
- return Err(vm_error!(self, RuntimeErrorKind::MismatchedTypes, "Mismatched types: {} and {}", v1.type_str(), v2.type_str()))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::MismatchedTypes,
+ "Mismatched types: {} and {}",
+ v1.type_str(),
+ v2.type_str()
+ ))
}
}
}
- 0x07 => { // SUB
+ 0x07 => {
+ // SUB
match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) {
(Num(v1), Num(v2)) => self.stack.push(Num(v1 - v2)),
(Str(_v1), Str(_v2)) => {
- return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot subtract strings"))
- },
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Cannot subtract strings"
+ ))
+ }
(Bool(_v1), Bool(_v2)) => {
- return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot subtract booleans"))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Cannot subtract booleans"
+ ))
}
(v1, v2) => {
- return Err(vm_error!(self, RuntimeErrorKind::MismatchedTypes, "Mismatched types: {} and {}", v1.type_str(), v2.type_str()))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::MismatchedTypes,
+ "Mismatched types: {} and {}",
+ v1.type_str(),
+ v2.type_str()
+ ))
}
}
}
- 0x08 => { // MUL
+ 0x08 => {
+ // MUL
match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) {
(Num(v1), Num(v2)) => self.stack.push(Num(v1 * v2)),
(Str(v1), Num(v2)) => {
if v2.fract() == 0.0 {
self.stack.push(Str(v1.repeat(v2 as usize)));
} else {
- return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Number must be an integer"))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Number must be an integer"
+ ));
}
}
(Str(_v1), Str(_v2)) => {
- return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot multiply strings"))
- },
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Cannot multiply strings"
+ ))
+ }
(Bool(_v1), Bool(_v2)) => {
- return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot multiply booleans"))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Cannot multiply booleans"
+ ))
}
(v1, v2) => {
- return Err(vm_error!(self, RuntimeErrorKind::MismatchedTypes, "Mismatched types: {} and {}", v1.type_str(), v2.type_str()))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::MismatchedTypes,
+ "Mismatched types: {} and {}",
+ v1.type_str(),
+ v2.type_str()
+ ))
}
}
}
- 0x09 => { // DIV
+ 0x09 => {
+ // DIV
match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) {
(Num(v1), Num(v2)) => self.stack.push(Num(v1 / v2)),
(Str(_v1), Str(_v2)) => {
- return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot divide strings"))
- },
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Cannot divide strings"
+ ))
+ }
(Bool(_v1), Bool(_v2)) => {
- return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot divide booleans"))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Cannot divide booleans"
+ ))
}
(v1, v2) => {
- return Err(vm_error!(self, RuntimeErrorKind::MismatchedTypes, "Mismatched types: {} and {}", v1.type_str(), v2.type_str()))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::MismatchedTypes,
+ "Mismatched types: {} and {}",
+ v1.type_str(),
+ v2.type_str()
+ ))
}
}
}
- 0x0A => { // MOD
+ 0x0A => {
+ // MOD
match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) {
(Num(v1), Num(v2)) => self.stack.push(Num(v1 % v2)),
(Str(_v1), Str(_v2)) => {
- return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform modulus on strings"))
- },
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Cannot perform modulus on strings"
+ ))
+ }
(Bool(_v1), Bool(_v2)) => {
- return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform modulus on booleans"))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Cannot perform modulus on booleans"
+ ))
}
(v1, v2) => {
- return Err(vm_error!(self, RuntimeErrorKind::MismatchedTypes, "Mismatched types: {} and {}", v1.type_str(), v2.type_str()))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::MismatchedTypes,
+ "Mismatched types: {} and {}",
+ v1.type_str(),
+ v2.type_str()
+ ))
}
}
}
- 0x0B => { // BITAND
+ 0x0B => {
+ // BITAND
match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) {
(Num(v1), Num(v2)) => {
if v1.fract() != 0.0 {
- return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform bitwise AND on {}", v1))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Cannot perform bitwise AND on {}",
+ v1
+ ));
}
if v2.fract() != 0.0 {
- return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform bitwise AND on {}", v2))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Cannot perform bitwise AND on {}",
+ v2
+ ));
}
self.stack.push(Num((v1 as u32 & v2 as u32) as f32))
}
(Str(_v1), Str(_v2)) => {
- return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform bitwise AND on strings"))
- },
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Cannot perform bitwise AND on strings"
+ ))
+ }
(Bool(_v1), Bool(_v2)) => {
- return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform bitwise AND on booleans"))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Cannot perform bitwise AND on booleans"
+ ))
}
(v1, v2) => {
- return Err(vm_error!(self, RuntimeErrorKind::MismatchedTypes, "Mismatched types: {} and {}", v1.type_str(), v2.type_str()))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::MismatchedTypes,
+ "Mismatched types: {} and {}",
+ v1.type_str(),
+ v2.type_str()
+ ))
}
}
}
- 0x0C => { // BITXOR
+ 0x0C => {
+ // BITXOR
match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) {
(Num(v1), Num(v2)) => {
if v1.fract() != 0.0 {
- return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform bitwise XOR on {}", v1))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Cannot perform bitwise XOR on {}",
+ v1
+ ));
}
if v2.fract() != 0.0 {
- return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform bitwise XOR on {}", v2))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Cannot perform bitwise XOR on {}",
+ v2
+ ));
}
self.stack.push(Num((v1 as u32 ^ v2 as u32) as f32))
}
(Str(_v1), Str(_v2)) => {
- return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform bitwise XOR on strings"))
- },
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Cannot perform bitwise XOR on strings"
+ ))
+ }
(Bool(_v1), Bool(_v2)) => {
- return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform bitwise XOR on booleans"))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Cannot perform bitwise XOR on booleans"
+ ))
}
(v1, v2) => {
- return Err(vm_error!(self, RuntimeErrorKind::MismatchedTypes, "Mismatched types: {} and {}", v1.type_str(), v2.type_str()))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::MismatchedTypes,
+ "Mismatched types: {} and {}",
+ v1.type_str(),
+ v2.type_str()
+ ))
}
}
}
- 0x0D => { // BITOR
+ 0x0D => {
+ // BITOR
match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) {
(Num(v1), Num(v2)) => {
if v1.fract() != 0.0 {
- return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform bitwise OR on {}", v1))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Cannot perform bitwise OR on {}",
+ v1
+ ));
}
if v2.fract() != 0.0 {
- return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform bitwise OR on {}", v2))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Cannot perform bitwise OR on {}",
+ v2
+ ));
}
self.stack.push(Num((v1 as u32 | v2 as u32) as f32))
}
(Str(_v1), Str(_v2)) => {
- return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform bitwise OR on strings"))
- },
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Cannot perform bitwise OR on strings"
+ ))
+ }
(Bool(_v1), Bool(_v2)) => {
- return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform bitwise OR on booleans"))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Cannot perform bitwise OR on booleans"
+ ))
}
(v1, v2) => {
- return Err(vm_error!(self, RuntimeErrorKind::MismatchedTypes, "Mismatched types: {} and {}", v1.type_str(), v2.type_str()))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::MismatchedTypes,
+ "Mismatched types: {} and {}",
+ v1.type_str(),
+ v2.type_str()
+ ))
}
}
}
@@ 269,73 448,177 @@ impl VM {
// OR
0x14 => match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) {
(Num(_v1), Num(_v2)) => {
- return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"||\" on non-boolean numbers"))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Tried to perform \"||\" on non-boolean numbers"
+ ))
}
(Str(_v1), Str(_v2)) => {
- return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"||\" on non-boolean strings"))
- },
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Tried to perform \"||\" on non-boolean strings"
+ ))
+ }
(Bool(v1), Bool(v2)) => self.stack.push(Bool(v1 || v2)),
- (Null, _) => return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"||\" on non-boolean value null")),
- (_, Null) => return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"||\" on non-boolean value null")),
+ (Null, _) => {
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Tried to perform \"||\" on non-boolean value null"
+ ))
+ }
+ (_, Null) => {
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Tried to perform \"||\" on non-boolean value null"
+ ))
+ }
(v1, v2) => {
- return Err(vm_error!(self, RuntimeErrorKind::MismatchedTypes, "Mismatched types: {} and {}", v1.type_str(), v2.type_str()))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::MismatchedTypes,
+ "Mismatched types: {} and {}",
+ v1.type_str(),
+ v2.type_str()
+ ))
}
- }
+ },
// AND
0x15 => match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) {
(Num(_v1), Num(_v2)) => {
- return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"&&\" on non-boolean numbers"))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Tried to perform \"&&\" on non-boolean numbers"
+ ))
}
(Str(_v1), Str(_v2)) => {
- return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"&&\" on non-boolean strings"))
- },
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Tried to perform \"&&\" on non-boolean strings"
+ ))
+ }
(Bool(v1), Bool(v2)) => self.stack.push(Bool(v1 && v2)),
- (Null, _) => return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"&&\" on non-boolean value null")),
- (_, Null) => return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"&&\" on non-boolean value null")),
+ (Null, _) => {
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Tried to perform \"&&\" on non-boolean value null"
+ ))
+ }
+ (_, Null) => {
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Tried to perform \"&&\" on non-boolean value null"
+ ))
+ }
(v1, v2) => {
- return Err(vm_error!(self, RuntimeErrorKind::MismatchedTypes, "Mismatched types: {} and {}", v1.type_str(), v2.type_str()))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::MismatchedTypes,
+ "Mismatched types: {} and {}",
+ v1.type_str(),
+ v2.type_str()
+ ))
}
- }
+ },
// NOT
0x16 => match self.stack.pop().unwrap() {
- Null => { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"!\" on non-boolean value null")) }
+ Null => {
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Tried to perform \"!\" on non-boolean value null"
+ ))
+ }
Num(_v1) => {
- return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"!\" on non-boolean number"))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Tried to perform \"!\" on non-boolean number"
+ ))
}
Str(_v1) => {
- return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"!\" on non-boolean string"))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Tried to perform \"!\" on non-boolean string"
+ ))
}
Bool(v1) => self.stack.push(Bool(!v1)),
List(_v1) => {
- return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"!\" on non-boolean list"))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Tried to perform \"!\" on non-boolean list"
+ ))
}
Fun(_v1) => {
- return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"!\" on non-boolean function"))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Tried to perform \"!\" on non-boolean function"
+ ))
}
Ref(_v1) => {
- return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"!\" on non-boolean reference"))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Tried to perform \"!\" on non-boolean reference"
+ ))
}
- }
+ },
// NEG
0x17 => match self.stack.pop().unwrap() {
- Null => { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"-\" on non-number value null")) }
+ Null => {
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Tried to perform \"-\" on non-number value null"
+ ))
+ }
Num(v1) => self.stack.push(Num(-v1)),
Str(_v1) => {
- return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"-\" on non-number string"))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Tried to perform \"-\" on non-number string"
+ ))
}
Bool(_v1) => {
- return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"-\" on non-number boolean"))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Tried to perform \"-\" on non-number boolean"
+ ))
}
List(_v1) => {
- return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"!\" on non-number list"))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Tried to perform \"!\" on non-number list"
+ ))
}
Fun(_v1) => {
- return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"-\" on non-number function"))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Tried to perform \"-\" on non-number function"
+ ))
}
Ref(_v1) => {
- return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"-\" on non-number reference"))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Tried to perform \"-\" on non-number reference"
+ ))
}
- }
+ },
// JMP
0x18 => {
let loc = self.read_u16();
@@ 357,7 640,11 @@ impl VM {
self.read_u16();
}
} else {
- return Err(vm_error!(self, RuntimeErrorKind::WrongType, "if must have condition of type boolean"))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "if must have condition of type boolean"
+ ));
}
}
@@ 367,20 654,34 @@ impl VM {
let function = self.stack.pop().expect("Stack was empty in call");
if let Value::Fun(function) = function {
if num_args as usize != function.arity {
- return Err(vm_error!(self, RuntimeErrorKind::IncorrectArity, "Function has {} arguments, {} provided", function.arity, num_args))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::IncorrectArity,
+ "Function has {} arguments, {} provided",
+ function.arity,
+ num_args
+ ));
}
self.variables_offset = self.stack.len() - num_args as usize;
- self.call_stack.push((self.unit_ptr, self.ip, self.variables_offset));
- self.stack.insert(self.stack.len()-num_args as usize, Value::Fun(function));
+ self.call_stack
+ .push((self.unit_ptr, self.ip, self.variables_offset));
+ self.stack
+ .insert(self.stack.len() - num_args as usize, Value::Fun(function));
self.ip = 0;
self.unit_ptr = function.unit_ptr as usize;
} else {
- return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to call non-function type {}", function.type_str()))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Tried to call non-function type {}",
+ function.type_str()
+ ));
}
}
// RET
0x1C => {
- let (unit_ptr, ip, variables_offset) = self.call_stack.pop().expect("Call stack empty on RET");
+ let (unit_ptr, ip, variables_offset) =
+ self.call_stack.pop().expect("Call stack empty on RET");
let ret = self.stack.pop().expect("Missing return value");
self.stack = self.stack[..variables_offset].to_vec();
self.variables_offset = self.call_stack.last().expect("call stack empty").2;
@@ 393,7 694,10 @@ impl VM {
// LIST
0x1D => {
let len = self.read();
- let list = self.stack.drain(self.stack.len()-len as usize..).collect();
+ let list = self
+ .stack
+ .drain(self.stack.len() - len as usize..)
+ .collect();
self.stack.push(Value::List(list));
}
// SCR
@@ 402,29 706,54 @@ impl VM {
let list = self.stack.pop().expect("stack empty on subscript list");
if let Value::Num(index) = index {
if index.fract() != 0.0 {
- return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Subscript index must be an integer but found {}", index))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Subscript index must be an integer but found {}",
+ index
+ ));
}
let index = index as usize;
if let Value::List(list) = list {
if index > list.len() {
- return Err(vm_error!(self, RuntimeErrorKind::ArrayOutOfBounds, "List length is {} but found index {}", list.len(), index))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::ArrayOutOfBounds,
+ "List length is {} but found index {}",
+ list.len(),
+ index
+ ));
}
self.stack.push(list[index].clone());
} else {
- return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to subscript non-list type {}", list.type_str()))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Tried to subscript non-list type {}",
+ list.type_str()
+ ));
}
} else {
- return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to use non-integer type {} to subscript list", index.type_str()))
+ return Err(vm_error!(
+ self,
+ RuntimeErrorKind::WrongType,
+ "Tried to use non-integer type {} to subscript list",
+ index.type_str()
+ ));
}
}
- 0xFD => { // POP
+ 0xFD => {
+ // POP
let times = self.read();
for _ in 0..times {
- self.stack.pop().expect(&format!("{}: Unable to pop stack", self.ip));
+ self.stack
+ .pop()
+ .expect(&format!("{}: Unable to pop stack", self.ip));
}
}
- 0xFE => { // PRINT
+ 0xFE => {
+ // PRINT
let value = self.stack.pop().unwrap();
/*match value {
Null => *output += "null",
@@ 460,7 789,8 @@ impl VM {
self.ip += 1;
byte_one | byte_two
}
- pub fn find_line(&self) -> usize { // returns line # at ip
+ pub fn find_line(&self) -> usize {
+ // returns line # at ip
let mut line_ip = 0;
for (line, rep) in self.units[self.unit_ptr].lines.clone() {
if line_ip + rep > self.ip {
@@ 474,7 804,12 @@ impl VM {
#[derive(Debug, Clone)]
pub enum Value {
- Null, Num(f32), Str(String), Bool(bool), List(Vec<Value>), Fun(Function),
+ Null,
+ Num(f32),
+ Str(String),
+ Bool(bool),
+ List(Vec<Value>),
+ Fun(Function),
Ref(usize),
}
@@ 510,7 845,7 @@ impl ToString for Value {
output
}
Fun(v) => format!("<function {}>", v.unit_ptr),
- Ref(v) => format!("<reference {}>", v)
+ Ref(v) => format!("<reference {}>", v),
}
}
}
M crates/server/src/crafting/components.rs => crates/server/src/crafting/components.rs +9 -10
@@ 5,16 5,16 @@ use starkingdoms_common::PlanetType;
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub enum MaterialType {
- Plasma, // Sun
+ Plasma, // Sun
Composite, // Mercury
- Sulfur, // Venus
- Silicon, // Moon
- Iron, // Mars
- Hydrogen, // Jupiter
- Helium, // Saturn
- Rubber, // Uranus
- Methane, // Neptune
- Ice, // Pluto
+ Sulfur, // Venus
+ Silicon, // Moon
+ Iron, // Mars
+ Hydrogen, // Jupiter
+ Helium, // Saturn
+ Rubber, // Uranus
+ Methane, // Neptune
+ Ice, // Pluto
}
impl TryFrom<PlanetType> for MaterialType {
type Error = ();
@@ 50,4 50,3 @@ pub struct VarietyMaterialStorage {
#[derive(Component, Debug, Clone, Default)]
pub struct IsMining(pub bool);
-
M crates/server/src/crafting/mining.rs => crates/server/src/crafting/mining.rs +25 -10
@@ 1,16 1,25 @@
-use bevy::prelude::{Children, Entity, Query, Res, With};
-use bevy_rapier2d::plugin::RapierContext;
use crate::{module::component::Attach, planet::PlanetType};
+use bevy::prelude::{Children, Entity, Query, Res};
+use bevy_rapier2d::plugin::RapierContext;
-use super::components::{IsMining, MaterialType, VarietyMaterialStorage};
+use super::components::{IsMining, VarietyMaterialStorage};
pub fn mine_materials(
rapier_context: Res<RapierContext>,
planet_query: Query<(&PlanetType, &Children)>,
- mut mineable_query: Query<(Entity, &mut Attach, Option<&IsMining>, Option<&mut VarietyMaterialStorage>)>,
+ mut mineable_query: Query<(
+ Entity,
+ &mut Attach,
+ Option<&IsMining>,
+ Option<&mut VarietyMaterialStorage>,
+ )>,
) {
for (planet_type, children) in &planet_query {
- for (entity1, entity2, intersecting) in rapier_context.intersection_pairs_with(*children.first().unwrap()) {
- if !intersecting { continue }
+ for (entity1, entity2, intersecting) in
+ rapier_context.intersection_pairs_with(*children.first().unwrap())
+ {
+ if !intersecting {
+ continue;
+ }
let other = if *children.first().unwrap() == entity1 {
entity2
} else {
@@ 22,7 31,7 @@ pub fn mine_materials(
};
let associated_player = match attach.associated_player {
Some(e) => e,
- None => entity
+ None => entity,
};
// is the module mining
if let Some(mineable) = mineable {
@@ 33,7 42,9 @@ pub fn mine_materials(
if let Ok(material) = planet_type.0.try_into() {
match storage.materials.get_mut(&material) {
Some(v) => *v += 1,
- None => { storage.materials.insert(material, 1); }
+ None => {
+ storage.materials.insert(material, 1);
+ }
}
}
}
@@ 45,7 56,12 @@ pub fn mine_materials(
}
pub fn find_storage(
player: Entity,
- mineable_query: &Query<(Entity, &mut Attach, Option<&IsMining>, Option<&mut VarietyMaterialStorage>)>,
+ mineable_query: &Query<(
+ Entity,
+ &mut Attach,
+ Option<&IsMining>,
+ Option<&mut VarietyMaterialStorage>,
+ )>,
) -> Option<Entity> {
for (entity, attach, _, storage) in mineable_query.iter() {
if let Some(storage) = storage {
@@ 65,7 81,6 @@ pub fn find_storage(
return Some(entity);
}
}
-
}
return None;
}
M crates/server/src/module/mod.rs => crates/server/src/module/mod.rs +5 -5
@@ 11,8 11,7 @@ use starkingdoms_common::proto_transform;
use crate::ws::PacketMessageConvert;
use crate::{
- capacity, config::StkConfig, part, planet::PlanetType, player::component::Player,
- ws::WsEvent,
+ capacity, config::StkConfig, part, planet::PlanetType, player::component::Player, ws::WsEvent,
};
use starkingdoms_common::PartType as c_PartType;
use starkingdoms_common::PlanetType as c_PlanetType;
@@ 123,7 122,7 @@ pub fn detach_recursive(
energy += capacity!(*part_type);
commands.entity(entity).remove::<Attach>();
flags.attached = false;
- if *part_type == c_PartType::LandingThrusterSuspension .into(){
+ if *part_type == c_PartType::LandingThrusterSuspension.into() {
let parent = attach.parent.unwrap();
let parent_attach = attached_query.get(parent).unwrap().3;
commands.entity(parent).insert(LooseAttach {
@@ 565,7 564,8 @@ fn convert_modules_recursive(
});
attach.children[2] = Some(suspension.id());
- increase_capacity_by += part!(c_PartType::LandingThruster.into()).energy_capacity;
+ increase_capacity_by +=
+ part!(c_PartType::LandingThruster.into()).energy_capacity;
let packet = Packet::DespawnPart { id: child.index() };
@@ 652,7 652,7 @@ pub fn break_modules(
}
let handle = match joints.get(&entity) {
Some(handle) => handle,
- None => continue
+ None => continue,
};
let joint = rapier_context.impulse_joints.get(*handle).unwrap();
if joint.impulses.magnitude() > 2.0 {
M crates/server/src/module/save.rs => crates/server/src/module/save.rs +5 -2
@@ 5,8 5,11 @@ use bevy_rapier2d::prelude::*;
use starkingdoms_common::{packet::Packet, PartType as c_PartType, SaveModule};
use crate::{
- capacity, mass, planet::PlanetType, player::component::Player, ws::{PacketMessageConvert, WsEvent}, Attach, CanAttach,
- LooseAttach, PartBundle, PartFlags, PartType,
+ capacity, mass,
+ planet::PlanetType,
+ player::component::Player,
+ ws::{PacketMessageConvert, WsEvent},
+ Attach, CanAttach, LooseAttach, PartBundle, PartFlags, PartType,
};
pub fn load_savefile(
M crates/server/src/planet.rs => crates/server/src/planet.rs +57 -19
@@ 29,7 29,9 @@ pub fn spawn_planets(mut commands: Commands) {
.insert(ReadMassProperties::default())
.with_children(|children| {
children
- .spawn(Collider::ball(planet!(PlanetType(c_PlanetType::Sun)).size + 0.3))
+ .spawn(Collider::ball(
+ planet!(PlanetType(c_PlanetType::Sun)).size + 0.3,
+ ))
.insert(ActiveEvents::COLLISION_EVENTS)
.insert(Sensor);
})
@@ 40,14 42,18 @@ pub fn spawn_planets(mut commands: Commands) {
planet_type: PlanetType(c_PlanetType::Mercury),
transform: TransformBundle::from(mercury_pos),
})
- .insert(Collider::ball(planet!(PlanetType(c_PlanetType::Mercury)).size))
+ .insert(Collider::ball(
+ planet!(PlanetType(c_PlanetType::Mercury)).size,
+ ))
.insert(AdditionalMassProperties::Mass(
planet!(PlanetType(c_PlanetType::Mercury)).mass,
))
.insert(ReadMassProperties::default())
.with_children(|children| {
children
- .spawn(Collider::ball(planet!(PlanetType(c_PlanetType::Mercury)).size + 0.3))
+ .spawn(Collider::ball(
+ planet!(PlanetType(c_PlanetType::Mercury)).size + 0.3,
+ ))
.insert(ActiveEvents::COLLISION_EVENTS)
.insert(Sensor);
})
@@ 58,14 64,18 @@ pub fn spawn_planets(mut commands: Commands) {
planet_type: PlanetType(c_PlanetType::Venus),
transform: TransformBundle::from(venus_pos),
})
- .insert(Collider::ball(planet!(PlanetType(c_PlanetType::Venus)).size))
+ .insert(Collider::ball(
+ planet!(PlanetType(c_PlanetType::Venus)).size,
+ ))
.insert(AdditionalMassProperties::Mass(
planet!(PlanetType(c_PlanetType::Venus)).mass,
))
.insert(ReadMassProperties::default())
.with_children(|children| {
children
- .spawn(Collider::ball(planet!(PlanetType(c_PlanetType::Venus)).size + 0.3))
+ .spawn(Collider::ball(
+ planet!(PlanetType(c_PlanetType::Venus)).size + 0.3,
+ ))
.insert(ActiveEvents::COLLISION_EVENTS)
.insert(Sensor);
})
@@ 76,14 86,18 @@ pub fn spawn_planets(mut commands: Commands) {
planet_type: PlanetType(c_PlanetType::Earth),
transform: TransformBundle::from(earth_pos),
})
- .insert(Collider::ball(planet!(PlanetType(c_PlanetType::Earth)).size))
+ .insert(Collider::ball(
+ planet!(PlanetType(c_PlanetType::Earth)).size,
+ ))
.insert(AdditionalMassProperties::Mass(
planet!(PlanetType(c_PlanetType::Earth)).mass,
))
.insert(ReadMassProperties::default())
.with_children(|children| {
children
- .spawn(Collider::ball(planet!(PlanetType(c_PlanetType::Earth)).size + 0.3))
+ .spawn(Collider::ball(
+ planet!(PlanetType(c_PlanetType::Earth)).size + 0.3,
+ ))
.insert(ActiveEvents::COLLISION_EVENTS)
.insert(Sensor);
})
@@ 101,7 115,9 @@ pub fn spawn_planets(mut commands: Commands) {
.insert(ReadMassProperties::default())
.with_children(|children| {
children
- .spawn(Collider::ball(planet!(PlanetType(c_PlanetType::Moon)).size + 0.1))
+ .spawn(Collider::ball(
+ planet!(PlanetType(c_PlanetType::Moon)).size + 0.1,
+ ))
.insert(ActiveEvents::COLLISION_EVENTS)
.insert(Sensor);
})
@@ 119,7 135,9 @@ pub fn spawn_planets(mut commands: Commands) {
.insert(ReadMassProperties::default())
.with_children(|children| {
children
- .spawn(Collider::ball(planet!(PlanetType(c_PlanetType::Mars)).size + 0.1))
+ .spawn(Collider::ball(
+ planet!(PlanetType(c_PlanetType::Mars)).size + 0.1,
+ ))
.insert(ActiveEvents::COLLISION_EVENTS)
.insert(Sensor);
})
@@ 130,14 148,18 @@ pub fn spawn_planets(mut commands: Commands) {
planet_type: PlanetType(c_PlanetType::Jupiter),
transform: TransformBundle::from(jupiter_pos),
})
- .insert(Collider::ball(planet!(PlanetType(c_PlanetType::Jupiter)).size))
+ .insert(Collider::ball(
+ planet!(PlanetType(c_PlanetType::Jupiter)).size,
+ ))
.insert(AdditionalMassProperties::Mass(
planet!(PlanetType(c_PlanetType::Jupiter)).mass,
))
.insert(ReadMassProperties::default())
.with_children(|children| {
children
- .spawn(Collider::ball(planet!(PlanetType(c_PlanetType::Jupiter)).size + 0.1))
+ .spawn(Collider::ball(
+ planet!(PlanetType(c_PlanetType::Jupiter)).size + 0.1,
+ ))
.insert(ActiveEvents::COLLISION_EVENTS)
.insert(Sensor);
})
@@ 148,14 170,18 @@ pub fn spawn_planets(mut commands: Commands) {
planet_type: PlanetType(c_PlanetType::Saturn),
transform: TransformBundle::from(saturn_pos),
})
- .insert(Collider::ball(planet!(PlanetType(c_PlanetType::Saturn)).size))
+ .insert(Collider::ball(
+ planet!(PlanetType(c_PlanetType::Saturn)).size,
+ ))
.insert(AdditionalMassProperties::Mass(
planet!(PlanetType(c_PlanetType::Saturn)).mass,
))
.insert(ReadMassProperties::default())
.with_children(|children| {
children
- .spawn(Collider::ball(planet!(PlanetType(c_PlanetType::Saturn)).size + 0.1))
+ .spawn(Collider::ball(
+ planet!(PlanetType(c_PlanetType::Saturn)).size + 0.1,
+ ))
.insert(ActiveEvents::COLLISION_EVENTS)
.insert(Sensor);
})
@@ 166,14 192,18 @@ pub fn spawn_planets(mut commands: Commands) {
planet_type: PlanetType(c_PlanetType::Uranus),
transform: TransformBundle::from(uranus_pos),
})
- .insert(Collider::ball(planet!(PlanetType(c_PlanetType::Uranus)).size))
+ .insert(Collider::ball(
+ planet!(PlanetType(c_PlanetType::Uranus)).size,
+ ))
.insert(AdditionalMassProperties::Mass(
planet!(PlanetType(c_PlanetType::Uranus)).mass,
))
.insert(ReadMassProperties::default())
.with_children(|children| {
children
- .spawn(Collider::ball(planet!(PlanetType(c_PlanetType::Uranus)).size + 0.1))
+ .spawn(Collider::ball(
+ planet!(PlanetType(c_PlanetType::Uranus)).size + 0.1,
+ ))
.insert(ActiveEvents::COLLISION_EVENTS)
.insert(Sensor);
})
@@ 184,14 214,18 @@ pub fn spawn_planets(mut commands: Commands) {
planet_type: PlanetType(c_PlanetType::Neptune),
transform: TransformBundle::from(neptune_pos),
})
- .insert(Collider::ball(planet!(PlanetType(c_PlanetType::Neptune)).size))
+ .insert(Collider::ball(
+ planet!(PlanetType(c_PlanetType::Neptune)).size,
+ ))
.insert(AdditionalMassProperties::Mass(
planet!(PlanetType(c_PlanetType::Neptune)).mass,
))
.insert(ReadMassProperties::default())
.with_children(|children| {
children
- .spawn(Collider::ball(planet!(PlanetType(c_PlanetType::Neptune)).size + 0.1))
+ .spawn(Collider::ball(
+ planet!(PlanetType(c_PlanetType::Neptune)).size + 0.1,
+ ))
.insert(ActiveEvents::COLLISION_EVENTS)
.insert(Sensor);
})
@@ 202,14 236,18 @@ pub fn spawn_planets(mut commands: Commands) {
planet_type: PlanetType(c_PlanetType::Pluto),
transform: TransformBundle::from(pluto_pos),
})
- .insert(Collider::ball(planet!(PlanetType(c_PlanetType::Pluto)).size))
+ .insert(Collider::ball(
+ planet!(PlanetType(c_PlanetType::Pluto)).size,
+ ))
.insert(AdditionalMassProperties::Mass(
planet!(PlanetType(c_PlanetType::Pluto)).mass,
))
.insert(ReadMassProperties::default())
.with_children(|children| {
children
- .spawn(Collider::ball(planet!(PlanetType(c_PlanetType::Pluto)).size + 0.1))
+ .spawn(Collider::ball(
+ planet!(PlanetType(c_PlanetType::Pluto)).size + 0.1,
+ ))
.insert(ActiveEvents::COLLISION_EVENTS)
.insert(Sensor);
})
M crates/server/src/player/client_login.rs => crates/server/src/player/client_login.rs +16 -7
@@ 6,13 6,21 @@ use hmac::{Hmac, Mac};
use jwt::VerifyWithKey;
use rand::Rng;
use sha2::Sha256;
-use starkingdoms_common::{packet::{MessageType, Packet, Part, Planet, ProtoPartFlags}, proto_part_flags, proto_transform, unpack_savefile, PartType as c_PartType, PlanetType as c_PlanetType};
+use starkingdoms_common::{
+ packet::{MessageType, Packet, Part, Planet, ProtoPartFlags},
+ proto_part_flags, proto_transform, unpack_savefile, PartType as c_PartType,
+};
use crate::{
- config::StkConfig, crafting::components::{IsMining, VarietyMaterialStorage}, module::{
+ config::StkConfig,
+ crafting::components::{IsMining, VarietyMaterialStorage},
+ module::{
component::{Attach, CanAttach, LooseAttach, PartBundle, PartFlags, PartType},
save::load_savefile,
- }, planet::PlanetType, ws::{PacketMessageConvert, WsEvent}, AppKeys, UserToken, CLIENT_SCALE
+ },
+ planet::PlanetType,
+ ws::{PacketMessageConvert, WsEvent},
+ AppKeys, UserToken, CLIENT_SCALE,
};
use super::component::{Input, Player};
@@ 232,9 240,7 @@ pub fn packet_stream(
transform: Transform,
) {
// response in the handshake
- let packet = Packet::LoginResponse {
- id: index,
- };
+ let packet = Packet::LoginResponse { id: index };
event_queue.push(WsEvent::Send {
to: *from,
message: packet.into_message(),
@@ 324,7 330,10 @@ pub fn packet_stream(
},
));
for part in parts {
- let packet = Packet::SpawnPart { id: part.0, part: part.1 };
+ let packet = Packet::SpawnPart {
+ id: part.0,
+ part: part.1,
+ };
event_queue.push(WsEvent::Send {
to: *from,
message: packet.into_message(),
M crates/server/src/player/mod.rs => crates/server/src/player/mod.rs +15 -4
@@ 8,10 8,18 @@ use send_message::send_message;
use starkingdoms_common::{packet::Packet, PartType as c_PartType};
use crate::{
- config::StkConfig, crafting::components::IsMining, err_or_cont, mathutil::rot2d, module::{
+ config::StkConfig,
+ crafting::components::IsMining,
+ err_or_cont,
+ mathutil::rot2d,
+ module::{
component::{Attach, CanAttach, LooseAttach, PartFlags, PartType},
PART_HALF_SIZE,
- }, part, planet::PlanetType, ws::{PacketMessageConvert, WsEvent}, AppKeys, CLIENT_SCALE
+ },
+ part,
+ planet::PlanetType,
+ ws::{PacketMessageConvert, WsEvent},
+ AppKeys, CLIENT_SCALE,
};
pub mod client_login;
@@ 294,12 302,15 @@ pub fn player_input_update(
// process each thruster on hearty
for (force_multiplier, x_offset, y_offset) in thrusters {
- if force_multiplier != 0.0 && player.energy >= part!(c_PartType::Hearty.into()).thruster_energy {
+ if force_multiplier != 0.0
+ && player.energy >= part!(c_PartType::Hearty.into()).thruster_energy
+ {
player.energy -= part!(c_PartType::Hearty.into()).thruster_energy;
let thruster_pos_uncast = vec2(x_offset, y_offset);
let thruster_pos_cast =
rot2d(thruster_pos_uncast, rot) + transform.translation.xy();
- let thruster_force = force_multiplier * part!(c_PartType::Hearty.into()).thruster_force;
+ let thruster_force =
+ force_multiplier * part!(c_PartType::Hearty.into()).thruster_force;
let thruster_vec = vec2(-thruster_force * rot.sin(), thruster_force * rot.cos());
let thruster_force = ExternalForce::at_point(
thruster_vec,
M crates/server/src/player/packet.rs => crates/server/src/player/packet.rs +4 -1
@@ 1,5 1,8 @@
use bevy::{ecs::event::ManualEventReader, prelude::*};
-use starkingdoms_common::{packet::{Packet, Part, Planet}, proto_part_flags, proto_transform};
+use starkingdoms_common::{
+ packet::{Packet, Part, Planet},
+ proto_part_flags, proto_transform,
+};
use crate::{
module::component::{Attach, PartFlags, PartType},
M crates/server/src/player/player_mouse_input.rs => crates/server/src/player/player_mouse_input.rs +9 -5
@@ 2,9 2,15 @@ use bevy::{math::vec3, prelude::*};
use bevy_rapier2d::prelude::*;
use crate::{
- crafting::components::IsMining, module::component::{Attach, CanAttach, LooseAttach, PartFlags, PartType}, planet::PlanetType, ws::{PacketMessageConvert, WsEvent}
+ crafting::components::IsMining,
+ module::component::{Attach, CanAttach, LooseAttach, PartFlags, PartType},
+ planet::PlanetType,
+ ws::{PacketMessageConvert, WsEvent},
+};
+use starkingdoms_common::{
+ packet::{ButtonType, Packet},
+ PartType as c_PartType,
};
-use starkingdoms_common::{packet::{ButtonType, Packet}, PartType as c_PartType};
use super::component::Player;
@@ 187,9 193,7 @@ pub fn mouse_picking(
if *button == ButtonType::Right {
send_events.push(WsEvent::Send {
to: q_player.addr,
- message: Packet::OpenCraftingUi {
- id: entity.index(),
- }.into_message(),
+ message: Packet::OpenCraftingUi { id: entity.index() }.into_message(),
});
// toggle mining
/*if let Ok(mut is_mining) = mining_query.get_mut(entity) {
M crates/xtask/src/main.rs => crates/xtask/src/main.rs +50 -34
@@ 1,18 1,15 @@
+use colored::Colorize;
+use notify::{Event, EventKind, RecursiveMode, Watcher};
use std::env::{args, var};
-use std::error::Error;
use std::fs;
-use std::io::{Cursor, Read};
-use std::net::{SocketAddr, TcpListener, TcpStream};
+use std::io::Cursor;
use std::path::{Path, PathBuf};
-use std::process::{Command, exit};
-use std::str::FromStr;
+use std::process::exit;
use std::sync::mpsc;
use std::sync::mpsc::TryRecvError;
use std::thread::sleep;
use std::time::Duration;
-use colored::Colorize;
-use notify::{Event, EventKind, RecursiveMode, Watcher};
-use tiny_http::{Header, HeaderField, Response, Server, StatusCode};
+use tiny_http::{Response, Server, StatusCode};
use wasm_pack::command::build::{BuildOptions, Target};
use wasm_pack::command::run_wasm_pack;
use wasm_pack::progressbar::LogLevel;
@@ 59,11 56,18 @@ fn build_client() -> anyhow::Result<()> {
fn try_build_client() -> bool {
match build_client() {
Ok(_) => {
- println!("{} -- Client package built successfully", "✓ Success".green().bold());
+ println!(
+ "{} -- Client package built successfully",
+ "✓ Success".green().bold()
+ );
true
- },
+ }
Err(e) => {
- eprintln!("{} -- Client package failed to build: {}", "✗ Failed".red().bold(), e);
+ eprintln!(
+ "{} -- Client package failed to build: {}",
+ "✗ Failed".red().bold(),
+ e
+ );
false
}
}
@@ 78,15 82,21 @@ fn start_server() {
if path == Path::new("/") {
path = Path::new("/index.html");
}
-
+
let path = path.strip_prefix(Path::new("/")).unwrap();
-
+
let full_path = workspace_dir().join("crates/client").join(path);
-
+
let content = match fs::read(full_path.clone()) {
Ok(r) => r,
Err(_) => {
- let _ = req.respond(Response::new(StatusCode::from(404), vec![], Cursor::new(vec![]), None, None));
+ let _ = req.respond(Response::new(
+ StatusCode::from(404),
+ vec![],
+ Cursor::new(vec![]),
+ None,
+ None,
+ ));
continue;
}
};
@@ 103,17 113,16 @@ fn start_server() {
&b"application/wasm"[..]
} else {
&b"application/octet-stream"[..]
- }
- ).unwrap();
-
+ },
+ )
+ .unwrap();
+
let response = Response::new(
StatusCode::from(200),
- vec![
- header
- ],
+ vec![header],
Cursor::new(content),
Some(len),
- None
+ None,
);
let _ = req.respond(response);
}
@@ 128,7 137,7 @@ fn main() {
if !try_build_client() {
exit(1);
}
- },
+ }
"watch" | "serve" => {
let serve = subcommand == "serve";
@@ 147,7 156,9 @@ fn main() {
// Add a path to be watched. All files and directories at that path and
// below will be monitored for changes.
- watcher.watch(&workspace_dir().join("crates"), RecursiveMode::Recursive).unwrap();
+ watcher
+ .watch(&workspace_dir().join("crates"), RecursiveMode::Recursive)
+ .unwrap();
println!("{}", "[Watch] 🛈 Watching for file changes".blue().bold());
// Block forever, printing out events as they come in
@@ 173,28 184,33 @@ fn main() {
} else {
rx.recv().unwrap()
}
- },
- Err(TryRecvError::Disconnected) => panic!("{:?}", TryRecvError::Disconnected)
+ }
+ Err(TryRecvError::Disconnected) => panic!("{:?}", TryRecvError::Disconnected),
};
match res {
Ok(event) => {
if let EventKind::Modify(_) = event.kind {
- let mut has_non_generated_update = false;
+ let has_non_generated_update = false;
for path in &event.paths {
- if !path.to_str().unwrap().contains("client/pkg") && !path.to_str().unwrap().ends_with("~") {
+ if !path.to_str().unwrap().contains("client/pkg")
+ && !path.to_str().unwrap().ends_with("~")
+ {
needs_rebuild = true;
}
}
}
-
- },
+ }
Err(e) => {
- eprintln!("{} -- Error watching for files: {}", "[Watch] ✗ Error".red().bold(), e);
- },
+ eprintln!(
+ "{} -- Error watching for files: {}",
+ "[Watch] ✗ Error".red().bold(),
+ e
+ );
+ }
}
}
- },
- _ => panic!("unsupported command")
+ }
+ _ => panic!("unsupported command"),
}
}