summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortomsmeding <hallo@tomsmeding.nl>2015-09-12 08:25:21 +0200
committertomsmeding <hallo@tomsmeding.nl>2015-09-12 08:51:53 +0200
commitcff41b52e0f801eede5428d97686661b95b9756a (patch)
treef2b77e0058378d4c269d344dbb8c34979d3d82d1
parent78a145a5bb77b73f5fbefb0efa2d188926eb55ef (diff)
Fix `roll` and add its more general cousin `rotate`
-rw-r--r--bf.prn2
-rw-r--r--functions.cpp42
-rw-r--r--reference.md3
-rw-r--r--test.prn17
4 files changed, 58 insertions, 6 deletions
diff --git a/bf.prn b/bf.prn
index 59e9727..c989655 100644
--- a/bf.prn
+++ b/bf.prn
@@ -75,7 +75,7 @@ dup 0 > while
else
ord 256 %
end
- #{}"Input put on stack " print dup print lf
+ #"Input put on stack " print dup print lf
end
c ">" = if -1 roll end
c "<" = if 1 roll end
diff --git a/functions.cpp b/functions.cpp
index f4beeb9..4e67bfa 100644
--- a/functions.cpp
+++ b/functions.cpp
@@ -321,7 +321,7 @@ unordered_map<string,function<void(vector<Stackitem>&,unordered_map<string,Stack
}
scopestack.pop();
}},
- //positive n: roll OFF top to bottom; negative n: roll off bottom ONTO top
+ //positive n: roll off bottom ONTO top (clockwise); negative n: roll OFF top to bottom (anti-clockwise)
{"roll",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
BUILTIN_GUARD_STACKSIZE("roll",1)
Stackitem ns=move(S.back()); S.pop_back();
@@ -341,7 +341,6 @@ unordered_map<string,function<void(vector<Stackitem>&,unordered_map<string,Stack
S.insert(S.begin(),n,Stackitem());
for(int i=0;i<n;i++)S[i]=move(tempstore[i]);
} else {
- //cerr<<"rolling back n="<<n<<endl;
vector<Stackitem> tempstore;
tempstore.reserve(n);
for(int i=0;i<n;i++)tempstore.push_back(move(S[i]));
@@ -349,6 +348,39 @@ unordered_map<string,function<void(vector<Stackitem>&,unordered_map<string,Stack
for(int i=0;i<n;i++)S.push_back(move(tempstore[i]));
}
}},
+ //positive n: rotate off bottom ONTO top (clockwise); negative n: rotate OFF top to bottom (anti-clockwise)
+ {"rotate",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
+ BUILTIN_GUARD_STACKSIZE("rotate",2)
+ Stackitem timess=move(S.back()); S.pop_back();
+ Stackitem ns=move(S.back()); S.pop_back();
+ if(ns.type!=SIT_INT)throw string("First argument to 'rotate' not a number");
+ if(timess.type!=SIT_INT)throw string("Second argument to 'rotate' not a number");
+ int n=ns.intval,times=timess.intval;
+ bool negative=times<0;
+ if(negative)times=-times;
+ if(n>S.size()||n<0)throw string("Invalid number of items in builtin 'rotate'");
+ if(n==0)return;
+ if(S.size()<2)return;
+ times%=n;
+ if(times==0)return;
+
+ if(negative){
+ vector<Stackitem> tempstore;
+ tempstore.reserve(times);
+ const int ssz=S.size();
+ for(int i=ssz-times;i<ssz;i++)tempstore.push_back(move(S[i]));
+ S.erase(S.end()-times,S.end());
+ S.insert(S.end()-(n-times),times,Stackitem());
+ for(int i=0;i<times;i++)S[ssz-n+i]=move(tempstore[i]);
+ } else {
+ vector<Stackitem> tempstore;
+ tempstore.reserve(times);
+ const int ssz=S.size();
+ for(int i=0;i<times;i++)tempstore.push_back(move(S[ssz-n+i]));
+ S.erase(S.end()-n,S.end()-(n-times));
+ for(int i=0;i<times;i++)S.push_back(move(tempstore[i]));
+ }
+ }},
//leaves the string on the stack
{"stridx",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
BUILTIN_GUARD_STACKSIZE("stridx",2)
@@ -473,15 +505,17 @@ unordered_map<string,function<void(vector<Stackitem>&,unordered_map<string,Stack
}},
{"rand",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
BUILTIN_GUARD_STACKSIZE("rand",0)
- assert(RAND_MAX==0x7fffffff);
+#if RAND_MAX != 0x7fffffff
+# error RAND_MAX should be 0x7fffffff for Postrun
+#endif
S.emplace_back(rand());
}},
//`to` exclusive
{"randr",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
BUILTIN_GUARD_STACKSIZE("rand",2)
assert(RAND_MAX==0x7fffffff);
- const Stackitem from=move(S.back()); S.pop_back();
const Stackitem to=move(S.back()); S.pop_back();
+ const Stackitem from=move(S.back()); S.pop_back();
if(from.type!=SIT_INT)throw string("First argument to 'randr' not a number");
if(to.type!=SIT_INT)throw string("Second argument to 'randr' not a number");
if(to.intval<=from.intval)throw string("Arguments to 'randr' form an empty range");
diff --git a/reference.md b/reference.md
index 13c7b2f..807664a 100644
--- a/reference.md
+++ b/reference.md
@@ -35,7 +35,8 @@ n `get` | Get value of variable with name `n`
n `swapoutvar` | Get value of variable with name `n`, *moving* onto the stack instead of copying
`enterscope` | Enter a function variable scope
`leavescope` | Leave a function variable scope
-n `roll` | Roll the stack by `n`; positive n: roll OFF top to bottom; negative n: roll off bottom ONTO top
+t `roll` | Roll the stack `t` times; positive n: roll off bottom ONTO top (clockwise); negative n: roll OFF top to bottom (anti-clockwise)
+n t `rotate` | Rotate the top `n` items of the stack `t` times; positive n: rotate off bottom ONTO top (clockwise); negative n: rotate OFF top to bottom (anti-clockwise)
s i `stridx` | Gets the character in string `s` index `i`, leaving `s` on the stack
s `strlen` | Gets the length of string `s`, leaving `s` on the stack
s a b `substr` | Gets the substring in `s` from index `a` to `b`, `b` exclusive; leaving `s` on the stack
diff --git a/test.prn b/test.prn
index 65549f9..ee29b6e 100644
--- a/test.prn
+++ b/test.prn
@@ -20,3 +20,20 @@ end
42 "vv" store
vv print lf
+
+pop
+
+1 2 3 4 5 6 stackdump
+4 1 rotate stackdump
+4 1 rotate stackdump
+4 1 rotate stackdump
+4 1 rotate stackdump
+5 2 rotate stackdump
+5 -2 rotate stackdump
+lf
+6 -1 rotate stackdump
+6 5 rotate stackdump
+-1 roll stackdump
+6 1 rotate stackdump
+6 7 rotate stackdump
+1 roll stackdump