improve speed, add time.spl, improve isbpl.spl, add inlining support
This commit is contained in:
parent
6d78b276d4
commit
a1f5941c1a
11 changed files with 230 additions and 32 deletions
61
benchmark.spl
Normal file
61
benchmark.spl
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
"#time.spl" import
|
||||||
|
|
||||||
|
func main { mega | with args ;
|
||||||
|
def begin
|
||||||
|
def end
|
||||||
|
|
||||||
|
"[-] spl benchmark v0.1.0" println
|
||||||
|
"[0] benchmarking while loop with variable 0..100000" println
|
||||||
|
"==> bgin at " print unixms dup =begin println
|
||||||
|
def i 0 =i
|
||||||
|
while { i 100000 lt } {
|
||||||
|
i ++ =i
|
||||||
|
}
|
||||||
|
"==> done at " print unixms dup =end println
|
||||||
|
"==> in " print end begin - println
|
||||||
|
|
||||||
|
"[1] benchmarking foreach on 100000" println
|
||||||
|
"==> bgin at " print unixms dup =begin println
|
||||||
|
{ | pop } 100000 :foreach
|
||||||
|
"==> done at " print unixms dup =end println
|
||||||
|
"==> in " print end begin - println
|
||||||
|
|
||||||
|
"[2] benchmarking fast foreach on 100000" println
|
||||||
|
"==> bgin at " print unixms dup =begin println
|
||||||
|
{ | pop } 100000 :fforeach
|
||||||
|
"==> done at " print unixms dup =end println
|
||||||
|
"==> in " print end begin - println
|
||||||
|
|
||||||
|
"[3] benchmarking foreach on Range 100000..200000" println
|
||||||
|
"==> bgin at " print unixms dup =begin println
|
||||||
|
100000 200000 Range:new
|
||||||
|
:iter
|
||||||
|
:foreach <{ | with i ; }>
|
||||||
|
"==> done at " print unixms dup =end println
|
||||||
|
"==> in " print end begin - println
|
||||||
|
|
||||||
|
"[4] benchmarking manual multiply of 100000 x 5" println
|
||||||
|
"==> bgin at " print unixms dup =begin println
|
||||||
|
def i 0 =i
|
||||||
|
def n 0 =n
|
||||||
|
while { i 100000 lt } {
|
||||||
|
i ++ =i
|
||||||
|
n 5 + =n
|
||||||
|
}
|
||||||
|
" -> n = " print n println
|
||||||
|
"==> done at " print unixms dup =end println
|
||||||
|
"==> in " print end begin - println
|
||||||
|
|
||||||
|
"[5] benchmarking 10000 array adds" println
|
||||||
|
"==> bgin at " print unixms dup =begin println
|
||||||
|
def i 0 =i
|
||||||
|
def arr 0 anew =arr
|
||||||
|
while { i 10000 lt } {
|
||||||
|
i awrap arr aadd =arr
|
||||||
|
i ++ =i
|
||||||
|
}
|
||||||
|
"==> done at " print unixms dup =end println
|
||||||
|
"==> in " print end begin - println
|
||||||
|
|
||||||
|
0
|
||||||
|
}
|
19
isbpl.spl
19
isbpl.spl
|
@ -1,3 +1,4 @@
|
||||||
|
"#time.spl" import
|
||||||
native engage-compatibility-mode
|
native engage-compatibility-mode
|
||||||
func # { pop }
|
func # { pop }
|
||||||
func puts { print }
|
func puts { print }
|
||||||
|
@ -5,6 +6,8 @@ func fcall { call }
|
||||||
func strconcat { concat }
|
func strconcat { concat }
|
||||||
func aget { swap :get }
|
func aget { swap :get }
|
||||||
func stoi { _mega }
|
func stoi { _mega }
|
||||||
|
func stol { _mega }
|
||||||
|
func _int { _mega }
|
||||||
func itos { _str }
|
func itos { _str }
|
||||||
def argv'pre-isbplmod &argv =argv'pre-isbplmod
|
def argv'pre-isbplmod &argv =argv'pre-isbplmod
|
||||||
func argv {
|
func argv {
|
||||||
|
@ -13,6 +16,17 @@ func argv {
|
||||||
args nargs 2 0 nargs:len acopy
|
args nargs 2 0 nargs:len acopy
|
||||||
nargs
|
nargs
|
||||||
}
|
}
|
||||||
|
func eputs {
|
||||||
|
print
|
||||||
|
}
|
||||||
|
func isbplmod'import-transform { with s ;
|
||||||
|
"spl: [compat] transforming import " s concat println
|
||||||
|
s:_char "#" :_char eq if {
|
||||||
|
"#nop.spl" =s
|
||||||
|
}
|
||||||
|
"spl: [compat] transformed to " s concat println
|
||||||
|
s
|
||||||
|
}
|
||||||
func inc {
|
func inc {
|
||||||
"isbpl.spl: ISBPL code tried to call inc, an untranslatable function" println
|
"isbpl.spl: ISBPL code tried to call inc, an untranslatable function" println
|
||||||
pop
|
pop
|
||||||
|
@ -21,3 +35,8 @@ func dec {
|
||||||
"isbpl.spl: ISBPL code tried to call inc, an untranslatable function" println
|
"isbpl.spl: ISBPL code tried to call inc, an untranslatable function" println
|
||||||
pop
|
pop
|
||||||
}
|
}
|
||||||
|
func getms {
|
||||||
|
0 time
|
||||||
|
}
|
||||||
|
|
||||||
|
func main { }
|
||||||
|
|
7
iter.spl
7
iter.spl
|
@ -11,10 +11,11 @@ construct _Iter {
|
||||||
arr
|
arr
|
||||||
}
|
}
|
||||||
foreach { | with callable this ;
|
foreach { | with callable this ;
|
||||||
def itm
|
!!-
|
||||||
while { this:next dup =itm null eq not } {
|
while { !!- this:next dup null eq not } {
|
||||||
itm callable call
|
!!- callable call
|
||||||
}
|
}
|
||||||
|
pop
|
||||||
}
|
}
|
||||||
collect { array | with this ;
|
collect { array | with this ;
|
||||||
[ { any | } this:foreach ]
|
[ { any | } this:foreach ]
|
||||||
|
|
17
src/lexer.rs
17
src/lexer.rs
|
@ -3,7 +3,7 @@ mod compat;
|
||||||
use std::{mem, sync::Arc};
|
use std::{mem, sync::Arc};
|
||||||
|
|
||||||
use crate::runtime::*;
|
use crate::runtime::*;
|
||||||
use compat::match_compat;
|
use compat::{match_compat, transform_compat};
|
||||||
use readformat::*;
|
use readformat::*;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
@ -57,7 +57,11 @@ fn read_block_dyn(
|
||||||
rem = Some(r as u32);
|
rem = Some(r as u32);
|
||||||
}
|
}
|
||||||
while i < str_words.len() {
|
while i < str_words.len() {
|
||||||
let word = str_words[i].to_owned();
|
let word = if !compat {
|
||||||
|
str_words[i].to_owned()
|
||||||
|
} else {
|
||||||
|
transform_compat(&str_words[i])
|
||||||
|
};
|
||||||
if compat && match_compat(word.to_owned(), str_words, &mut words, &mut i) {
|
if compat && match_compat(word.to_owned(), str_words, &mut words, &mut i) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -236,6 +240,15 @@ fn read_block_dyn(
|
||||||
}
|
}
|
||||||
words.push(Word::Key(Keyword::With(vars)));
|
words.push(Word::Key(Keyword::With(vars)));
|
||||||
}
|
}
|
||||||
|
"inline-callable" => {
|
||||||
|
words.push(Word::Key(Keyword::InlineCallable));
|
||||||
|
}
|
||||||
|
"!!-" => {
|
||||||
|
words.push(Word::Key(Keyword::InlineStart));
|
||||||
|
}
|
||||||
|
"-!!" => {
|
||||||
|
words.push(Word::Key(Keyword::InlineEnd));
|
||||||
|
}
|
||||||
x if x == endword => {
|
x if x == endword => {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
use crate::Word;
|
use crate::Word;
|
||||||
|
|
||||||
|
pub(crate) fn transform_compat(word: &str) -> String {
|
||||||
|
match word {
|
||||||
|
"try" => "catch".to_owned(),
|
||||||
|
_ => word.to_owned(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn match_compat(
|
pub(crate) fn match_compat(
|
||||||
word: String,
|
word: String,
|
||||||
str_words: &[String],
|
str_words: &[String],
|
||||||
|
@ -15,6 +22,7 @@ pub(crate) fn match_compat(
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
"dec" => {
|
"dec" => {
|
||||||
|
eprintln!("spl: [compat] transforming dec call");
|
||||||
eprintln!("spl: [compat] transforming dec call");
|
eprintln!("spl: [compat] transforming dec call");
|
||||||
words.push(Word::Call("--".to_owned(), false, 0));
|
words.push(Word::Call("--".to_owned(), false, 0));
|
||||||
words.push(Word::Call("=".to_owned() + &str_words[*i - 1], false, 0));
|
words.push(Word::Call("=".to_owned() + &str_words[*i - 1], false, 0));
|
||||||
|
@ -22,8 +30,9 @@ pub(crate) fn match_compat(
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
"include" => {
|
"include" => {
|
||||||
// TODO: translate some stdlib components?
|
words.push(Word::Call("isbplmod'import-transform".to_owned(), false, 0));
|
||||||
words.push(Word::Call("import".to_owned(), false, 0));
|
words.push(Word::Call("import".to_owned(), false, 0));
|
||||||
|
*i += 1;
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
|
|
|
@ -470,6 +470,11 @@ impl Stack {
|
||||||
r
|
r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn fast_call(&mut self, func: &AFunc) -> OError {
|
||||||
|
let r = func.to_call.call(self);
|
||||||
|
r
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_func(&self, name: String) -> Result<AFunc, Error> {
|
pub fn get_func(&self, name: String) -> Result<AFunc, Error> {
|
||||||
let mut frame = self.frames.last().unwrap();
|
let mut frame = self.frames.last().unwrap();
|
||||||
loop {
|
loop {
|
||||||
|
@ -649,6 +654,21 @@ pub enum Keyword {
|
||||||
/// equivalent to dyn-__dump
|
/// equivalent to dyn-__dump
|
||||||
/// example: func main { int | "Hello, world!" dyn-__dump pop 0 }
|
/// example: func main { int | "Hello, world!" dyn-__dump pop 0 }
|
||||||
Dump,
|
Dump,
|
||||||
|
/// inline-call
|
||||||
|
///
|
||||||
|
/// Inlines a callable into the current function
|
||||||
|
/// equivalent to call
|
||||||
|
InlineCallable,
|
||||||
|
/// !!-
|
||||||
|
///
|
||||||
|
/// Makes future calls inline, not adding a new stack frame
|
||||||
|
/// no equivalent
|
||||||
|
InlineStart,
|
||||||
|
/// -!!
|
||||||
|
///
|
||||||
|
/// Stops making calls inline
|
||||||
|
/// no equivalent
|
||||||
|
InlineEnd,
|
||||||
/// def <name>
|
/// def <name>
|
||||||
///
|
///
|
||||||
/// Defines a variable.
|
/// Defines a variable.
|
||||||
|
@ -1144,20 +1164,35 @@ impl Words {
|
||||||
/// Executes the words. This does *not* create a new frame on the stack. Use [Stack::call] to
|
/// Executes the words. This does *not* create a new frame on the stack. Use [Stack::call] to
|
||||||
/// call and create a new frame.
|
/// call and create a new frame.
|
||||||
pub fn exec(&self, stack: &mut Stack) -> OError {
|
pub fn exec(&self, stack: &mut Stack) -> OError {
|
||||||
for word in self.words.clone() {
|
let mut inline_calls = false;
|
||||||
|
for word in self.words.iter() {
|
||||||
match word {
|
match word {
|
||||||
Word::Key(x) => match x {
|
Word::Key(x) => match x {
|
||||||
Keyword::Dump => println!("{stack}"),
|
Keyword::Dump => println!("{stack}"),
|
||||||
Keyword::Def(x) => stack.define_var(x),
|
Keyword::InlineCallable => {
|
||||||
|
let Value::Func(f) = stack.pop().lock_ro().native.clone() else {
|
||||||
|
return Err(
|
||||||
|
stack.error(ErrorKind::InvalidCall("inline-callable".to_owned()))
|
||||||
|
);
|
||||||
|
};
|
||||||
|
stack.fast_call(&f)?;
|
||||||
|
}
|
||||||
|
Keyword::InlineStart => {
|
||||||
|
inline_calls = true;
|
||||||
|
}
|
||||||
|
Keyword::InlineEnd => {
|
||||||
|
inline_calls = false;
|
||||||
|
}
|
||||||
|
Keyword::Def(x) => stack.define_var(x.to_owned()),
|
||||||
Keyword::Func(name, rem, words) => stack.define_func(
|
Keyword::Func(name, rem, words) => stack.define_func(
|
||||||
name.clone(),
|
name.clone(),
|
||||||
Arc::new(Func {
|
Arc::new(Func {
|
||||||
ret_count: rem,
|
ret_count: *rem,
|
||||||
to_call: FuncImpl::SPL(words),
|
to_call: FuncImpl::SPL(words.to_owned()),
|
||||||
origin: stack.get_frame(),
|
origin: stack.get_frame(),
|
||||||
run_as_base: false,
|
run_as_base: false,
|
||||||
fname: None,
|
fname: None,
|
||||||
name,
|
name: name.to_owned(),
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
Keyword::Construct(name, fields, methods, is_namespace) => {
|
Keyword::Construct(name, fields, methods, is_namespace) => {
|
||||||
|
@ -1168,14 +1203,14 @@ impl Words {
|
||||||
let t = runtime_mut(|mut rt| {
|
let t = runtime_mut(|mut rt| {
|
||||||
rt.make_type(name.clone(), |mut t| {
|
rt.make_type(name.clone(), |mut t| {
|
||||||
for field in fields {
|
for field in fields {
|
||||||
t.add_property(field, origin.clone())?;
|
t.add_property(field.to_owned(), origin.clone())?;
|
||||||
}
|
}
|
||||||
t.functions.extend(methods.into_iter().map(|(k, v)| {
|
t.functions.extend(methods.into_iter().map(|(k, v)| {
|
||||||
(
|
(
|
||||||
k.clone(),
|
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.to_owned()),
|
||||||
origin: origin.clone(),
|
origin: origin.clone(),
|
||||||
run_as_base: false,
|
run_as_base: false,
|
||||||
fname: None,
|
fname: None,
|
||||||
|
@ -1187,7 +1222,7 @@ impl Words {
|
||||||
})
|
})
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let to_set: Object = if is_namespace {
|
let to_set: Object = if *is_namespace {
|
||||||
let mut obj: Object = Value::Null.into();
|
let mut obj: Object = Value::Null.into();
|
||||||
obj.kind = t.clone();
|
obj.kind = t.clone();
|
||||||
t.lock_ro().write_into(&mut obj);
|
t.lock_ro().write_into(&mut obj);
|
||||||
|
@ -1216,13 +1251,14 @@ impl Words {
|
||||||
let rstack = &stack;
|
let rstack = &stack;
|
||||||
runtime(move |rt| {
|
runtime(move |rt| {
|
||||||
rt.get_type_by_name(&tb)
|
rt.get_type_by_name(&tb)
|
||||||
.ok_or_else(|| rstack.error(ErrorKind::TypeNotFound(tb)))?
|
.ok_or_else(|| {
|
||||||
|
rstack.error(ErrorKind::TypeNotFound(tb.to_owned()))
|
||||||
|
})?
|
||||||
.lock()
|
.lock()
|
||||||
.parents
|
.parents
|
||||||
.push(
|
.push(rt.get_type_by_name(&ta).ok_or_else(|| {
|
||||||
rt.get_type_by_name(&ta)
|
rstack.error(ErrorKind::TypeNotFound(ta.to_owned()))
|
||||||
.ok_or_else(|| rstack.error(ErrorKind::TypeNotFound(ta)))?,
|
})?);
|
||||||
);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
|
@ -1271,7 +1307,7 @@ impl Words {
|
||||||
for var in vars.into_iter().rev() {
|
for var in vars.into_iter().rev() {
|
||||||
stack.define_var(var.clone());
|
stack.define_var(var.clone());
|
||||||
let obj = stack.pop();
|
let obj = stack.pop();
|
||||||
stack.set_var(var, obj)?;
|
stack.set_var(var.to_owned(), obj)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Keyword::ObjPush => {
|
Keyword::ObjPush => {
|
||||||
|
@ -1295,7 +1331,7 @@ impl Words {
|
||||||
origin: stack.get_frame(),
|
origin: stack.get_frame(),
|
||||||
run_as_base: false,
|
run_as_base: false,
|
||||||
fname: None,
|
fname: None,
|
||||||
name,
|
name: name.to_owned(),
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
|
@ -1307,6 +1343,7 @@ impl Words {
|
||||||
stack.push(x.clone().ensure_init(stack).spl())
|
stack.push(x.clone().ensure_init(stack).spl())
|
||||||
}
|
}
|
||||||
Word::Call(x, rem, ra) => {
|
Word::Call(x, rem, ra) => {
|
||||||
|
let ra = *ra;
|
||||||
if option_env!("SPLDEBUG").is_some() {
|
if option_env!("SPLDEBUG").is_some() {
|
||||||
println!("CALL({}) {x}", stack.len());
|
println!("CALL({}) {x}", stack.len());
|
||||||
}
|
}
|
||||||
|
@ -1333,8 +1370,12 @@ impl Words {
|
||||||
}
|
}
|
||||||
stack.push(f.spl());
|
stack.push(f.spl());
|
||||||
} else {
|
} else {
|
||||||
stack.call(&f)?;
|
if inline_calls {
|
||||||
if rem {
|
stack.fast_call(&f)?;
|
||||||
|
} else {
|
||||||
|
stack.call(&f)?;
|
||||||
|
}
|
||||||
|
if *rem {
|
||||||
for _ in 0..f.ret_count {
|
for _ in 0..f.ret_count {
|
||||||
stack.pop();
|
stack.pop();
|
||||||
}
|
}
|
||||||
|
@ -1342,6 +1383,7 @@ impl Words {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Word::ObjCall(x, rem, ra) => {
|
Word::ObjCall(x, rem, ra) => {
|
||||||
|
let ra = *ra;
|
||||||
let o = stack.peek();
|
let o = stack.peek();
|
||||||
let o = o.lock_ro();
|
let o = o.lock_ro();
|
||||||
let f0 = o.kind.lock_ro();
|
let f0 = o.kind.lock_ro();
|
||||||
|
@ -1379,8 +1421,12 @@ impl Words {
|
||||||
stack.pop();
|
stack.pop();
|
||||||
stack.push(f.spl())
|
stack.push(f.spl())
|
||||||
} else {
|
} else {
|
||||||
stack.call(&f)?;
|
if inline_calls {
|
||||||
if rem {
|
stack.fast_call(&f)?;
|
||||||
|
} else {
|
||||||
|
stack.call(&f)?;
|
||||||
|
}
|
||||||
|
if *rem {
|
||||||
for _ in 0..f.ret_count {
|
for _ in 0..f.ret_count {
|
||||||
stack.pop();
|
stack.pop();
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,9 @@ fn sasm_parse<'a>(line: &str, words: &mut Vec<Word>, lines: &mut impl Iterator<I
|
||||||
let line: Vec<_> = line.split(" ").collect();
|
let line: Vec<_> = line.split(" ").collect();
|
||||||
match line[0] {
|
match line[0] {
|
||||||
"dump" => words.push(Word::Key(Keyword::Dump)),
|
"dump" => words.push(Word::Key(Keyword::Dump)),
|
||||||
|
"inline-callable" => words.push(Word::Key(Keyword::InlineCallable)),
|
||||||
|
"inline-start" => words.push(Word::Key(Keyword::InlineStart)),
|
||||||
|
"inline-end" => words.push(Word::Key(Keyword::InlineEnd)),
|
||||||
"def" => words.push(Word::Key(Keyword::Def(line[1].to_owned()))),
|
"def" => words.push(Word::Key(Keyword::Def(line[1].to_owned()))),
|
||||||
"func" => words.push(Word::Key(Keyword::Func(
|
"func" => words.push(Word::Key(Keyword::Func(
|
||||||
line[1].to_owned(),
|
line[1].to_owned(),
|
||||||
|
@ -223,6 +226,9 @@ fn sasm_write_func(words: Words) -> String {
|
||||||
Keyword::Dump => {
|
Keyword::Dump => {
|
||||||
output += "dump\n";
|
output += "dump\n";
|
||||||
}
|
}
|
||||||
|
Keyword::InlineCallable => output += "inline-callable\n",
|
||||||
|
Keyword::InlineStart => output += "inline-start\n",
|
||||||
|
Keyword::InlineEnd => output += "inline-end\n",
|
||||||
Keyword::Def(x) => {
|
Keyword::Def(x) => {
|
||||||
output += "def ";
|
output += "def ";
|
||||||
output += &x;
|
output += &x;
|
||||||
|
|
|
@ -8,6 +8,7 @@ use std::{
|
||||||
process::{self, Stdio},
|
process::{self, Stdio},
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
thread,
|
thread,
|
||||||
|
time::{Duration, SystemTime},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{dyn_fns, mutex::Mut, runtime::*, sasm::sasm_write, *};
|
use crate::{dyn_fns, mutex::Mut, runtime::*, sasm::sasm_write, *};
|
||||||
|
@ -51,6 +52,13 @@ pub fn dup(stack: &mut Stack) -> OError {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn dup2(stack: &mut Stack) -> OError {
|
||||||
|
let o = stack.peek();
|
||||||
|
stack.push(o.clone());
|
||||||
|
stack.push(o);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn pop(stack: &mut Stack) -> OError {
|
pub fn pop(stack: &mut Stack) -> OError {
|
||||||
stack.pop();
|
stack.pop();
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -854,11 +862,27 @@ pub fn fork(stack: &mut Stack) -> OError {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn time(stack: &mut Stack) -> OError {
|
||||||
|
require_on_stack!(sleep_ms, Mega, stack, "time");
|
||||||
|
if sleep_ms != 0 {
|
||||||
|
thread::sleep(Duration::from_millis(sleep_ms as u64));
|
||||||
|
}
|
||||||
|
stack.push(
|
||||||
|
(SystemTime::now()
|
||||||
|
.duration_since(SystemTime::UNIX_EPOCH)
|
||||||
|
.unwrap()
|
||||||
|
.as_millis() as i128)
|
||||||
|
.spl(),
|
||||||
|
);
|
||||||
|
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); 54] = [
|
let fns: [(&str, Fn, u32); 56] = [
|
||||||
("pop", pop, 0),
|
("pop", pop, 0),
|
||||||
("dup", dup, 2),
|
("dup", dup, 2),
|
||||||
|
("dup2", dup2, 3),
|
||||||
("clone", clone, 1),
|
("clone", clone, 1),
|
||||||
("swap", swap, 2),
|
("swap", swap, 2),
|
||||||
("mswap", mswap, 2),
|
("mswap", mswap, 2),
|
||||||
|
@ -911,6 +935,7 @@ pub fn register(r: &mut Stack, o: Arc<Frame>) {
|
||||||
("write-sasm", write_sasm, 1),
|
("write-sasm", write_sasm, 1),
|
||||||
("write-file-sasm", write_file_sasm, 1),
|
("write-file-sasm", write_file_sasm, 1),
|
||||||
("fork", fork, 0),
|
("fork", fork, 0),
|
||||||
|
("time", time, 0),
|
||||||
];
|
];
|
||||||
for f in fns {
|
for f in fns {
|
||||||
r.define_func(
|
r.define_func(
|
||||||
|
|
|
@ -11,6 +11,8 @@ pub const ASSEMBLE: &str = include_str!("../assemble.spl");
|
||||||
pub const ISBPL: &str = include_str!("../isbpl.spl");
|
pub const ISBPL: &str = include_str!("../isbpl.spl");
|
||||||
pub const REPL: &str = include_str!("../repl.spl");
|
pub const REPL: &str = include_str!("../repl.spl");
|
||||||
pub const PURE: &str = include_str!("../pure.spl");
|
pub const PURE: &str = include_str!("../pure.spl");
|
||||||
|
pub const TIME: &str = include_str!("../time.spl");
|
||||||
|
pub const NOP: &str = "";
|
||||||
|
|
||||||
pub fn register(runtime: &mut Runtime) {
|
pub fn register(runtime: &mut Runtime) {
|
||||||
multicall! {
|
multicall! {
|
||||||
|
@ -25,5 +27,7 @@ pub fn register(runtime: &mut Runtime) {
|
||||||
insert("isbpl.spl", ISBPL);
|
insert("isbpl.spl", ISBPL);
|
||||||
insert("repl.spl", REPL);
|
insert("repl.spl", REPL);
|
||||||
insert("pure.spl", PURE);
|
insert("pure.spl", PURE);
|
||||||
|
insert("time.spl", TIME);
|
||||||
|
insert("nop.spl", NOP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
20
std.spl
20
std.spl
|
@ -12,7 +12,7 @@ func print { |
|
||||||
}
|
}
|
||||||
|
|
||||||
func println { |
|
func println { |
|
||||||
"\n" concat print
|
!!- _str "\n" concat print
|
||||||
}
|
}
|
||||||
|
|
||||||
construct error {
|
construct error {
|
||||||
|
@ -96,7 +96,10 @@ construct _mega-ext {
|
||||||
mswap { .. | mswap }
|
mswap { .. | mswap }
|
||||||
foreach { | with callable this ;
|
foreach { | with callable this ;
|
||||||
def i 0 =i
|
def i 0 =i
|
||||||
while { i this lt } { i callable call i ++ =i }
|
while { !!- i this lt } { !!- i callable call i 1 + =i }
|
||||||
|
}
|
||||||
|
fforeach { | with callable this ;
|
||||||
|
0 while { !!- dup2 this lt } { !!- callable inline-callable 1 + }
|
||||||
}
|
}
|
||||||
} include _mega-ext in mega
|
} include _mega-ext in mega
|
||||||
|
|
||||||
|
@ -368,16 +371,21 @@ construct Range {
|
||||||
}
|
}
|
||||||
|
|
||||||
construct RangeIter {
|
construct RangeIter {
|
||||||
range
|
upper step
|
||||||
idx
|
idx
|
||||||
;
|
;
|
||||||
construct { this | with range this ;
|
construct { this | with range this ;
|
||||||
range this:=range
|
range:lower this:=idx
|
||||||
0 this:=idx
|
range:upper this:=upper
|
||||||
|
range:step this:=step
|
||||||
this
|
this
|
||||||
}
|
}
|
||||||
next { mega | with this ;
|
next { mega | with this ;
|
||||||
this:idx dup ++ this:=idx this:range:item
|
!!-
|
||||||
|
this:idx dup this:step + this:=idx
|
||||||
|
dup this:upper lt not if {
|
||||||
|
pop null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
6
time.spl
Normal file
6
time.spl
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
|
||||||
|
func unixms { mega |
|
||||||
|
0 time
|
||||||
|
}
|
||||||
|
|
||||||
|
func sleep { mega | time }
|
Loading…
Add table
Reference in a new issue