diff --git a/src/dyn_fns.rs b/src/dyn_fns.rs
new file mode 100644
index 0000000..e70816d
--- /dev/null
+++ b/src/dyn_fns.rs
@@ -0,0 +1,297 @@
+use std::sync::Arc;
+
+use crate::{mutex::Mut, runtime::*, lexer};
+
+pub fn dyn_dump(stack: &mut Stack) {
+ Words {
+ words: vec![Word::Key(Keyword::Dump)],
+ }
+ .exec(stack);
+}
+
+pub fn dyn_def(stack: &mut Stack) {
+ if let Value::Str(s) = stack.pop().lock_ro().native.clone() {
+ Words {
+ words: vec![Word::Key(Keyword::Def(s))],
+ }
+ .exec(stack);
+ } else {
+ panic!("incorrect usage of dyn-def");
+ }
+}
+
+pub fn dyn_func(stack: &mut Stack) {
+ if let Value::Str(s) = stack.pop().lock_ro().native.clone() {
+ if let Value::Func(f) = stack.pop().lock_ro().native.clone() {
+ stack.define_func(s, f);
+ } else {
+ panic!("incorrect usage of dyn-func");
+ }
+ } else {
+ panic!("incorrect usage of dyn-func");
+ }
+}
+
+pub fn dyn_construct(stack: &mut Stack) {
+ if let Value::Str(s) = stack.pop().lock_ro().native.clone() {
+ Words {
+ words: vec![Word::Key(Keyword::Construct(s, Vec::new(), Vec::new()))],
+ }
+ .exec(stack);
+ } else {
+ panic!("incorrect usage of dyn-construct");
+ }
+}
+
+pub fn dyn_def_field(stack: &mut Stack) {
+ if let Value::Str(s) = stack.pop().lock_ro().native.clone() {
+ if let Value::Str(name) = stack.pop().lock_ro().native.clone() {
+ runtime(|rt| {
+ rt.get_type_by_name(s)
+ .unwrap()
+ .lock()
+ .add_property(name, stack.get_frame());
+ });
+ } else {
+ panic!("incorrect usage of dyn-def-field");
+ }
+ } else {
+ panic!("incorrect usage of dyn-def-field");
+ }
+}
+
+pub fn dyn_def_method(stack: &mut Stack) {
+ if let Value::Str(s) = stack.pop().lock_ro().native.clone() {
+ if let Value::Str(name) = stack.pop().lock_ro().native.clone() {
+ if let Value::Func(f) = stack.pop().lock_ro().native.clone() {
+ runtime(|rt| {
+ rt.get_type_by_name(s)
+ .unwrap()
+ .lock()
+ .functions
+ .insert(name, f);
+ });
+ } else {
+ panic!("incorrect usage of dyn-def-method");
+ }
+ } else {
+ panic!("incorrect usage of dyn-def-method");
+ }
+ } else {
+ panic!("incorrect usage of dyn-def-method");
+ }
+}
+
+pub fn dyn_include(stack: &mut Stack) {
+ if let Value::Str(b) = stack.pop().lock_ro().native.clone() {
+ if let Value::Str(a) = stack.pop().lock_ro().native.clone() {
+ Words {
+ words: vec![Word::Key(Keyword::Include(a, b))],
+ }
+ .exec(stack);
+ } else {
+ panic!("incorrect usage of dyn-include");
+ }
+ } else {
+ panic!("incorrect usage of dyn-include");
+ }
+}
+
+pub fn dyn_while(stack: &mut Stack) {
+ if let Value::Func(blk) = stack.pop().lock_ro().native.clone() {
+ if let Value::Func(cond) = stack.pop().lock_ro().native.clone() {
+ loop {
+ cond.to_call.call(stack);
+ if !stack.pop().lock_ro().is_truthy() {
+ break;
+ }
+ blk.to_call.call(stack);
+ }
+ } else {
+ panic!("incorrect usage of dyn-while");
+ }
+ } else {
+ panic!("incorrect usage of dyn-while");
+ }
+}
+
+pub fn dyn_if(stack: &mut Stack) {
+ if let Value::Func(blk) = stack.pop().lock_ro().native.clone() {
+ if stack.pop().lock_ro().is_truthy() {
+ blk.to_call.call(stack);
+ }
+ } else {
+ panic!("incorrect usage of dyn-if");
+ }
+}
+
+pub fn dyn_call(stack: &mut Stack) {
+ if let Value::Str(mut s) = stack.pop().lock_ro().native.clone() {
+ let mut words = Vec::new();
+ let mut ra = 0;
+ while s.starts_with("&") {
+ ra += 1;
+ s = s[1..].to_owned();
+ }
+ if s.ends_with(";") {
+ words.push(Word::Call(s[..s.len() - 1].to_owned(), true, ra));
+ } else {
+ words.push(Word::Call(s.to_owned(), false, ra));
+ }
+ Words { words }.exec(stack);
+ } else {
+ panic!("incorrect usage of dyn-call");
+ }
+}
+
+pub fn dyn_objcall(stack: &mut Stack) {
+ if let Value::Str(mut s) = stack.pop().lock_ro().native.clone() {
+ let mut words = Vec::new();
+ let mut ra = 0;
+ while s.starts_with("&") {
+ ra += 1;
+ s = s[1..].to_owned();
+ }
+ if s.ends_with(";") {
+ words.push(Word::ObjCall(s[..s.len() - 1].to_owned(), true, ra));
+ } else {
+ words.push(Word::ObjCall(s.to_owned(), false, ra));
+ }
+ Words { words }.exec(stack);
+ } else {
+ panic!("incorrect usage of dyn-objcall");
+ }
+}
+
+pub fn dyn_all_types(stack: &mut Stack) {
+ runtime(|rt| {
+ stack.push(
+ Value::Array(
+ rt.get_types()
+ .into_iter()
+ .map(|x| Value::Str(x.lock_ro().get_name()).spl())
+ .collect(),
+ )
+ .spl(),
+ );
+ });
+}
+
+pub fn dyn_read(stack: &mut Stack) {
+ if let Value::Str(s) = stack.pop().lock_ro().native.clone() {
+ stack.push(Value::Func(AFunc::new(Func {
+ ret_count: 0,
+ to_call: FuncImpl::SPL(lexer::lex(s, "dyn-read@".to_owned() + &stack.get_origin().file, stack.get_frame())),
+ origin: stack.get_frame(),
+ })).spl());
+ } else {
+ panic!("incorrect usage of dyn-call");
+ }
+}
+
+pub fn register(r: &mut Stack, o: Arc) {
+ r.define_func(
+ "dyn-__dump".to_owned(),
+ AFunc::new(Func {
+ ret_count: 0,
+ to_call: FuncImpl::Native(dyn_dump),
+ origin: o.clone(),
+ }),
+ );
+ r.define_func(
+ "dyn-def".to_owned(),
+ AFunc::new(Func {
+ ret_count: 0,
+ to_call: FuncImpl::Native(dyn_def),
+ origin: o.clone(),
+ }),
+ );
+ r.define_func(
+ "dyn-func".to_owned(),
+ AFunc::new(Func {
+ ret_count: 0,
+ to_call: FuncImpl::Native(dyn_func),
+ origin: o.clone(),
+ }),
+ );
+ r.define_func(
+ "dyn-construct".to_owned(),
+ AFunc::new(Func {
+ ret_count: 0,
+ to_call: FuncImpl::Native(dyn_construct),
+ origin: o.clone(),
+ }),
+ );
+ r.define_func(
+ "dyn-def-field".to_owned(),
+ AFunc::new(Func {
+ ret_count: 0,
+ to_call: FuncImpl::Native(dyn_def_field),
+ origin: o.clone(),
+ }),
+ );
+ r.define_func(
+ "dyn-def-method".to_owned(),
+ AFunc::new(Func {
+ ret_count: 0,
+ to_call: FuncImpl::Native(dyn_def_method),
+ origin: o.clone(),
+ }),
+ );
+ r.define_func(
+ "dyn-include".to_owned(),
+ AFunc::new(Func {
+ ret_count: 0,
+ to_call: FuncImpl::Native(dyn_include),
+ origin: o.clone(),
+ }),
+ );
+ r.define_func(
+ "dyn-while".to_owned(),
+ AFunc::new(Func {
+ ret_count: 0,
+ to_call: FuncImpl::Native(dyn_while),
+ origin: o.clone(),
+ }),
+ );
+ r.define_func(
+ "dyn-if".to_owned(),
+ AFunc::new(Func {
+ ret_count: 0,
+ to_call: FuncImpl::Native(dyn_if),
+ origin: o.clone(),
+ }),
+ );
+ r.define_func(
+ "dyn-call".to_owned(),
+ AFunc::new(Func {
+ ret_count: 0,
+ to_call: FuncImpl::Native(dyn_call),
+ origin: o.clone(),
+ }),
+ );
+ r.define_func(
+ "dyn-objcall".to_owned(),
+ AFunc::new(Func {
+ ret_count: 0,
+ to_call: FuncImpl::Native(dyn_objcall),
+ origin: o.clone(),
+ }),
+ );
+ r.define_func(
+ "dyn-all-types".to_owned(),
+ AFunc::new(Func {
+ ret_count: 1,
+ to_call: FuncImpl::Native(dyn_all_types),
+ origin: o.clone(),
+ }),
+ );
+ r.define_func(
+ "dyn-read".to_owned(),
+ AFunc::new(Func {
+ ret_count: 1,
+ to_call: FuncImpl::Native(dyn_read),
+ origin: o.clone(),
+ }),
+ )
+}
diff --git a/src/lexer.rs b/src/lexer.rs
index f1a285e..bb19d75 100644
--- a/src/lexer.rs
+++ b/src/lexer.rs
@@ -1,28 +1,32 @@
+use std::sync::Arc;
+
use crate::runtime::*;
use readformat::*;
-pub fn lex(input: String, filename: String) -> Words {
+pub fn lex(input: String, filename: String, frame: Arc) -> Words {
let mut str_words = Vec::new();
for line in input.split('\n') {
str_words.append(&mut parse_line(line));
}
- read_block(&str_words[..], false, &FrameInfo { file: filename }).1
+ read_block(
+ &str_words[..],
+ false,
+ Arc::new(Frame::new_in(frame, filename)),
+ )
+ .1
}
-fn read_block(str_words: &[String], isfn: bool, origin: &FrameInfo) -> (Option, Words, usize) {
+fn read_block(str_words: &[String], isfn: bool, origin: Arc) -> (Option, Words, usize) {
let mut rem = None;
let mut words = Vec::new();
let mut i = 0;
- if str_words[0] == "{" {
- if isfn {
- let mut r = 0_u32;
- while str_words[r as usize + 1] != "|" {
- r += 1;
- }
- i += r as usize + 1;
- rem = Some(r);
+ if str_words[0] == "{" && isfn {
+ let mut r = 0_u32;
+ while str_words[r as usize + 1] != "|" {
+ r += 1;
}
- i += 1;
+ i += r as usize + 2;
+ rem = Some(r);
}
while i < str_words.len() {
let word = str_words[i].to_owned();
@@ -33,7 +37,11 @@ fn read_block(str_words: &[String], isfn: bool, origin: &FrameInfo) -> (Option {
if let Some(dat) = readf("func\0{}\0{", str_words[i..=i + 2].join("\0").as_str()) {
- let block = read_block(&str_words[i + 2..], true, &origin);
+ let block = read_block(
+ &str_words[i + 2..],
+ true,
+ Arc::new(Frame::new(origin.clone())),
+ );
i += 2 + block.2;
words.push(Word::Key(Keyword::Func(
dat[0].to_owned(),
@@ -43,9 +51,9 @@ fn read_block(str_words: &[String], isfn: bool, origin: &FrameInfo) -> (Option {
- let block = read_block(&str_words[i..], true, &origin);
+ let block = read_block(&str_words[i..], true, Arc::new(Frame::new(origin.clone())));
i += block.2;
- words.push(Word::Const(Constant::Func(AFunc::new(Func {
+ words.push(Word::Const(Value::Func(AFunc::new(Func {
ret_count: block.0.expect("LEXERR: Expected `{ <...> |`."),
to_call: FuncImpl::SPL(block.1),
origin: origin.to_owned(),
@@ -59,17 +67,21 @@ fn read_block(str_words: &[String], isfn: bool, origin: &FrameInfo) -> (Option {{`, got `construct `"
);
let mut fields = Vec::new();
- i += 2;
+ i += 3;
while str_words[i] != ";" && str_words[i] != "}" {
fields.push((&str_words[i]).to_owned());
i += 1;
}
let mut methods = Vec::new();
+ let mut has_construct = false;
if str_words[i] == ";" {
i += 1;
while str_words[i] != "}" {
let name = (&str_words[i]).to_owned();
- let block = read_block(&str_words[i + 1..], true, origin);
+ if name == "construct" {
+ has_construct = true;
+ }
+ let block = read_block(&str_words[i + 1..], true, origin.clone());
i += 1 + block.2;
methods.push((
name,
@@ -81,12 +93,15 @@ fn read_block(str_words: &[String], isfn: bool, origin: &FrameInfo) -> (Option {
if let Some(x) = readf(
"include\0{}\0in\0{}",
- str_words[i..=i + 4].join("\0").as_str(),
+ str_words[i..i + 4].join("\0").as_str(),
) {
words.push(Word::Key(Keyword::Include(
x[0].to_owned(),
@@ -95,20 +110,19 @@ fn read_block(str_words: &[String], isfn: bool, origin: &FrameInfo) -> (Option in `.");
}
+ i += 3;
}
"while" => {
- let cond = read_block(&str_words[i + 1..], false, origin);
- i += 1 + cond.2;
- let blk = read_block(&str_words[i + 1..], false, origin);
- i += 1 + cond.2;
+ let cond = read_block(&str_words[i + 2..], false, origin.clone());
+ i += 2 + cond.2;
+ let blk = read_block(&str_words[i + 2..], false, origin.clone());
+ i += 2 + blk.2;
words.push(Word::Key(Keyword::While(cond.1, blk.1)));
}
"if" => {
- let cond = read_block(&str_words[i + 1..], false, origin);
- i += 1 + cond.2;
- let blk = read_block(&str_words[i + 1..], false, origin);
- i += 1 + cond.2;
- words.push(Word::Key(Keyword::If(cond.1, blk.1)));
+ let blk = read_block(&str_words[i + 2..], false, origin.clone());
+ i += 2 + blk.2;
+ words.push(Word::Key(Keyword::If(blk.1)));
}
"with" => {
let mut vars = Vec::new();
@@ -123,24 +137,27 @@ fn read_block(str_words: &[String], isfn: bool, origin: &FrameInfo) -> (Option {
- words.push(Word::Const(Constant::Str(x[1..].to_owned())));
+ words.push(Word::Const(Value::Str(x[1..].to_owned())));
}
x if x.chars().all(|c| c.is_numeric() || c == '_') && !x.starts_with("_") => {
- words.push(Word::Const(Constant::Mega(x.parse().unwrap())));
+ words.push(Word::Const(Value::Mega(x.parse().unwrap())));
}
- x if x.chars().all(|c| c.is_numeric() || c == '.' || c == '_') && !x.starts_with("_") => {
- words.push(Word::Const(Constant::Double(x.parse().unwrap())));
+ x if x.chars().all(|c| c.is_numeric() || c == '.' || c == '_')
+ && !x.starts_with("_") =>
+ {
+ words.push(Word::Const(Value::Double(x.parse().unwrap())));
}
- mut x => {
+ x => {
+ let mut word = x.split(":").next().unwrap();
let mut ra = 0;
- while x.starts_with("&") {
+ while word.starts_with("&") {
ra += 1;
- x = &x[1..];
+ word = &word[1..];
}
- if x.ends_with(";") {
- words.push(Word::Call(x[..x.len() - 1].to_owned(), true, ra));
+ if word.ends_with(";") {
+ words.push(Word::Call(word[..word.len() - 1].to_owned(), true, ra));
} else {
- words.push(Word::Call(x.to_owned(), false, ra));
+ words.push(Word::Call(word.to_owned(), false, ra));
}
for mut word in x.split(":").skip(1) {
let mut ra = 0;
@@ -165,6 +182,7 @@ fn parse_line(line: &str) -> Vec {
let mut words = Vec::new();
let mut in_string = false;
let mut escaping = false;
+ let mut was_in_string = false;
let mut s = String::new();
for c in line.chars() {
if in_string {
@@ -178,11 +196,15 @@ fn parse_line(line: &str) -> Vec {
if c == 'r' {
s += "\r";
}
+ if c == '"' {
+ s += "\"";
+ }
escaping = false;
continue;
} else if c == '"' {
in_string = false;
escaping = false;
+ was_in_string = true;
continue;
}
if c == '\\' {
@@ -195,15 +217,24 @@ fn parse_line(line: &str) -> Vec {
in_string = true;
continue;
}
+ if c == ';' && was_in_string {
+ s = String::new();
+ continue;
+ }
+ if c == '(' || c == ')' {
+ continue;
+ }
if c == ' ' {
if s == "" {
continue;
}
words.push(s);
s = String::new();
+ was_in_string = false;
continue;
}
}
+ was_in_string = false;
s += String::from(c).as_str();
}
if s != "" {
diff --git a/src/lib.rs b/src/lib.rs
index 2876b4b..8e67ced 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,3 +1,5 @@
+pub(crate) mod dyn_fns;
pub mod lexer;
pub mod mutex;
pub mod runtime;
+pub(crate) mod std_fns;
diff --git a/src/main.rs b/src/main.rs
index f449d7e..480ac27 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,32 +1,13 @@
use spl::{lexer::lex, runtime::*};
use std::{
- io::{stdout, Write},
- sync::Arc,
+ fs,
vec,
};
fn main() {
let rt = Runtime::new();
let mut stack = Stack::new();
- fn print(stack: &mut Stack) {
- let s = stack.pop();
- let s = s.lock();
- if let Constant::Str(ref s) = s.native {
- print!("{s}");
- stdout().lock().flush().unwrap();
- }
- }
- stack.define_func(
- "print".to_owned(),
- Arc::new(Func {
- ret_count: 0,
- to_call: FuncImpl::Native(print),
- origin: FrameInfo {
- file: "RUNTIME".to_owned(),
- },
- }),
- );
rt.set();
Words {
words: vec![
@@ -36,19 +17,25 @@ fn main() {
Words {
words: vec![
Word::Call("print".to_owned(), true, 0),
- Word::Const(Constant::Str("\n".to_owned())),
+ Word::Const(Value::Str("\n".to_owned())),
Word::Call("print".to_owned(), true, 0),
],
},
)),
Word::Key(Keyword::Def("helloworld".to_owned())),
- Word::Const(Constant::Str("Hello, World".to_owned())),
+ Word::Const(Value::Str("Hello, World".to_owned())),
Word::Call("=helloworld".to_owned(), false, 0),
Word::Call("helloworld".to_owned(), false, 0),
Word::Call("println".to_owned(), true, 0),
],
}
.exec(&mut stack);
- lex("func println { | print \"\\n\" print } def helloworld \"Hello, World\" =helloworld helloworld println".to_owned(), "TEST".to_owned()).exec(&mut stack);
+ let words = lex(
+ fs::read_to_string("test.spl").unwrap(),
+ "test.spl".to_owned(),
+ stack.get_frame(),
+ );
+ println!("{words:?}");
+ words.exec(&mut stack);
Runtime::reset();
}
diff --git a/src/mutex.rs b/src/mutex.rs
index 640caae..a2e33cc 100644
--- a/src/mutex.rs
+++ b/src/mutex.rs
@@ -1,14 +1,19 @@
-use std::sync::{Mutex, MutexGuard};
+use std::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard};
-pub struct Mut(Mutex);
+#[derive(Debug)]
+pub struct Mut(RwLock);
impl Mut {
pub fn new(obj: T) -> Mut {
- Mut(Mutex::new(obj))
+ Mut(RwLock::new(obj))
}
- pub fn lock(&self) -> MutexGuard {
- self.0.lock().unwrap()
+ pub fn lock_ro(&self) -> RwLockReadGuard {
+ self.0.read().unwrap()
+ }
+
+ pub fn lock(&self) -> RwLockWriteGuard {
+ self.0.write().unwrap()
}
}
@@ -17,6 +22,26 @@ where
T: Clone,
{
fn clone(&self) -> Self {
- Self(Mutex::new(self.0.lock().unwrap().clone()))
+ Self(RwLock::new(self.0.read().unwrap().clone()))
+ }
+}
+
+impl PartialEq for Mut
+where
+ T: PartialEq,
+{
+ fn eq(&self, other: &Self) -> bool {
+ self.0.read().unwrap().eq(&other.0.read().unwrap())
+ }
+}
+
+impl Eq for Mut where T: Eq {}
+
+impl PartialOrd for Mut
+where
+ T: PartialOrd,
+{
+ fn partial_cmp(&self, other: &Self) -> Option {
+ self.0.read().unwrap().partial_cmp(&other.0.read().unwrap())
}
}
diff --git a/src/runtime.rs b/src/runtime.rs
index 9b08665..12902f5 100644
--- a/src/runtime.rs
+++ b/src/runtime.rs
@@ -1,10 +1,12 @@
-use crate::mutex::*;
+use crate::{dyn_fns, mutex::*, std_fns};
+use core::panic;
use std::collections::VecDeque;
+use std::mem;
use std::{
cell::RefCell,
collections::HashMap,
- fmt::{Debug, Display, Formatter, Pointer},
+ fmt::{Debug, Display, Formatter},
sync::Arc,
vec,
};
@@ -17,6 +19,10 @@ thread_local! {
static RUNTIME: RefCell