Skip to content

Commit bdf9637

Browse files
committed
0.37.0
1 parent a31e425 commit bdf9637

11 files changed

Lines changed: 105 additions & 46 deletions

File tree

changelog.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# Changelog
22

3+
## 0.37.0
4+
5+
- Page now has 'comma notation' for using dot notation on values on the stack, e.g. `,set`, `,names.add`
6+
- 'roll' now rolls in the reverse direction, e.g. `3 -1 roll` now rolls to the left
7+
- Added the 'nip' and 'over' builtin operators
8+
- Added the 'f-readline' operator to the 'io' internal library
9+
310
## 0.36.1
411

512
- 'slice' causes a fatal crash when slicing strings

examples/fib.pg

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,3 @@
1-
% 'over', a common stack language operation,
2-
% isn't in Page because 'roll' implements part of its functionality
3-
/over {
4-
% A B
5-
exch dup % B A A
6-
3 -1 roll % A A B
7-
exch % A B A
8-
} def
9-
101
/fib {
112
1 dict begin % Create a new dictionary with one initial slot
123
/i exch def % Set 'i' to the amount of numbers given

examples/range.pg

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
/2dup {dup dup} def
1+
/dup2 {dup dup} def
22

33
% 4 9 range -> [4 5 6 7 8 9]
44
/range {
5-
3 dict begin
5+
2 dict begin
66
/rend exch def
77
/rstart exch def
88

99
[ rstart 1 sub
10-
{ 1 add 2dup
10+
{ 1 add dup2
1111

1212
rend eq
1313
{pop exit}

page.nimble

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Package
22

3-
version = "0.36.1"
3+
version = "0.37.0"
44
author = "Nuclear Pasta"
55
description = "A PostScript-like language."
66
license = "Apache-2.0"

src/builtinlibs/libio.nim

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -121,14 +121,36 @@ Reads a byte from a file and returns it as an integer.
121121

122122
let f = cast[File](fobj.dat)
123123

124-
var b: byte
124+
var b: char
125125
try:
126-
b = f.readChar().byte
127-
except IoError as e:
126+
b = f.readChar()
127+
except IOError as e:
128128
raise newPgError(e.msg)
129129

130130
s.push(newInteger(b.int))
131131

132+
addF("f-readline",
133+
"""
134+
'f-readline'
135+
FILE -> str
136+
Reads everything until a newline.
137+
LF and CRLF are both valid.
138+
The newline is not a part of the returned string.
139+
""", @[("FILE", tExtitem)]):
140+
let fobj = s.pop()
141+
142+
let f = cast[File](fobj.dat)
143+
144+
fobj.checkPgFile()
145+
146+
var content: string
147+
try:
148+
content = f.readLine()
149+
except IOError as e:
150+
raise newPgError(e.msg)
151+
152+
s.push(newString(content))
153+
132154
addF("f-readall",
133155
"""
134156
'f-readall'
@@ -144,7 +166,7 @@ Reads everything from a file object and returns the contents as a string.
144166
var content: string
145167
try:
146168
content = f.readAll()
147-
except IoError as e:
169+
except IOError as e:
148170
raise newPgError(e.msg)
149171

150172
s.push(newString(content))
@@ -166,5 +188,5 @@ Writes a string S to a file object and returns the amount written.
166188
try:
167189
let b = f.writeBuffer(str[0].addr, str.len)
168190
s.push(newInteger(b))
169-
except IoError as e:
191+
except IOError as e:
170192
raise newPgError(e.msg)

src/builtinlibs/libos.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ Returns the path to the current file.
7070
addF("argv",
7171
"""
7272
'argv'
73-
-> list<str>
73+
-> list(str)
7474
Returns the program arguments.
7575
""", @[]):
7676
s.push(newList(s.g.args.map(newString)))

src/builtinlibs/libstrings.nim

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ template addS(name, doc: string, args: ProcArgs, body: string) =
2323
addF("chars",
2424
"""
2525
'chars'
26-
S -> list<str>
26+
S -> list(str)
2727
Separates a string S into a list L of character strings.
2828
""", @[("S", tString)]):
2929
let str = s.pop().strv
@@ -38,7 +38,7 @@ Separates a string S into a list L of character strings.
3838
addF("split",
3939
"""
4040
'split'
41-
S D -> list<str>
41+
S D -> list(str)
4242
Separates a string S into a list L of parts by a delimiter D.
4343
""", @[("S", tString), ("D", tString)]):
4444
let

src/builtins.nim

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -382,9 +382,9 @@ Returns true if the stack has at least two items on it, false otherwise.
382382
addF("pop",
383383
"""
384384
'pop'
385-
V ->
386-
Discards a value V.
387-
""", @[("V", tAny)]):
385+
X ->
386+
Discards a value X.
387+
""", @[("X", tAny)]):
388388
discard s.pop()
389389

390390
addF("dup",
@@ -414,15 +414,15 @@ Positive R rotates to the right, negative R rotates to the left.
414414
var expe = newProcArgs(count)
415415

416416
for i in 0..<expe.len():
417-
expe[i] = ("I" & $(i + 1), tAny)
417+
expe[i] = ("V" & $(i + 1), tAny)
418418

419419
s.check(expe)
420420

421421
let st = s.stack()
422422

423423
var sl = st[st.len() - count .. ^1]
424424

425-
sl.rotateLeft(-roll)
425+
sl.rotateLeft(roll)
426426

427427
var j = 0
428428

@@ -441,19 +441,34 @@ Exchanges the positions of values X and Y.
441441
addS("rot",
442442
"""
443443
'rot'
444-
X Y Z -> Y Z X
445-
Rotates the top three values on the stack to the left.
444+
X Y Z -> Z X Y
445+
Rotates the top three values on the stack to the right.
446446
""", @[("X", tAny), ("Y", tAny), ("Z", tAny)]):
447447
"3 1 roll"
448448

449449
addS("-rot",
450450
"""
451451
'-rot'
452-
X Y Z -> Z X Y
453-
Rotates the top three values on the stack to the right.
452+
X Y Z -> Y Z X
453+
Rotates the top three values on the stack to the left.
454454
""", @[("X", tAny), ("Y", tAny), ("Z", tAny)]):
455455
"3 -1 roll"
456456

457+
addS("nip",
458+
"""
459+
'nip'
460+
X Y -> Y
461+
Discards the second-from-top value on the stack.
462+
""", @[("X", tAny), ("Y", tAny)]):
463+
"exch pop"
464+
465+
addS("over",
466+
"""
467+
'over'
468+
X Y -> X Y X
469+
Discards the second-from-top value to the top of the stack.
470+
""", @[("X", tAny), ("Y", tAny)]):
471+
"exch dup rot"
457472

458473
# Arithmetic operators
459474

@@ -1243,7 +1258,7 @@ end"""
12431258
addF("symbols",
12441259
"""
12451260
'symbols'
1246-
-> list<symbol>
1261+
-> list(symbol)
12471262
Returns a list of the symbols inside the last opened dictionary.
12481263
""", @[]):
12491264
let symbols = s.symbols
@@ -1257,7 +1272,7 @@ Returns a list of the symbols inside the last opened dictionary.
12571272
addF("rsymbols",
12581273
"""
12591274
'rsymbols'
1260-
-> list<list<symbol>>
1275+
-> list(list(symbol))
12611276
Returns a list of lists of the symbols in each dictionary.
12621277
""", @[]):
12631278
let dicts = s.dicts

src/lexer.nim

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ type
2424
ttBracketClose,
2525
ttBraceOpen,
2626
ttBraceClose,
27-
ttDot
27+
ttDot,
28+
ttComma
2829

2930
Token* = object
3031
typ: TokenType
@@ -50,6 +51,8 @@ func toTokenType(ch: char, tt: var TokenType): bool =
5051
tt = ttBraceClose
5152
of '.':
5253
tt = ttDot
54+
of ',':
55+
tt = ttComma
5356
else:
5457
return false
5558

@@ -80,6 +83,8 @@ func name*(typ: TokenType): string =
8083
"'}'"
8184
of ttDot:
8285
"'.'"
86+
of ttComma:
87+
"','"
8388

8489

8590
func initToken*(typ: TokenType, file, lit: string, col, ln: int): Token =

src/parser.nim

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ type
2626
anchor*: Token
2727
nodes*: seq[Node]
2828
of nDot:
29+
dot*: Token
2930
left*, right*: Node
3031

3132
Parser* = ref object
@@ -63,7 +64,10 @@ func trace*(self: Node): string =
6364
of nList, nProc:
6465
self.anchor.trace()
6566
of nDot:
66-
self.left.trace()
67+
if self.left == nil:
68+
self.dot.trace()
69+
else:
70+
self.left.trace()
6771

6872
func copy*(self: Node): Node =
6973
case self.typ
@@ -93,7 +97,9 @@ proc `$`*(self: Node): string =
9397
of nList, nProc:
9498
result &= $self.nodes
9599
of nDot:
96-
result &= $self.left
100+
if self.left != nil:
101+
result &= $self.left
102+
97103
result &= "."
98104
result &= $self.right
99105

@@ -124,6 +130,13 @@ proc eat(self: Parser, tt: TokenType): Token =
124130

125131
inc self.idx
126132

133+
proc parseDot(self: Parser, start: Node): Node =
134+
result = start
135+
136+
while self.isType(ttDot):
137+
result = Node(typ: nDot, dot: self.eat(ttDot), left: result)
138+
result.right = Node(typ: nWord, tok: self.eat(ttWord))
139+
127140
proc parseInner(self: Parser, startTok: ptr Token, endType: TokenType): seq[Node] =
128141
while self.idx < self.toks.len:
129142
let tok = self.toks[self.idx]
@@ -134,16 +147,13 @@ proc parseInner(self: Parser, startTok: ptr Token, endType: TokenType): seq[Node
134147
inc self.idx
135148

136149
if self.isType(ttDot):
137-
var le = n
138-
139-
while self.isType(ttDot):
140-
inc self.idx
141-
le = Node(typ: nDot, left: le)
142-
le.right = Node(typ: nWord, tok: self.eat(ttWord))
143-
144-
result.add(le)
150+
result.add(self.parseDot(n))
145151
else:
146152
result.add(n)
153+
of ttComma:
154+
let n = Node(typ: nDot, dot: self.eat(ttComma), left: nil)
155+
n.right = Node(typ: nWord, tok: self.eat(ttWord))
156+
result.add(self.parseDot(n))
147157
of ttSymbol:
148158
result.add(Node(typ: nSymbol, tok: tok))
149159
inc self.idx

0 commit comments

Comments
 (0)