commit 34dd8ca486064e0d49aa9225fa129962b94e2cd4 Author: TudbuT Date: Fri Feb 17 20:00:39 2023 +0100 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..04fa96d --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "spl" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..3b1a1c4 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "spl" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..dff037a --- /dev/null +++ b/src/main.rs @@ -0,0 +1,313 @@ +use std::{ + cell::RefCell, + collections::HashMap, + fmt::{Display, Formatter, Pointer, Debug}, + sync::{Arc, Mutex}, + vec, +}; + +thread_local! { + static RUNTIME: RefCell> = RefCell::new(None); +} + +#[derive(Clone)] +struct Runtime { + next_type_id: u32, + types_by_name: HashMap>, + types_by_id: HashMap>, +} + +impl Runtime { + pub fn new() -> Self { + let mut rt = Runtime { + next_type_id: 0, + types_by_name: HashMap::new(), + types_by_id: HashMap::new(), + }; + rt.make_type("null".to_owned(), |t|t); + rt.make_type("int".to_owned(), |t|t); + rt.make_type("long".to_owned(), |t|t); + rt.make_type("mega".to_owned(), |t|t); + rt.make_type("func".to_owned(), |t|t); + rt.make_type("array".to_owned(), |t|t); + rt.make_type("str".to_owned(), |t|t); + rt + } + + pub fn get_type_by_name(&self, name: String) -> Option> { + self.types_by_name.get(&name).cloned() + } + + pub fn get_type_by_id(&self, id: u32) -> Option> { + self.types_by_id.get(&id).cloned() + } + + pub fn make_type(&mut self, name: String, op: impl FnOnce(Type) -> Type) -> Arc { + let t = Arc::new(op(Type { + name: name.clone(), + id: (self.next_type_id, self.next_type_id += 1).0, + functions: HashMap::new(), + properties: Vec::new(), + })); + self.types_by_id.insert(self.next_type_id - 1, t.clone()); + self.types_by_name.insert(name, t.clone()); + t + } + + pub fn set(self) { + RUNTIME.with(move |x| *x.borrow_mut() = Some(self)); + } + + pub fn reset() { + RUNTIME.with(|x| *x.borrow_mut() = None); + } +} + +#[derive(Clone)] +struct FrameInfo { + file: String, +} + +#[derive(Clone)] +struct Frame { + parent: Option>, + object_stack: Vec>>, + variables: HashMap>>, + origin: FrameInfo, +} + +impl Display for Frame { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.write_str("Stack: \n")?; + for object in &self.object_stack { + f.write_str(" ")?; + object.lock().unwrap().fmt(f)?; + f.write_str("\n")?; + } + f.write_str("\nVars: \n")?; + for (name, object) in &self.variables { + f.write_str(" ")?; + f.write_str(&name)?; + f.write_str(": ")?; + object.lock().unwrap().fmt(f)?; + f.write_str("\n")?; + } + Ok(()) + } +} + +impl Frame { + fn root() -> Self { + Frame { + parent: None, + object_stack: Vec::new(), + variables: HashMap::new(), + origin: FrameInfo { + file: "RUNTIME".to_owned(), + }, + } + } + + pub fn new(parent: Arc, origin: FrameInfo) -> Self { + Frame { + parent: Some(parent), + object_stack: Vec::new(), + variables: HashMap::new(), + origin, + } + } +} + +#[derive(Clone)] +struct Stack { + frames: Vec, +} + +impl Display for Stack { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + for frame in &self.frames { + f.write_str("Frame: ")?; + f.write_str(&frame.origin.file)?; + f.write_str("\n\n")?; + frame.fmt(f)?; + } + Ok(()) + } +} + +impl Stack { + pub fn new() -> Self { + Stack { + frames: vec![Frame::root()], + } + } + + pub fn push(&mut self, obj: Arc>) { + self.frames + .last_mut() + .expect("program end reached but stack still being used") + .object_stack + .push(obj) + } +} + +#[derive(Clone)] +enum Keyword { + DUMP, +} + +#[derive(Clone, Debug)] +enum Constant { + Int(i32), + Long(i64), + Mega(i128), + Str(String), + Func(Func), + Null, +} + +#[derive(Clone)] +enum Word { + Key(Keyword), + Const(Constant), + GetPointer(String), + ObjGetPointer(String), + Call(String), + ObjCall(String), +} + +#[derive(Clone)] +struct Words { + words: Vec, +} + +#[derive(Clone)] +enum FuncImpl { + NATIVE(fn(&mut Stack)), + SPL(Words), +} + +#[derive(Clone)] +struct Func { + arg_count: u32, + to_call: FuncImpl, +} + +impl Debug for Func { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.write_str(&self.arg_count.to_string())?; + Ok(()) + } +} + +#[derive(Clone)] +struct Type { + name: String, + id: u32, + functions: HashMap, + properties: Vec, +} + +#[derive(Clone)] +struct Object { + kind: Arc, + property_map: HashMap>>, + native: Constant, +} + +impl Display for Object { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.write_str(&self.kind.name)?; + f.write_str("(")?; + self.native.fmt(f)?; + f.write_str(") { ")?; + for (k, v) in &self.property_map { + f.write_str(&k)?; + f.write_str(": ")?; + v.fmt(f)?; + } + f.write_str(" }")?; + Ok(()) + } +} + +impl Object { + pub fn new(kind: Arc, native: Constant) -> Object { + Object { + property_map: { + let mut map = HashMap::new(); + for property in &kind.properties { + map.insert(property.clone(), Constant::Null.spl()); + } + map + }, + kind, + native, + } + } +} + +impl From for Object { + fn from(value: Constant) -> Self { + Object::new( + RUNTIME.with(|x| { + let x = x.borrow(); + let x = x.as_ref().unwrap(); + match value { + Constant::Null => x.get_type_by_id(0), + Constant::Int(_) => x.get_type_by_id(1), + Constant::Long(_) => x.get_type_by_id(2), + Constant::Mega(_) => x.get_type_by_id(3), + Constant::Func(_) => x.get_type_by_id(4), + // array is 5 + Constant::Str(_) => x.get_type_by_id(6), + } + .expect("runtime uninitialized: default types not set.") + }), + value, + ) + } +} + +trait SPL { + fn spl(self) -> Arc>; +} + +impl SPL for T +where + T: Into, +{ + fn spl(self) -> Arc> { + Arc::new(Mutex::new(self.into())) + } +} + +impl Words { + pub fn exec(&self, stack: &mut Stack) { + for word in &self.words { + match word { + Word::Key(x) => match x { + Keyword::DUMP => println!("{}", stack), + }, + Word::Const(x) => stack.push(x.clone().spl()), + Word::GetPointer(_) => todo!(), + Word::ObjGetPointer(_) => todo!(), + Word::Call(_) => todo!(), + Word::ObjCall(_) => todo!(), + } + } + } +} + +fn main() { + let rt = Runtime::new(); + rt.set(); + Words { + words: vec![ + Word::Const(Constant::Str("Hello, World".to_owned())), + Word::Key(Keyword::DUMP), + ], + } + .exec(&mut Stack::new()); + Runtime::reset(); +}