aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/llgcode/ps/operators_stack.go
blob: 6b7480d62015d4c66f7eea4d28f41d1d95625bb0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
// Copyright 2010 The postscript-go Authors. All rights reserved.
// created: 13/12/2010 by Laurent Le Goff

//Operand Stack Manipulation Operators
package ps

//any pop – -> Discard top element
func pop(interpreter *Interpreter) {
	interpreter.Pop()
}

//any1  any2 exch any2  any1 -> Exchange top two elements
func exch(interpreter *Interpreter) {
	value1 := interpreter.Pop()
	value2 := interpreter.Pop()
	interpreter.Push(value1)
	interpreter.Push(value2)
}

//any dup any  any -> Duplicate top element
func dup(interpreter *Interpreter) {
	interpreter.Push(interpreter.Peek())
}

//any1  …  anyn  n copy any1  …  anyn  any1  …  anyn -> Duplicate top n elements
func copystack(interpreter *Interpreter) {
	n := interpreter.PopInt()
	values := interpreter.GetValues(n)
	for _, value := range values {
		interpreter.Push(value)
	}
}

//anyn  …  any0  n index anyn …  any0  anyn -> Duplicate arbitrary element
func index(interpreter *Interpreter) {
	f := interpreter.PopInt()
	interpreter.Push(interpreter.Get(int(f)))
}

//anyn−1  …  any0  n  j roll any(j−1) mod n  …  any0  anyn−1  …  anyj mod n -> Roll n elements up j times
func roll(interpreter *Interpreter) {
	j := interpreter.PopInt()
	n := interpreter.PopInt()
	values := interpreter.PopValues(n)
	j %= n
	for i := 0; i < n; i++ {
		interpreter.Push(values[(n+i-j)%n])
	}
}

//any1  …  anyn clear -> Discard all elements
func clear(interpreter *Interpreter) {
	interpreter.ClearOperands()
}

//any1  …  anyn count any1  …  anyn  n -> Count elements on stack
func count(interpreter *Interpreter) {
	interpreter.Push(interpreter.OperandSize())
}

//Mark
type Mark struct{}

//– mark mark -> Push mark on stack
func mark(interpreter *Interpreter) {
	interpreter.Push(Mark{})
}

//mark  obj 1  …  obj n cleartomark – -> Discard elements down through mark
func cleartomark(interpreter *Interpreter) {
	value := interpreter.Pop()
	for _, ok := value.(Mark); !ok; {
		value = interpreter.Pop()
	}
}

//mark  obj 1  …  obj n counttomark mark  obj 1  …  obj n  n -> Count elements down to mark
func counttomark(interpreter *Interpreter) {
	i := 0
	value := interpreter.Get(i)
	for _, ok := value.(Mark); !ok; i++ {
		value = interpreter.Get(i)
	}
	interpreter.Push(float64(i))
}

func initStackOperator(interpreter *Interpreter) {
	interpreter.SystemDefine("pop", NewOperator(pop))
	interpreter.SystemDefine("exch", NewOperator(exch))
	interpreter.SystemDefine("dup", NewOperator(dup))
	interpreter.SystemDefine("index", NewOperator(index))
	interpreter.SystemDefine("roll", NewOperator(roll))
	interpreter.SystemDefine("clear", NewOperator(clear))
	interpreter.SystemDefine("count", NewOperator(count))
	interpreter.SystemDefine("mark", NewOperator(mark))
	interpreter.SystemDefine("cleartomark", NewOperator(mark))
	interpreter.SystemDefine("counttomark", NewOperator(mark))
}