device templates exist now

This commit is contained in:
Rachel Powers
2024-04-15 21:30:05 -07:00
parent 10d5db967c
commit 4e6ac09c5e
9 changed files with 108 additions and 29 deletions

1
Cargo.lock generated
View File

@@ -588,6 +588,7 @@ dependencies = [
"serde", "serde",
"serde-wasm-bindgen 0.6.5", "serde-wasm-bindgen 0.6.5",
"serde_with", "serde_with",
"strum",
"thiserror", "thiserror",
"tsify", "tsify",
"wasm-bindgen", "wasm-bindgen",

View File

@@ -449,8 +449,8 @@ impl Network {
#[derive(Debug, Default, Clone, Serialize, Deserialize)] #[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub struct Prefab { pub struct Prefab {
name: String, pub name: String,
hash: i32, pub hash: i32,
} }
impl Prefab { impl Prefab {
@@ -481,7 +481,7 @@ pub struct DeviceTemplate {
pub name: Option<String>, pub name: Option<String>,
pub prefab_name: Option<String>, pub prefab_name: Option<String>,
pub slots: Vec<SlotTemplate>, pub slots: Vec<SlotTemplate>,
pub reagents: HashMap<ReagentMode, HashMap<i32, f64>>, // pub reagents: HashMap<ReagentMode, HashMap<i32, f64>>,
pub connections: Vec<Connection>, pub connections: Vec<Connection>,
pub fields: HashMap<LogicType, LogicField>, pub fields: HashMap<LogicType, LogicField>,
} }
@@ -1089,7 +1089,8 @@ impl VM {
name_hash, name_hash,
prefab: template.prefab_name.map(|name| Prefab::new(&name)), prefab: template.prefab_name.map(|name| Prefab::new(&name)),
slots, slots,
reagents: template.reagents, // reagents: template.reagents,
reagents: HashMap::new(),
ic, ic,
connections: template.connections, connections: template.connections,
fields, fields,

View File

@@ -21,6 +21,11 @@ serde_with = "3.7.0"
tsify = { version = "0.4.5", default-features = false, features = ["js", "wasm-bindgen"] } tsify = { version = "0.4.5", default-features = false, features = ["js", "wasm-bindgen"] }
thiserror = "1.0.58" thiserror = "1.0.58"
[build-dependencies]
ic10emu = { path = "../ic10emu" }
strum = { version = "0.26.2"}
itertools = "0.12.1"
[features] [features]
default = ["console_error_panic_hook"] default = ["console_error_panic_hook"]
console_error_panic_hook = ["dep:console_error_panic_hook"] console_error_panic_hook = ["dep:console_error_panic_hook"]

View File

@@ -5,18 +5,59 @@ use std::{
path::Path, path::Path,
}; };
use itertools::Itertools;
use strum::IntoEnumIterator;
fn main() { fn main() {
let out_dir = env::var_os("OUT_DIR").unwrap(); let out_dir = env::var_os("OUT_DIR").unwrap();
let dest_path = Path::new(&out_dir).join("ts_types.rs"); let dest_path = Path::new(&out_dir).join("ts_types.rs");
let output_file = File::create(dest_path).unwrap(); let output_file = File::create(dest_path).unwrap();
let mut writer = BufWriter::new(&output_file); let mut writer = BufWriter::new(&output_file);
let mut ts_types: String = String::new();
let lt_tsunion: String = Itertools::intersperse(
ic10emu::grammar::generated::LogicType::iter().map(|lt| format!("\"{}\"", lt.as_ref())),
"\n | ".to_owned(),
)
.collect();
let lt_tstype = format!("\nexport type LogicType = {};", lt_tsunion);
ts_types.push_str(&lt_tstype);
let slt_tsunion: String = Itertools::intersperse(
ic10emu::grammar::generated::SlotLogicType::iter().map(|slt| format!("\"{}\"", slt.as_ref())),
"\n | ".to_owned(),
)
.collect();
let slt_tstype = format!("\nexport type SlotLogicType = {};", slt_tsunion);
ts_types.push_str(&slt_tstype);
let bm_tsunion: String = Itertools::intersperse(
ic10emu::grammar::generated::BatchMode::iter().map(|bm| format!("\"{}\"", bm.as_ref())),
"\n | ".to_owned(),
)
.collect();
let bm_tstype = format!("\nexport type BatchMode = {};", bm_tsunion);
ts_types.push_str(&bm_tstype);
let rm_tsunion: String = Itertools::intersperse(
ic10emu::grammar::generated::ReagentMode::iter().map(|rm| format!("\"{}\"", rm.as_ref())),
"\n | ".to_owned(),
)
.collect();
let rm_tstype = format!("\nexport type ReagentMode = {};", rm_tsunion);
ts_types.push_str(&rm_tstype);
let infile = Path::new("src/types.ts"); let infile = Path::new("src/types.ts");
let contents = fs::read_to_string(infile).unwrap(); let contents = fs::read_to_string(infile).unwrap();
ts_types.push('\n');
ts_types.push_str(&contents);
write!( write!(
&mut writer, &mut writer,
"#[wasm_bindgen(typescript_custom_section)]\n\ "#[wasm_bindgen(typescript_custom_section)]\n\
const TYPES: &'static str = r#\"{contents}\"#; const TYPES: &'static str = r#\"{ts_types}\"#;
" "
) )
.unwrap(); .unwrap();

View File

@@ -2,7 +2,7 @@
mod utils; mod utils;
mod types; mod types;
use ic10emu::grammar::{LogicType, SlotLogicType}; use ic10emu::{grammar::{LogicType, SlotLogicType}, DeviceTemplate};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use types::{Registers, Stack}; use types::{Registers, Stack};
@@ -55,18 +55,18 @@ impl DeviceRef {
} }
#[wasm_bindgen(getter, js_name = "nameHash")] #[wasm_bindgen(getter, js_name = "nameHash")]
pub fn name_hash(&self) -> Option<f64> { pub fn name_hash(&self) -> Option<i32> {
self.device.borrow().name_hash self.device.borrow().name_hash
} }
#[wasm_bindgen(getter, js_name = "prefabName")] #[wasm_bindgen(getter, js_name = "prefabName")]
pub fn prefab_name(&self) -> Option<String> { pub fn prefab_name(&self) -> Option<String> {
self.device.borrow().prefab_name.clone() self.device.borrow().prefab.as_ref().map(|prefab| prefab.name.clone())
} }
#[wasm_bindgen(getter, js_name = "prefabHash")] #[wasm_bindgen(getter, js_name = "prefabHash")]
pub fn prefab_hash(&self) -> Option<i32> { pub fn prefab_hash(&self) -> Option<i32> {
self.device.borrow().prefab_hash self.device.borrow().prefab.as_ref().map(|prefab| prefab.hash)
} }
#[wasm_bindgen(getter, skip_typescript)] #[wasm_bindgen(getter, skip_typescript)]
@@ -351,6 +351,12 @@ impl VM {
Ok(self.vm.borrow_mut().add_device(network)?) Ok(self.vm.borrow_mut().add_device(network)?)
} }
#[wasm_bindgen(js_name = "addDeviceFromTemplate", skip_typescript)]
pub fn add_device_from_template(&self, template: JsValue) -> Result<u32, JsError> {
let template: DeviceTemplate = serde_wasm_bindgen::from_value(template)?;
Ok(self.vm.borrow_mut().add_device_from_template(template)?)
}
#[wasm_bindgen(js_name = "getDevice")] #[wasm_bindgen(js_name = "getDevice")]
pub fn get_device(&self, id: u32) -> Option<DeviceRef> { pub fn get_device(&self, id: u32) -> Option<DeviceRef> {
let device = self.vm.borrow().get_device(id); let device = self.vm.borrow().get_device(id);

View File

@@ -4,7 +4,8 @@ export interface LogicField {
field_type: FieldType; field_type: FieldType;
value: number; value: number;
} }
export type Fields = Map<string, LogicField>; export type LogicFields = Map<LogicType, LogicField>;
export type SlotLogicFields = Map<SlotLogicType, LogicField>;
export type SlotType = export type SlotType =
| "AccessCard" | "AccessCard"
@@ -46,12 +47,12 @@ export interface SlotOccupant {
readonly quantity: number; readonly quantity: number;
readonly max_quantity: number; readonly max_quantity: number;
readonly damage: number; readonly damage: number;
readonly fields: Fields; readonly fields: SlotLogicFields;
} }
export interface Slot { export interface Slot {
readonly typ: SlotType; readonly typ: SlotType;
readonly occupant: SlotOccupant | undefined; readonly occupant: SlotOccupant | undefined;
readonly fields: Fields; readonly fields: SlotLogicFields;
} }
export type Reagents = Map<string, Map<number, number>>; export type Reagents = Map<string, Map<number, number>>;
@@ -80,10 +81,10 @@ export type DeviceSpec = {
}; };
readonly connection: number | undefined; readonly connection: number | undefined;
}; };
export type LogicType = { readonly LogicType: string }; export type OperandLogicType = { readonly LogicType: string };
export type SlotLogicType = { readonly SlotLogicType: string }; export type OperandSlotLogicType = { readonly SlotLogicType: string };
export type BatchMode = { readonly BatchMode: string }; export type OperandBatchMode = { readonly BatchMode: string };
export type ReagentMode = { readonly ReagentMode: string }; export type OperandReagentMode = { readonly ReagentMode: string };
export type Identifier = { readonly Identifier: { name: string } }; export type Identifier = { readonly Identifier: { name: string } };
export type NumberFloat = { readonly Float: number }; export type NumberFloat = { readonly Float: number };
@@ -106,10 +107,10 @@ export type Operand =
| RegisterSpec | RegisterSpec
| DeviceSpec | DeviceSpec
| NumberOperand | NumberOperand
| LogicType | OperandLogicType
| SlotLogicType | OperandSlotLogicType
| BatchMode | OperandBatchMode
| ReagentMode | OperandReagentMode
| Identifier; | Identifier;
export type Alias = RegisterSpec | DeviceSpec; export type Alias = RegisterSpec | DeviceSpec;
@@ -141,7 +142,7 @@ export interface Program {
} }
export interface DeviceRef { export interface DeviceRef {
readonly fields: Fields; readonly fields: LogicFields;
readonly slots: Slot[]; readonly slots: Slot[];
readonly reagents: Reagents; readonly reagents: Reagents;
readonly connections: Connection[]; readonly connections: Connection[];
@@ -149,5 +150,29 @@ export interface DeviceRef {
readonly defines?: Defines | undefined; readonly defines?: Defines | undefined;
readonly pins?: Pins; readonly pins?: Pins;
readonly program?: Program; readonly program?: Program;
getSlotFields(slot: number): Fields; getSlotFields(slot: number): SlotLogicFields;
}
export interface SlotOccupantTemplate {
id?: number;
fields: { [key in SlotLogicType]?: LogicField };
}
export interface SlotTemplate {
typ: SlotType;
occupant?: SlotOccupantTemplate;
}
export interface DeviceTemplate {
id?: number;
name?: string;
prefab_name?: string;
slots: SlotTemplate[];
// reagents: { [key: string]: float}
connections: Connection[];
fields: { [key in LogicType]?: LogicField };
}
export interface VM {
addDeviceFromTemplate(template: DeviceTemplate): number
} }

View File

@@ -44,7 +44,7 @@ export class IC10Editor extends BaseElement {
}; };
sessions: Map<number, Ace.EditSession>; sessions: Map<number, Ace.EditSession>;
@state() active_session: number = 0; @state() active_session: number = 1;
active_line_markers: Map<number, number | null> = new Map(); active_line_markers: Map<number, number | null> = new Map();
languageProvider?: LanguageProvider; languageProvider?: LanguageProvider;

View File

@@ -74,7 +74,7 @@ export class Session extends EventTarget {
this._programs = new Map(); this._programs = new Map();
this._errors = new Map(); this._errors = new Map();
this._save_timeout = undefined; this._save_timeout = undefined;
this._activeIC = 0; this._activeIC = 1;
this._activeLines = new Map(); this._activeLines = new Map();
this.loadFromFragment(); this.loadFromFragment();
@@ -201,7 +201,7 @@ export class Session extends EventTarget {
async loadFromFragment() { async loadFromFragment() {
const fragment = window.location.hash.slice(1); const fragment = window.location.hash.slice(1);
if (fragment === "demo") { if (fragment === "demo") {
this._programs = new Map([[0, demoCode]]); this._programs = new Map([[1, demoCode]]);
this._fireOnLoad(); this._fireOnLoad();
return; return;
} }
@@ -213,7 +213,7 @@ export class Session extends EventTarget {
const data = getJson(txt); const data = getJson(txt);
if (data === null) { if (data === null) {
// backwards compatible // backwards compatible
this._programs = new Map([[0, txt]]); this._programs = new Map([[1, txt]]);
this, this._fireOnLoad(); this, this._fireOnLoad();
return; return;
} }

View File

@@ -2,7 +2,7 @@ import { property, state } from "lit/decorators.js";
import { import {
DeviceRef, DeviceRef,
Fields, LogicFields,
Reagents, Reagents,
Slot, Slot,
Connection, Connection,
@@ -25,7 +25,7 @@ export declare class VMDeviceMixinInterface {
name: string | null; name: string | null;
nameHash: number | null; nameHash: number | null;
prefabName: string | null; prefabName: string | null;
fields: Fields; fields: LogicFields;
slots: Slot[]; slots: Slot[];
reagents: Reagents; reagents: Reagents;
connections: Connection[]; connections: Connection[];
@@ -53,7 +53,7 @@ export const VMDeviceMixin = <T extends Constructor<LitElement>>(
@state() accessor name: string | null = null; @state() accessor name: string | null = null;
@state() accessor nameHash: number | null = null; @state() accessor nameHash: number | null = null;
@state() accessor prefabName: string | null; @state() accessor prefabName: string | null;
@state() accessor fields: Fields; @state() accessor fields: LogicFields;
@state() accessor slots: Slot[]; @state() accessor slots: Slot[];
@state() accessor reagents: Reagents; @state() accessor reagents: Reagents;
@state() accessor connections: Connection[]; @state() accessor connections: Connection[];