errors, stack traces
This commit is contained in:
parent
07264a5f67
commit
901a5cb734
6 changed files with 407 additions and 286 deletions
|
@ -188,24 +188,19 @@ pub fn dyn_all_types(stack: &mut Stack) -> OError {
|
||||||
|
|
||||||
pub fn dyn_read(stack: &mut Stack) -> OError {
|
pub fn dyn_read(stack: &mut Stack) -> OError {
|
||||||
let Value::Str(s) = stack.pop().lock_ro().native.clone() else {
|
let Value::Str(s) = stack.pop().lock_ro().native.clone() else {
|
||||||
return stack.err(ErrorKind::InvalidCall("dyn-call".to_owned()))
|
return stack.err(ErrorKind::InvalidCall("dyn-read".to_owned()))
|
||||||
};
|
};
|
||||||
|
let origin = stack.peek_frame(1);
|
||||||
stack.push(
|
stack.push(
|
||||||
Value::Func(AFunc::new(Func {
|
Value::Func(AFunc::new(Func {
|
||||||
ret_count: 0,
|
ret_count: 0,
|
||||||
to_call: FuncImpl::SPL(
|
to_call: FuncImpl::SPL(lexer::lex(s).map_err(|x| Error {
|
||||||
lexer::lex(
|
|
||||||
s,
|
|
||||||
"dyn-read@".to_owned() + &stack.get_origin().file,
|
|
||||||
stack.get_frame(),
|
|
||||||
)
|
|
||||||
.map_err(|x| Error {
|
|
||||||
kind: ErrorKind::LexError(format!("{x:?}")),
|
kind: ErrorKind::LexError(format!("{x:?}")),
|
||||||
stack: stack.trace(),
|
stack: stack.trace(),
|
||||||
})?,
|
})?),
|
||||||
),
|
origin,
|
||||||
origin: stack.get_frame(),
|
fname: None,
|
||||||
cname: None,
|
name: "(dyn-read)".to_owned(),
|
||||||
}))
|
}))
|
||||||
.spl(),
|
.spl(),
|
||||||
);
|
);
|
||||||
|
@ -214,25 +209,25 @@ pub fn dyn_read(stack: &mut Stack) -> OError {
|
||||||
|
|
||||||
pub fn dyn_readf(stack: &mut Stack) -> OError {
|
pub fn dyn_readf(stack: &mut Stack) -> OError {
|
||||||
let (
|
let (
|
||||||
Value::Str(n),
|
|
||||||
Value::Str(s),
|
Value::Str(s),
|
||||||
|
Value::Str(n),
|
||||||
) = (
|
) = (
|
||||||
stack.pop().lock_ro().native.clone(),
|
stack.pop().lock_ro().native.clone(),
|
||||||
stack.pop().lock_ro().native.clone(),
|
stack.pop().lock_ro().native.clone(),
|
||||||
) else {
|
) else {
|
||||||
return stack.err(ErrorKind::InvalidCall("dyn-call".to_owned()))
|
return stack.err(ErrorKind::InvalidCall("dyn-readf".to_owned()))
|
||||||
};
|
};
|
||||||
|
let origin = stack.peek_frame(1);
|
||||||
stack.push(
|
stack.push(
|
||||||
Value::Func(AFunc::new(Func {
|
Value::Func(AFunc::new(Func {
|
||||||
ret_count: 0,
|
ret_count: 0,
|
||||||
to_call: FuncImpl::SPL(lexer::lex(s, n.clone(), stack.get_frame()).map_err(|x| {
|
to_call: FuncImpl::SPL(lexer::lex(s).map_err(|x| Error {
|
||||||
Error {
|
|
||||||
kind: ErrorKind::LexError(format!("{x:?}")),
|
kind: ErrorKind::LexError(format!("{x:?}")),
|
||||||
stack: stack.trace(),
|
stack: stack.trace(),
|
||||||
}
|
|
||||||
})?),
|
})?),
|
||||||
origin: stack.get_frame(),
|
origin,
|
||||||
cname: Some(n),
|
fname: Some(n),
|
||||||
|
name: "(dyn-read)".to_owned(),
|
||||||
}))
|
}))
|
||||||
.spl(),
|
.spl(),
|
||||||
);
|
);
|
||||||
|
@ -264,7 +259,8 @@ pub fn register(r: &mut Stack, o: Arc<Frame>) {
|
||||||
ret_count: f.2,
|
ret_count: f.2,
|
||||||
to_call: FuncImpl::Native(f.1),
|
to_call: FuncImpl::Native(f.1),
|
||||||
origin: o.clone(),
|
origin: o.clone(),
|
||||||
cname: None,
|
fname: None,
|
||||||
|
name: f.0.to_owned(),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
83
src/lexer.rs
83
src/lexer.rs
|
@ -4,26 +4,23 @@ use crate::runtime::*;
|
||||||
use readformat::*;
|
use readformat::*;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub enum LexerError {}
|
pub enum LexerError {
|
||||||
|
FunctionBlockExpected,
|
||||||
|
WrongFunctionDeclaration,
|
||||||
|
InvalidInclude,
|
||||||
|
InvalidConstructBlock,
|
||||||
|
InvalidNumber(String),
|
||||||
|
}
|
||||||
|
|
||||||
pub fn lex(input: String, filename: String, frame: Arc<Frame>) -> Result<Words, LexerError> {
|
pub fn lex(input: String) -> Result<Words, LexerError> {
|
||||||
let mut str_words = Vec::new();
|
let mut str_words = Vec::new();
|
||||||
for line in input.split('\n') {
|
for line in input.split('\n') {
|
||||||
str_words.append(&mut parse_line(line));
|
str_words.append(&mut parse_line(line));
|
||||||
}
|
}
|
||||||
Ok(read_block(
|
Ok(read_block(&str_words[..], false)?.1)
|
||||||
&str_words[..],
|
|
||||||
false,
|
|
||||||
Arc::new(Frame::new_in(frame, filename)),
|
|
||||||
)?
|
|
||||||
.1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_block(
|
fn read_block(str_words: &[String], isfn: bool) -> Result<(Option<u32>, Words, usize), LexerError> {
|
||||||
str_words: &[String],
|
|
||||||
isfn: bool,
|
|
||||||
origin: Arc<Frame>,
|
|
||||||
) -> Result<(Option<u32>, Words, usize), LexerError> {
|
|
||||||
let mut rem = None;
|
let mut rem = None;
|
||||||
let mut words = Vec::new();
|
let mut words = Vec::new();
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
|
@ -43,38 +40,32 @@ fn read_block(
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
"func" => {
|
"func" => {
|
||||||
if let Some(dat) = readf("func\0{}\0{", str_words[i..=i + 2].join("\0").as_str()) {
|
if let Some(dat) = readf1("func\0{}\0{", str_words[i..=i + 2].join("\0").as_str()) {
|
||||||
let block = read_block(
|
let block = read_block(&str_words[i + 2..], true)?;
|
||||||
&str_words[i + 2..],
|
|
||||||
true,
|
|
||||||
Arc::new(Frame::new(origin.clone())),
|
|
||||||
)?;
|
|
||||||
i += 2 + block.2;
|
i += 2 + block.2;
|
||||||
words.push(Word::Key(Keyword::Func(
|
words.push(Word::Key(Keyword::Func(
|
||||||
dat[0].to_owned(),
|
dat.to_owned(),
|
||||||
block.0.expect("LEXERR: Expected `{ <type> <...> |`."),
|
block.0.ok_or(LexerError::FunctionBlockExpected)?,
|
||||||
block.1,
|
block.1,
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"{" => {
|
"{" => {
|
||||||
let block =
|
let block = read_block(&str_words[i..], true)?;
|
||||||
read_block(&str_words[i..], true, Arc::new(Frame::new(origin.clone())))?;
|
|
||||||
i += block.2;
|
i += block.2;
|
||||||
words.push(Word::Const(Value::Func(AFunc::new(Func {
|
words.push(Word::Const(Value::Func(AFunc::new(Func {
|
||||||
ret_count: block.0.expect("LEXERR: Expected `{ <type> <...> |`."),
|
ret_count: block.0.ok_or(LexerError::FunctionBlockExpected)?,
|
||||||
to_call: FuncImpl::SPL(block.1),
|
to_call: FuncImpl::SPL(block.1),
|
||||||
origin: origin.to_owned(),
|
origin: Arc::new(Frame::dummy()),
|
||||||
cname: None,
|
fname: None,
|
||||||
|
name: "dyn".to_owned(),
|
||||||
}))))
|
}))))
|
||||||
}
|
}
|
||||||
"construct" => {
|
"construct" => {
|
||||||
let name = str_words[i + 1].to_owned();
|
let name = str_words[i + 1].to_owned();
|
||||||
assert_eq!(
|
if str_words[i + 2] != "{" {
|
||||||
str_words[i + 2],
|
return Err(LexerError::InvalidConstructBlock);
|
||||||
"{",
|
}
|
||||||
"LEXERR: Expected `construct <name> {{`, got `construct <name>`"
|
|
||||||
);
|
|
||||||
let mut fields = Vec::new();
|
let mut fields = Vec::new();
|
||||||
i += 3;
|
i += 3;
|
||||||
while str_words[i] != ";" && str_words[i] != "}" {
|
while str_words[i] != ";" && str_words[i] != "}" {
|
||||||
|
@ -90,14 +81,11 @@ fn read_block(
|
||||||
if name == "construct" {
|
if name == "construct" {
|
||||||
has_construct = true;
|
has_construct = true;
|
||||||
}
|
}
|
||||||
let block = read_block(&str_words[i + 1..], true, origin.clone())?;
|
let block = read_block(&str_words[i + 1..], true)?;
|
||||||
i += 1 + block.2;
|
i += 1 + block.2;
|
||||||
methods.push((
|
methods.push((
|
||||||
name,
|
name,
|
||||||
(
|
(block.0.ok_or(LexerError::FunctionBlockExpected)?, block.1),
|
||||||
block.0.expect("LEXERR: Expected `{ <type> <...> |`."),
|
|
||||||
block.1,
|
|
||||||
),
|
|
||||||
));
|
));
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
|
@ -117,19 +105,19 @@ fn read_block(
|
||||||
x[1].to_owned(),
|
x[1].to_owned(),
|
||||||
)))
|
)))
|
||||||
} else {
|
} else {
|
||||||
panic!("LEXERR: Expected `include <typeA> in <typeB>`.");
|
return Err(LexerError::InvalidInclude);
|
||||||
}
|
}
|
||||||
i += 3;
|
i += 3;
|
||||||
}
|
}
|
||||||
"while" => {
|
"while" => {
|
||||||
let cond = read_block(&str_words[i + 2..], false, origin.clone())?;
|
let cond = read_block(&str_words[i + 2..], false)?;
|
||||||
i += 2 + cond.2;
|
i += 2 + cond.2;
|
||||||
let blk = read_block(&str_words[i + 2..], false, origin.clone())?;
|
let blk = read_block(&str_words[i + 2..], false)?;
|
||||||
i += 2 + blk.2;
|
i += 2 + blk.2;
|
||||||
words.push(Word::Key(Keyword::While(cond.1, blk.1)));
|
words.push(Word::Key(Keyword::While(cond.1, blk.1)));
|
||||||
}
|
}
|
||||||
"if" => {
|
"if" => {
|
||||||
let blk = read_block(&str_words[i + 2..], false, origin.clone())?;
|
let blk = read_block(&str_words[i + 2..], false)?;
|
||||||
i += 2 + blk.2;
|
i += 2 + blk.2;
|
||||||
words.push(Word::Key(Keyword::If(blk.1)));
|
words.push(Word::Key(Keyword::If(blk.1)));
|
||||||
}
|
}
|
||||||
|
@ -149,15 +137,24 @@ fn read_block(
|
||||||
words.push(Word::Const(Value::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('_') => {
|
x if x.chars().all(|c| c.is_numeric() || c == '_') && !x.starts_with('_') => {
|
||||||
words.push(Word::Const(Value::Mega(x.parse().unwrap())));
|
words.push(Word::Const(Value::Mega(
|
||||||
|
x.parse()
|
||||||
|
.map_err(|_| LexerError::InvalidNumber(x.to_owned()))?,
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
x if x.chars().all(|c| c.is_numeric() || c == '.' || c == '_')
|
x if x.chars().all(|c| c.is_numeric() || c == '.' || c == '_')
|
||||||
&& !x.starts_with('_') =>
|
&& !x.starts_with('_') =>
|
||||||
{
|
{
|
||||||
words.push(Word::Const(Value::Double(x.parse().unwrap())));
|
words.push(Word::Const(Value::Double(
|
||||||
|
x.parse()
|
||||||
|
.map_err(|_| LexerError::InvalidNumber(x.to_owned()))?,
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
x => {
|
x => {
|
||||||
let mut word = x.split(':').next().unwrap();
|
let mut word = x
|
||||||
|
.split(':')
|
||||||
|
.next()
|
||||||
|
.expect("unreachable (empty words are filtered by the parser)");
|
||||||
let mut ra = 0;
|
let mut ra = 0;
|
||||||
while word.starts_with('&') {
|
while word.starts_with('&') {
|
||||||
ra += 1;
|
ra += 1;
|
||||||
|
|
58
src/main.rs
58
src/main.rs
|
@ -1,41 +1,43 @@
|
||||||
use spl::{lexer::lex, runtime::*};
|
use spl::{lexer::lex, runtime::*};
|
||||||
|
|
||||||
use std::{fs, vec};
|
use std::{fs, env::args};
|
||||||
|
|
||||||
fn main() -> OError {
|
fn main() -> OError {
|
||||||
let rt = Runtime::new();
|
let rt = Runtime::new();
|
||||||
let mut stack = Stack::new();
|
|
||||||
rt.set();
|
rt.set();
|
||||||
Words {
|
let mut stack = Stack::new_in(FrameInfo {
|
||||||
words: vec![
|
file: "std.spl".to_owned(),
|
||||||
Word::Key(Keyword::Func(
|
function: "root".to_owned(),
|
||||||
"println".to_owned(),
|
});
|
||||||
0,
|
fn argv(stack: &mut Stack) -> OError {
|
||||||
Words {
|
stack.push(Value::Array(args().into_iter().map(|x| Value::Str(x).spl()).collect()).spl());
|
||||||
words: vec![
|
Ok(())
|
||||||
Word::Call("print".to_owned(), true, 0),
|
|
||||||
Word::Const(Value::Str("\n".to_owned())),
|
|
||||||
Word::Call("print".to_owned(), true, 0),
|
|
||||||
],
|
|
||||||
},
|
|
||||||
)),
|
|
||||||
Word::Key(Keyword::Def("helloworld".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)?;
|
fn read_file(stack: &mut Stack) -> OError {
|
||||||
let words = lex(
|
let Value::Str(s) = stack.pop().lock_ro().native.clone() else {
|
||||||
fs::read_to_string("test.spl").unwrap(),
|
return stack.err(ErrorKind::InvalidCall("read_file".to_owned()))
|
||||||
"test.spl".to_owned(),
|
};
|
||||||
stack.get_frame(),
|
stack.push(Value::Str(fs::read_to_string(s).map_err(|x| stack.error(ErrorKind::IO(format!("{x:?}"))))?).spl());
|
||||||
).map_err(|x| Error {
|
Ok(())
|
||||||
|
}
|
||||||
|
stack.define_func("argv".to_owned(), AFunc::new(Func {
|
||||||
|
ret_count: 1,
|
||||||
|
to_call: FuncImpl::Native(argv),
|
||||||
|
origin: stack.get_frame(),
|
||||||
|
fname: None,
|
||||||
|
name: "argv".to_owned(),
|
||||||
|
}));
|
||||||
|
stack.define_func("read-file".to_owned(), AFunc::new(Func {
|
||||||
|
ret_count: 1,
|
||||||
|
to_call: FuncImpl::Native(read_file),
|
||||||
|
origin: stack.get_frame(),
|
||||||
|
fname: None,
|
||||||
|
name: "read-file".to_owned(),
|
||||||
|
}));
|
||||||
|
let words = lex(fs::read_to_string("std.spl").unwrap()).map_err(|x| Error {
|
||||||
kind: ErrorKind::LexError(format!("{x:?}")),
|
kind: ErrorKind::LexError(format!("{x:?}")),
|
||||||
stack: Vec::new(),
|
stack: Vec::new(),
|
||||||
})?;
|
})?;
|
||||||
println!("{words:#?}");
|
|
||||||
words.exec(&mut stack)?;
|
words.exec(&mut stack)?;
|
||||||
Runtime::reset();
|
Runtime::reset();
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
257
src/runtime.rs
257
src/runtime.rs
|
@ -3,6 +3,7 @@ use crate::{dyn_fns, mutex::*, std_fns};
|
||||||
use core::panic;
|
use core::panic;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
use std::sync::RwLockWriteGuard;
|
||||||
use std::{
|
use std::{
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
|
@ -17,11 +18,16 @@ pub type AFunc = Arc<Func>;
|
||||||
pub type OError = Result<(), Error>;
|
pub type OError = Result<(), Error>;
|
||||||
|
|
||||||
thread_local! {
|
thread_local! {
|
||||||
static RUNTIME: RefCell<Option<Runtime>> = RefCell::new(None);
|
static RUNTIME: RefCell<Option<Arc<Mut<Runtime>>>> = RefCell::new(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn runtime<T>(f: impl FnOnce(&mut Runtime) -> T) -> T {
|
pub fn runtime<T>(f: impl FnOnce(RwLockWriteGuard<Runtime>) -> T) -> T {
|
||||||
RUNTIME.with(|rt| f(rt.borrow_mut().as_mut().unwrap()))
|
RUNTIME.with(|rt| {
|
||||||
|
f(rt.borrow_mut()
|
||||||
|
.as_mut()
|
||||||
|
.expect("no runtime (use .set())")
|
||||||
|
.lock())
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -68,7 +74,11 @@ impl Runtime {
|
||||||
self.types_by_id.clone().into_values().collect()
|
self.types_by_id.clone().into_values().collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn make_type(&mut self, name: String, op: impl FnOnce(Type) -> Result<Type, Error>) -> Result<AMType, Error> {
|
pub fn make_type(
|
||||||
|
&mut self,
|
||||||
|
name: String,
|
||||||
|
op: impl FnOnce(Type) -> Result<Type, Error>,
|
||||||
|
) -> Result<AMType, Error> {
|
||||||
let t = Arc::new(Mut::new(op(Type {
|
let t = Arc::new(Mut::new(op(Type {
|
||||||
name: name.clone(),
|
name: name.clone(),
|
||||||
id: (self.next_type_id, self.next_type_id += 1).0,
|
id: (self.next_type_id, self.next_type_id += 1).0,
|
||||||
|
@ -81,18 +91,31 @@ impl Runtime {
|
||||||
Ok(t)
|
Ok(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set(self) {
|
|
||||||
RUNTIME.with(move |x| *x.borrow_mut() = Some(self));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn reset() {
|
pub fn reset() {
|
||||||
RUNTIME.with(|x| *x.borrow_mut() = None);
|
RUNTIME.with(|x| *x.borrow_mut() = None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait SetRuntime {
|
||||||
|
fn set(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SetRuntime for Runtime {
|
||||||
|
fn set(self) {
|
||||||
|
Arc::new(Mut::new(self)).set()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SetRuntime for Arc<Mut<Runtime>> {
|
||||||
|
fn set(self) {
|
||||||
|
RUNTIME.with(move |x| *x.borrow_mut() = Some(self));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct FrameInfo {
|
pub struct FrameInfo {
|
||||||
pub file: String,
|
pub file: String,
|
||||||
|
pub function: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -118,32 +141,60 @@ impl Display for Frame {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Frame {
|
impl Frame {
|
||||||
fn root() -> Self {
|
pub fn dummy() -> Self {
|
||||||
|
Frame {
|
||||||
|
parent: None,
|
||||||
|
variables: Mut::new(HashMap::new()),
|
||||||
|
functions: Mut::new(HashMap::new()),
|
||||||
|
origin: FrameInfo {
|
||||||
|
file: "\0".to_owned(),
|
||||||
|
function: "\0".to_owned(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn root() -> Self {
|
||||||
Frame {
|
Frame {
|
||||||
parent: None,
|
parent: None,
|
||||||
variables: Mut::new(HashMap::new()),
|
variables: Mut::new(HashMap::new()),
|
||||||
functions: Mut::new(HashMap::new()),
|
functions: Mut::new(HashMap::new()),
|
||||||
origin: FrameInfo {
|
origin: FrameInfo {
|
||||||
file: "RUNTIME".to_owned(),
|
file: "RUNTIME".to_owned(),
|
||||||
|
function: "root".to_owned(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(parent: Arc<Frame>) -> Self {
|
pub fn root_in(info: FrameInfo) -> Self {
|
||||||
|
Frame {
|
||||||
|
parent: None,
|
||||||
|
variables: Mut::new(HashMap::new()),
|
||||||
|
functions: Mut::new(HashMap::new()),
|
||||||
|
origin: info,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(parent: Arc<Frame>, function: String) -> Self {
|
||||||
Frame {
|
Frame {
|
||||||
variables: Mut::new(HashMap::new()),
|
variables: Mut::new(HashMap::new()),
|
||||||
functions: Mut::new(HashMap::new()),
|
functions: Mut::new(HashMap::new()),
|
||||||
origin: parent.origin.clone(),
|
origin: FrameInfo {
|
||||||
|
function,
|
||||||
|
..parent.origin.clone()
|
||||||
|
},
|
||||||
parent: Some(parent),
|
parent: Some(parent),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_in(parent: Arc<Frame>, origin: String) -> Self {
|
pub fn new_in(parent: Arc<Frame>, origin: String, function: String) -> Self {
|
||||||
Frame {
|
Frame {
|
||||||
parent: Some(parent),
|
parent: Some(parent),
|
||||||
variables: Mut::new(HashMap::new()),
|
variables: Mut::new(HashMap::new()),
|
||||||
functions: Mut::new(HashMap::new()),
|
functions: Mut::new(HashMap::new()),
|
||||||
origin: FrameInfo { file: origin },
|
origin: FrameInfo {
|
||||||
|
file: origin,
|
||||||
|
function,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,6 +232,25 @@ impl Frame {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn path(&self) -> Vec<FrameInfo> {
|
||||||
|
let mut r = Vec::new();
|
||||||
|
let mut frame = self;
|
||||||
|
loop {
|
||||||
|
r.insert(0, frame.origin.clone());
|
||||||
|
|
||||||
|
if let Some(ref parent) = frame.parent {
|
||||||
|
frame = parent;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
r
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_dummy(&self) -> bool {
|
||||||
|
self.parent.is_none() && self.origin.file == "\0" && self.origin.function == "\0"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -227,6 +297,19 @@ impl Stack {
|
||||||
r
|
r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn new_in(frame_info: FrameInfo) -> Self {
|
||||||
|
let o = Arc::new(Frame::root_in(frame_info));
|
||||||
|
let mut r = Stack {
|
||||||
|
frames: vec![o.clone()],
|
||||||
|
object_stack: Vec::new(),
|
||||||
|
};
|
||||||
|
|
||||||
|
dyn_fns::register(&mut r, o.clone());
|
||||||
|
std_fns::register(&mut r, o);
|
||||||
|
|
||||||
|
r
|
||||||
|
}
|
||||||
|
|
||||||
pub fn define_func(&mut self, name: String, func: AFunc) {
|
pub fn define_func(&mut self, name: String, func: AFunc) {
|
||||||
self.frames
|
self.frames
|
||||||
.last_mut()
|
.last_mut()
|
||||||
|
@ -237,8 +320,8 @@ impl Stack {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn call(&mut self, func: &AFunc) -> OError {
|
pub fn call(&mut self, func: &AFunc) -> OError {
|
||||||
let mut f = Frame::new(func.origin.clone());
|
let mut f = Frame::new(func.origin.clone(), func.name.clone());
|
||||||
if let Some(ref cname) = func.cname {
|
if let Some(ref cname) = func.fname {
|
||||||
f.origin.file = cname.clone();
|
f.origin.file = cname.clone();
|
||||||
}
|
}
|
||||||
self.frames.push(Arc::new(f));
|
self.frames.push(Arc::new(f));
|
||||||
|
@ -278,7 +361,8 @@ impl Stack {
|
||||||
stack.push(tmpframe.get_var(tmpname.clone(), stack)?);
|
stack.push(tmpframe.get_var(tmpname.clone(), stack)?);
|
||||||
Ok(())
|
Ok(())
|
||||||
}))),
|
}))),
|
||||||
cname: Some("RUNTIME".to_owned()),
|
fname: Some("RUNTIME".to_owned()),
|
||||||
|
name: name.clone(),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
let tmpname = name.clone();
|
let tmpname = name.clone();
|
||||||
|
@ -292,7 +376,8 @@ impl Stack {
|
||||||
let v = stack.pop();
|
let v = stack.pop();
|
||||||
tmpframe.set_var(tmpname.clone(), v, stack)
|
tmpframe.set_var(tmpname.clone(), v, stack)
|
||||||
}))),
|
}))),
|
||||||
cname: Some("RUNTIME".to_owned()),
|
fname: Some("RUNTIME".to_owned()),
|
||||||
|
name: "=".to_owned() + &name,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
frame.variables.lock().insert(name, Value::Null.spl());
|
frame.variables.lock().insert(name, Value::Null.spl());
|
||||||
|
@ -343,8 +428,42 @@ impl Stack {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn mr_trace(&self) -> Vec<Vec<FrameInfo>> {
|
||||||
|
self.frames.iter().map(|frame| frame.path()).collect()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn trace(&self) -> Vec<String> {
|
pub fn trace(&self) -> Vec<String> {
|
||||||
todo!()
|
self.frames
|
||||||
|
.iter()
|
||||||
|
.map(|frame| {
|
||||||
|
let mut item = String::new();
|
||||||
|
let path = frame.path();
|
||||||
|
let mut file = "\0".to_owned();
|
||||||
|
for element in path {
|
||||||
|
if element.file != file {
|
||||||
|
item += " | in ";
|
||||||
|
item += &element.file;
|
||||||
|
item += ":";
|
||||||
|
file = element.file;
|
||||||
|
}
|
||||||
|
item += " ";
|
||||||
|
item += &element.function;
|
||||||
|
}
|
||||||
|
item
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn peek_frame(&self, index: usize) -> Arc<Frame> {
|
||||||
|
self.frames.get(self.frames.len() - index - 1).unwrap().clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn pop_frame(&mut self, index: usize) -> Arc<Frame> {
|
||||||
|
self.frames.remove(self.frames.len() - index - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn push_frame(&mut self, frame: Arc<Frame>) {
|
||||||
|
self.frames.push(frame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -411,6 +530,26 @@ pub enum Value {
|
||||||
Str(String),
|
Str(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Value {
|
||||||
|
fn ensure_init(self, stack: &Stack) -> Self {
|
||||||
|
match self {
|
||||||
|
Value::Func(x) if x.origin.is_dummy() => Value::Func(AFunc::new(Func {
|
||||||
|
origin: stack.get_frame(),
|
||||||
|
..x.as_ref().clone()
|
||||||
|
})),
|
||||||
|
x => x,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn try_mega_to_int(self) -> Value {
|
||||||
|
if let Value::Mega(x) = self {
|
||||||
|
Value::Int(x as i32)
|
||||||
|
} else {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl PartialOrd for Value {
|
impl PartialOrd for Value {
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
|
@ -456,7 +595,8 @@ pub struct Func {
|
||||||
pub ret_count: u32,
|
pub ret_count: u32,
|
||||||
pub to_call: FuncImpl,
|
pub to_call: FuncImpl,
|
||||||
pub origin: Arc<Frame>,
|
pub origin: Arc<Frame>,
|
||||||
pub cname: Option<String>,
|
pub fname: Option<String>,
|
||||||
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for Func {
|
impl PartialEq for Func {
|
||||||
|
@ -533,7 +673,8 @@ impl Type {
|
||||||
Ok(())
|
Ok(())
|
||||||
}))),
|
}))),
|
||||||
origin: origin.clone(),
|
origin: origin.clone(),
|
||||||
cname: Some("RUNTIME".to_owned()),
|
fname: Some("RUNTIME".to_owned()),
|
||||||
|
name: name.clone(),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
let tmpname = name.clone();
|
let tmpname = name.clone();
|
||||||
|
@ -548,7 +689,8 @@ impl Type {
|
||||||
Ok(())
|
Ok(())
|
||||||
}))),
|
}))),
|
||||||
origin,
|
origin,
|
||||||
cname: Some("RUNTIME".to_owned()),
|
fname: Some("RUNTIME".to_owned()),
|
||||||
|
name: "=".to_owned() + &name,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
self.properties.push(name);
|
self.properties.push(name);
|
||||||
|
@ -580,6 +722,8 @@ impl PartialOrd for Object {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Eq for Object {}
|
||||||
|
|
||||||
impl Display for Object {
|
impl Display for Object {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
f.write_str(&self.kind.lock_ro().name)?;
|
f.write_str(&self.kind.lock_ro().name)?;
|
||||||
|
@ -629,9 +773,7 @@ impl Object {
|
||||||
impl From<Value> for Object {
|
impl From<Value> for Object {
|
||||||
fn from(value: Value) -> Self {
|
fn from(value: Value) -> Self {
|
||||||
Object::new(
|
Object::new(
|
||||||
RUNTIME.with(|x| {
|
runtime(|x| {
|
||||||
let x = x.borrow();
|
|
||||||
let x = x.as_ref().expect("no runtime (use .set())");
|
|
||||||
match value {
|
match value {
|
||||||
Value::Null => x.get_type_by_id(0),
|
Value::Null => x.get_type_by_id(0),
|
||||||
Value::Int(_) => x.get_type_by_id(1),
|
Value::Int(_) => x.get_type_by_id(1),
|
||||||
|
@ -671,12 +813,13 @@ impl Words {
|
||||||
Keyword::Dump => println!("{stack}"),
|
Keyword::Dump => println!("{stack}"),
|
||||||
Keyword::Def(x) => stack.define_var(x),
|
Keyword::Def(x) => stack.define_var(x),
|
||||||
Keyword::Func(name, rem, words) => stack.define_func(
|
Keyword::Func(name, rem, words) => stack.define_func(
|
||||||
name,
|
name.clone(),
|
||||||
Arc::new(Func {
|
Arc::new(Func {
|
||||||
ret_count: rem,
|
ret_count: rem,
|
||||||
to_call: FuncImpl::SPL(words),
|
to_call: FuncImpl::SPL(words),
|
||||||
origin: stack.get_frame(),
|
origin: stack.get_frame(),
|
||||||
cname: None,
|
fname: None,
|
||||||
|
name,
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
Keyword::Construct(name, fields, methods) => {
|
Keyword::Construct(name, fields, methods) => {
|
||||||
|
@ -685,30 +828,25 @@ impl Words {
|
||||||
stack.set_var(
|
stack.set_var(
|
||||||
name.clone(),
|
name.clone(),
|
||||||
Value::Str(
|
Value::Str(
|
||||||
RUNTIME
|
runtime(move |mut rt| {
|
||||||
.with(move |rt| {
|
rt.make_type(name.clone(), move |mut t| {
|
||||||
rt.borrow_mut().as_mut().expect("no runtime (use .set)").make_type(
|
|
||||||
name,
|
|
||||||
move |mut t| {
|
|
||||||
for field in fields {
|
for field in fields {
|
||||||
t.add_property(field, origin.clone())?;
|
t.add_property(field, origin.clone())?;
|
||||||
}
|
}
|
||||||
t.functions.extend(methods.into_iter().map(
|
t.functions.extend(methods.into_iter().map(|(k, v)| {
|
||||||
|(k, v)| {
|
|
||||||
(
|
(
|
||||||
k,
|
k.clone(),
|
||||||
Arc::new(Func {
|
Arc::new(Func {
|
||||||
ret_count: v.0,
|
ret_count: v.0,
|
||||||
to_call: FuncImpl::SPL(v.1),
|
to_call: FuncImpl::SPL(v.1),
|
||||||
origin: origin.clone(),
|
origin: origin.clone(),
|
||||||
cname: None,
|
fname: None,
|
||||||
|
name: name.clone() + ":" + &k,
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
},
|
}));
|
||||||
));
|
|
||||||
Ok(t)
|
Ok(t)
|
||||||
},
|
})
|
||||||
)
|
|
||||||
})?
|
})?
|
||||||
.lock_ro()
|
.lock_ro()
|
||||||
.get_name(),
|
.get_name(),
|
||||||
|
@ -718,16 +856,16 @@ impl Words {
|
||||||
}
|
}
|
||||||
Keyword::Include(ta, tb) => {
|
Keyword::Include(ta, tb) => {
|
||||||
let rstack = &stack;
|
let rstack = &stack;
|
||||||
RUNTIME.with(move |rt| {
|
runtime(move |rt| {
|
||||||
let mut rt = rt.borrow_mut();
|
|
||||||
let rt = rt.as_mut().expect("no runtime (use .set())");
|
|
||||||
rt.get_type_by_name(tb.clone())
|
rt.get_type_by_name(tb.clone())
|
||||||
.ok_or_else(|| rstack.error(ErrorKind::TypeNotFound(tb.clone())))?
|
.ok_or_else(|| rstack.error(ErrorKind::TypeNotFound(tb.clone())))?
|
||||||
.lock()
|
.lock()
|
||||||
.parents
|
.parents
|
||||||
.push(rt.get_type_by_name(ta).ok_or_else(|| rstack.error(ErrorKind::TypeNotFound(tb)))?);
|
.push(
|
||||||
Ok(
|
rt.get_type_by_name(ta)
|
||||||
())
|
.ok_or_else(|| rstack.error(ErrorKind::TypeNotFound(tb)))?,
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
Keyword::While(cond, blk) => loop {
|
Keyword::While(cond, blk) => loop {
|
||||||
|
@ -750,12 +888,16 @@ impl Words {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Word::Const(x) => stack.push(x.clone().spl()),
|
Word::Const(x) => stack.push(x.clone().ensure_init(stack).spl()),
|
||||||
Word::Call(x, rem, ra) => {
|
Word::Call(x, rem, ra) => {
|
||||||
let f = stack.get_func(x)?;
|
let f = stack.get_func(x.clone())?;
|
||||||
if ra != 0 {
|
if ra != 0 {
|
||||||
let mut f = Value::Func(f);
|
let mut f = Value::Func(f);
|
||||||
for _ in 1..ra {
|
for n in 1..ra {
|
||||||
|
let mut s = String::new();
|
||||||
|
for _ in 0..n {
|
||||||
|
s += "&";
|
||||||
|
}
|
||||||
let ftmp = f;
|
let ftmp = f;
|
||||||
f = Value::Func(AFunc::new(Func {
|
f = Value::Func(AFunc::new(Func {
|
||||||
ret_count: 1,
|
ret_count: 1,
|
||||||
|
@ -764,9 +906,11 @@ impl Words {
|
||||||
Ok(())
|
Ok(())
|
||||||
}))),
|
}))),
|
||||||
origin: stack.get_frame(),
|
origin: stack.get_frame(),
|
||||||
cname: None,
|
fname: None,
|
||||||
|
name: s + &x,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
stack.push(f.spl());
|
||||||
} else {
|
} else {
|
||||||
stack.call(&f)?;
|
stack.call(&f)?;
|
||||||
if rem {
|
if rem {
|
||||||
|
@ -784,7 +928,7 @@ impl Words {
|
||||||
.functions
|
.functions
|
||||||
.get(&x)
|
.get(&x)
|
||||||
.ok_or_else(|| Error {
|
.ok_or_else(|| Error {
|
||||||
kind: ErrorKind::MethodNotFound(f0.name.clone(), x),
|
kind: ErrorKind::MethodNotFound(f0.name.clone(), x.clone()),
|
||||||
stack: stack.trace(),
|
stack: stack.trace(),
|
||||||
})?
|
})?
|
||||||
.clone();
|
.clone();
|
||||||
|
@ -792,7 +936,11 @@ impl Words {
|
||||||
mem::drop(o);
|
mem::drop(o);
|
||||||
if ra != 0 {
|
if ra != 0 {
|
||||||
let mut f = Value::Func(f.clone());
|
let mut f = Value::Func(f.clone());
|
||||||
for _ in 1..ra {
|
for n in 1..ra {
|
||||||
|
let mut s = String::new();
|
||||||
|
for _ in 0..n {
|
||||||
|
s += "&";
|
||||||
|
}
|
||||||
let ftmp = f;
|
let ftmp = f;
|
||||||
f = Value::Func(AFunc::new(Func {
|
f = Value::Func(AFunc::new(Func {
|
||||||
ret_count: 1,
|
ret_count: 1,
|
||||||
|
@ -801,9 +949,11 @@ impl Words {
|
||||||
Ok(())
|
Ok(())
|
||||||
}))),
|
}))),
|
||||||
origin: stack.get_frame(),
|
origin: stack.get_frame(),
|
||||||
cname: None,
|
fname: None,
|
||||||
|
name: s + &x,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
stack.push(f.spl())
|
||||||
} else {
|
} else {
|
||||||
stack.call(&f)?;
|
stack.call(&f)?;
|
||||||
if rem {
|
if rem {
|
||||||
|
@ -830,6 +980,9 @@ pub enum ErrorKind {
|
||||||
PropertyNotFound(String, String),
|
PropertyNotFound(String, String),
|
||||||
TypeNotFound(String),
|
TypeNotFound(String),
|
||||||
LexError(String),
|
LexError(String),
|
||||||
|
IO(String),
|
||||||
|
Custom(String),
|
||||||
|
CustomObject(AMObject),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
|
|
@ -365,22 +365,75 @@ pub fn call(stack: &mut Stack) -> OError {
|
||||||
stack.call(&a)
|
stack.call(&a)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn trace(stack: &mut Stack) -> OError {
|
||||||
|
let trace = stack.trace();
|
||||||
|
stack.push(Value::Array(trace.into_iter().map(|x| Value::Str(x).spl()).collect()).spl());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mr_trace(stack: &mut Stack) -> OError {
|
||||||
|
let trace = stack.mr_trace();
|
||||||
|
let kind = runtime(|rt| rt.get_type_by_name("TraceElement".to_owned()))
|
||||||
|
.ok_or_else(|| stack.error(ErrorKind::TypeNotFound("TraceElement".to_owned())))?;
|
||||||
|
stack.push(
|
||||||
|
Value::Array(
|
||||||
|
trace
|
||||||
|
.into_iter()
|
||||||
|
.map(|x| {
|
||||||
|
Value::Array(
|
||||||
|
x.into_iter()
|
||||||
|
.map(|x| {
|
||||||
|
let item = Value::Null.spl();
|
||||||
|
let mut obj = item.lock();
|
||||||
|
for property in &kind.lock_ro().properties {
|
||||||
|
obj.property_map.insert(property.clone(), Value::Null.spl());
|
||||||
|
}
|
||||||
|
obj.kind = kind.clone();
|
||||||
|
obj.property_map
|
||||||
|
.insert("file".to_owned(), Value::Str(x.file).spl());
|
||||||
|
obj.property_map
|
||||||
|
.insert("function".to_owned(), Value::Str(x.function).spl());
|
||||||
|
mem::drop(obj);
|
||||||
|
item
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
)
|
||||||
|
.spl()
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
)
|
||||||
|
.spl(),
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn exit(stack: &mut Stack) -> OError {
|
pub fn exit(stack: &mut Stack) -> OError {
|
||||||
let Value::Int(a) = stack.pop().lock_ro().native.clone() else {
|
let Value::Int(a) = stack.pop().lock_ro().native.clone().try_mega_to_int() else {
|
||||||
return stack.err(ErrorKind::InvalidCall("exit".to_owned()))
|
return stack.err(ErrorKind::InvalidCall("exit".to_owned()))
|
||||||
};
|
};
|
||||||
process::exit(a)
|
process::exit(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn exec(stack: &mut Stack) -> OError {
|
||||||
|
let Value::Func(a) = stack.pop().lock_ro().native.clone() else {
|
||||||
|
return stack.err(ErrorKind::InvalidCall("exec".to_owned()))
|
||||||
|
};
|
||||||
|
unsafe {
|
||||||
|
let f = stack.pop_frame(0);
|
||||||
|
a.to_call.call(stack)?;
|
||||||
|
stack.push_frame(f);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn register(r: &mut Stack, o: Arc<Frame>) {
|
pub fn register(r: &mut Stack, o: Arc<Frame>) {
|
||||||
type Fn = fn(&mut Stack) -> OError;
|
type Fn = fn(&mut Stack) -> OError;
|
||||||
let fns: [(&str, Fn, u32); 28] = [
|
let fns: [(&str, Fn, u32); 31] = [
|
||||||
("pop", pop, 0),
|
("pop", pop, 0),
|
||||||
("dup", dup, 2),
|
("dup", dup, 2),
|
||||||
("clone", clone, 1),
|
("clone", clone, 1),
|
||||||
("swap", swap, 2),
|
("swap", swap, 2),
|
||||||
("print", print, 0),
|
("print", print, 0),
|
||||||
("call", call, 0),
|
|
||||||
("gettype", gettype, 1),
|
("gettype", gettype, 1),
|
||||||
("settype", settype, 1),
|
("settype", settype, 1),
|
||||||
("anew", array_new, 1),
|
("anew", array_new, 1),
|
||||||
|
@ -402,7 +455,11 @@ pub fn register(r: &mut Stack, o: Arc<Frame>) {
|
||||||
("_double", to_double, 1),
|
("_double", to_double, 1),
|
||||||
("_array", to_array, 1),
|
("_array", to_array, 1),
|
||||||
("_str", to_str, 1),
|
("_str", to_str, 1),
|
||||||
|
("call", call, 0),
|
||||||
|
("trace", trace, 1),
|
||||||
|
("mr-trace", mr_trace, 1),
|
||||||
("exit", exit, 0),
|
("exit", exit, 0),
|
||||||
|
("exec", exec, 0),
|
||||||
];
|
];
|
||||||
for f in fns {
|
for f in fns {
|
||||||
r.define_func(
|
r.define_func(
|
||||||
|
@ -411,7 +468,8 @@ pub fn register(r: &mut Stack, o: Arc<Frame>) {
|
||||||
ret_count: f.2,
|
ret_count: f.2,
|
||||||
to_call: FuncImpl::Native(f.1),
|
to_call: FuncImpl::Native(f.1),
|
||||||
origin: o.clone(),
|
origin: o.clone(),
|
||||||
cname: None,
|
fname: None,
|
||||||
|
name: f.0.to_owned(),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
151
test.spl
151
test.spl
|
@ -1,122 +1,37 @@
|
||||||
|
|
||||||
def null
|
func main { int | with args ;
|
||||||
|
def thing
|
||||||
|
|
||||||
func println { |
|
1 anew =thing
|
||||||
print "\n" print
|
|
||||||
|
"hi" 0 thing:unwrap:set;
|
||||||
|
|
||||||
|
def thing2 thing:unwrap ChangingArray:new =thing2
|
||||||
|
|
||||||
|
"world" thing2:unwrap:push
|
||||||
|
|
||||||
|
def thing3 thing2:unwrap:array =thing3
|
||||||
|
|
||||||
|
0 thing3:unwrap:get println
|
||||||
|
1 thing3:unwrap:get println
|
||||||
|
|
||||||
|
def thingy
|
||||||
|
"heya1" =thingy
|
||||||
|
"thingy println" dyn-read call
|
||||||
|
|
||||||
|
"heya2" =thingy
|
||||||
|
{ |
|
||||||
|
thingy println
|
||||||
|
{ |
|
||||||
|
{ | with it ;
|
||||||
|
it println
|
||||||
|
} trace:foreach
|
||||||
|
} call
|
||||||
|
} call
|
||||||
|
|
||||||
|
100
|
||||||
}
|
}
|
||||||
|
|
||||||
{ int | array-get } "get" "array" dyn-def-method
|
{ | with it ;
|
||||||
{ int | array-len } "len" "array" dyn-def-method
|
it println
|
||||||
{ any | array-set } "set" "array" dyn-def-method
|
} trace:foreach
|
||||||
{ | with this ;
|
|
||||||
def len this:len =len
|
|
||||||
def i 0 =i
|
|
||||||
while { i len lt } {
|
|
||||||
i this:get
|
|
||||||
i 1 + =i
|
|
||||||
}
|
|
||||||
} "to-stack" "array" dyn-def-method
|
|
||||||
|
|
||||||
{ any | with type ;
|
|
||||||
null clone type settype "construct" dyn-objcall
|
|
||||||
} "new" "str" dyn-def-method
|
|
||||||
|
|
||||||
{ | with callable this ;
|
|
||||||
def i 0 =i
|
|
||||||
while { i this:len lt } { i this:get callable call i ++ =i }
|
|
||||||
} "foreach" "array" dyn-def-method
|
|
||||||
|
|
||||||
construct ChangingArray {
|
|
||||||
array
|
|
||||||
;
|
|
||||||
construct { this | with array this ;
|
|
||||||
array this:=array
|
|
||||||
this
|
|
||||||
}
|
|
||||||
push { | with item this ;
|
|
||||||
[ this:array:to-stack item ] this:=array
|
|
||||||
}
|
|
||||||
}
|
|
||||||
construct ShrinkingArray_trait {
|
|
||||||
;
|
|
||||||
pop { any | with this ;
|
|
||||||
[ this:array:to-stack pop ] this:=array
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
include ShrinkingArray_trait in ChangingArray
|
|
||||||
|
|
||||||
"ChangingArray now has push and pop.";
|
|
||||||
|
|
||||||
construct shadow { }
|
|
||||||
|
|
||||||
"Copy array";
|
|
||||||
func acopy { array | with arr1 arr2 idx1 idx2 len ;
|
|
||||||
|
|
||||||
def i 0 =i
|
|
||||||
while { i len lt } {
|
|
||||||
(( i idx1 + ) arr1:get) (i idx2 +) arr2:set;
|
|
||||||
i 1 + =i
|
|
||||||
}
|
|
||||||
|
|
||||||
arr2
|
|
||||||
}
|
|
||||||
|
|
||||||
func aadd { array | with arr1 arr2 ;
|
|
||||||
|
|
||||||
def newarr arr1:len arr2:len + anew =newarr
|
|
||||||
|
|
||||||
arr1 newarr 0 0 arr1:len acopy =newarr
|
|
||||||
arr2 newarr 0 arr1:len arr2:len acopy =newarr
|
|
||||||
|
|
||||||
newarr
|
|
||||||
}
|
|
||||||
|
|
||||||
func [ { shadow |
|
|
||||||
"array" "shadow" settype
|
|
||||||
}
|
|
||||||
|
|
||||||
func ] { array |
|
|
||||||
"create an array containing everything on stack until the arrayshadow";
|
|
||||||
def array 0 anew =array
|
|
||||||
def array2
|
|
||||||
while { dup [ eq not } {
|
|
||||||
1 anew =array2
|
|
||||||
0 array2:set;
|
|
||||||
array2 array aadd =array
|
|
||||||
}
|
|
||||||
pop array
|
|
||||||
}
|
|
||||||
|
|
||||||
func ++ { mega |
|
|
||||||
1 +
|
|
||||||
}
|
|
||||||
|
|
||||||
{ | with type ;
|
|
||||||
"registering on " print type println
|
|
||||||
{ self | } "unwrap" type dyn-def-method
|
|
||||||
} dyn-all-types:foreach
|
|
||||||
{ | with this ;
|
|
||||||
"ERR: null cannot be unwrapped." println
|
|
||||||
1 _int exit
|
|
||||||
} "unwrap" "null" dyn-def-method
|
|
||||||
|
|
||||||
|
|
||||||
def thing
|
|
||||||
|
|
||||||
1 anew =thing
|
|
||||||
|
|
||||||
"hi" 0 thing:unwrap:set;
|
|
||||||
|
|
||||||
def thing2 thing:unwrap ChangingArray:new =thing2
|
|
||||||
|
|
||||||
"world" thing2:unwrap:push
|
|
||||||
|
|
||||||
def thing3 thing2:unwrap:array =thing3
|
|
||||||
|
|
||||||
0 thing3:unwrap:get println
|
|
||||||
1 thing3:unwrap:get println
|
|
||||||
|
|
||||||
"\"heya1\" println" dyn-read call
|
|
||||||
|
|
||||||
{ | "heya2" println } call
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue