Skip to content

Commit

Permalink
Merge pull request #4 from acook/wv_rework
Browse files Browse the repository at this point in the history
Square bracket syntax and arbitrary nesting for WV literals
  • Loading branch information
acook committed Nov 9, 2015
2 parents 4d9da60 + 41e6543 commit 2ea5d45
Show file tree
Hide file tree
Showing 15 changed files with 80 additions and 66 deletions.
2 changes: 1 addition & 1 deletion examples/basic_objects.bl
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ o-new
:num print

;; create a WV slot
. 'omg hai' print . greet:
[ 'omg hai' print ] greet:
;; call a WV slot
:greet

Expand Down
4 changes: 2 additions & 2 deletions examples/catting_a_vector.bl
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
''
('a' 'b' 'c' 'd')

. 0 ato swap 0 rmo rot rot cat swap .
. len 0 eq swap drop .
[ 0 ato swap 0 rmo rot rot cat swap ]
[ len 0 eq swap drop ]
until

drop
Expand Down
8 changes: 4 additions & 4 deletions examples/fd-read.bl
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
;; NOTE -> this will block and wait on input!

newq 0 read swap newq ;; Q for read-queue, hide FD, Q for work-queue
.
[
'' swap ;; create empty CV and bring recv Q back to top
.. rot swap app swap .. ;; bring Cv to top, then item, append item, bring Q to top
.. deq dup not .. ;; deq item, dup it, and make it boolean
[ rot swap app swap ] ;; bring Cv to top, then item, append item, bring Q to top
[ deq dup not ] ;; deq item, dup it, and make it boolean
until ;; iterate over read-queue until we get to a nil
drop drop ;; drop the EOF nil and read-queue
enq ;; send CV over the other Q to the main thread
. work ;; use work thread for read loop
] work ;; use work thread for read loop
deq print ;; deq will block waiting for a response
10 changes: 5 additions & 5 deletions examples/logic.bl
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
1
. 'not zero!' print .
. 0 eq not .
[ 'not zero!' print ]
[ 0 eq not ]
if

(1 2)
. 'empty' .
. 'not empty!' .
. len 0 eq swap drop .
[ 'empty' ]
[ 'not empty!' ]
[ len 0 eq swap drop ]
either print
6 changes: 3 additions & 3 deletions examples/loops.bl
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
5 4 3 2 1 ;; some stuff we're going to reverse

s-new
. swap push . ;; take whatever is in he @stack and put it into our user-stack
.
[ swap push ] ;; take whatever is in he @stack and put it into our user-stack
[
depth 1 eq ;; compare the @stack depth with 1
swap drop ;; clean up our lingering number
. until
] until

$ swap push ;; promote our user-stack onto the $stack
;; this means the user-stack becomes our new @stack
Expand Down
2 changes: 1 addition & 1 deletion examples/object-child.bl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ o-new ;; This will be the parent object
child ;; And this creates a child object that checks the parent

swap ;; let's add some slots to the parent
. self print . inspect: ;; this lets us check out what object we have
[ self print ] inspect: ;; this lets us check out what object we have

swap ;; bring the child back to the top
:inspect ;; call the inspect slot on the child
Expand Down
4 changes: 2 additions & 2 deletions examples/object-self.bl
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
o-new

;; we can use self much like @ inside of slots to refer to the current object
. self print . inspect:
[ self print ] inspect:
:inspect

;; self also allows you to easily use other slots on the same object
. 1 2 3 4 5 'I am an object: ' print self :inspect . pp:
[ 1 2 3 4 5 'I am an object: ' print self :inspect ] pp:
:pp
2 changes: 1 addition & 1 deletion examples/print_types.bl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ s-new 1 push 2 push 3 push 4 push print '' print
~1 print

'word vectors' print
. 1 2 3 4 . print '' print
[ 1 2 3 4 ] print '' print

'char vectors' print
'1 2 3 4' print '' print
Expand Down
2 changes: 1 addition & 1 deletion examples/queues.bl
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ newq 1 enq
newq 2 enq
swap deq print drop
3 enq 4 enq
. print . proq
[ print ] proq
14 changes: 7 additions & 7 deletions examples/talking_to_threads.bl
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
newq newq ;; create send and receive queues
.
..
[
[
deq ;; will block if the queue is empty
n-to-cv rot swap enq ;; convert number into a cv (string) and send back
n-to-cv rot swap enq ;; convert number into a cv (string) and send back
swap ;; reorder queues so we can loop without confusion
.. loop ;; using loop since it goes forever
. work ;; start new thread and swap the queues
] loop ;; using loop since it goes forever
] work ;; start new thread and swap the queues

swap ;; bring send queue to top
1 enq 2 enq 3 enq 4 enq ;; send some numbers to be converted

0
. 1 add .
. 1000 eq .
[ 1 add ]
[ 1000 eq ]
until drop ;; give the main thread busywork

swap q-to-v ;; get contents of receive Q as V
Expand Down
8 changes: 4 additions & 4 deletions examples/working_with_threads.bl
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
'examples/_file_to_run_with_co.bl' co

newq 1 enq 2 enq 3 enq ;; make a Q of work
.
..
[
[
print ;; print items in Q
.. proq ;; interate over items in Q until empty
. bkg ;; run this WV in the background taking the top item with it
] proq ;; interate over items in Q until empty
] bkg ;; run this WV in the background taking the top item with it

;; now lets communicate with the thread run by co
'bar' enq
Expand Down
18 changes: 9 additions & 9 deletions examples/wv-call.bl
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
;; basic demonstration of nested calls
.
..
[
[
0
.. call
. call
] call
] call
print

;; Smalltalk-style Conditionals

o-new ;; o1 will house our truthy and falsey objects

o-new ;; o2 (truthy object)
. swap call . ;; evaluate the wv
[ swap call ] ;; evaluate the wv
if-true: ;; store function in slot
. swap drop . ;; do nothing except get rid of the wv
[ swap drop ] ;; do nothing except get rid of the wv
if-false: ;; store function in slot
true: ;; store o2 in slot in o1

o-new ;; o3 (falsy object)
. swap drop . ;; do nothing except get rid of the wv
[ swap drop ] ;; do nothing except get rid of the wv
if-true: ;; store function in slot
. swap call . ;; evaluate the wv
[ swap call ] ;; evaluate the wv
if-false: ;; store function in slot
false: ;; store o3 in slot in o1

:false ;; summon reference to falsey o3
. 'I am so false.' print . ;; a WV to demonstrate the condition
[ 'I am so false.' print ] ;; a WV to demonstrate the condition
swap :if-false ;; call if-false on o3, will display "I am so false."
41 changes: 15 additions & 26 deletions src/github.com/acook/blacklight/lexer.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package main

import ()
import (
"fmt"
)

var keywords = []string{
"<>", "decap", "depth", "drop", "dup", "over", "rot", "swap", "purge",
Expand All @@ -27,8 +29,9 @@ var metaops = []string{

func lex(tokens []string) []operation {
var op operation
var ops, real_ops, wv_ops []operation
var inside_vector, inside_word_vector, inside_nested_word_vector bool
var ops, real_ops []operation
var inside_vector bool
var wv_stack ops_fifo

for _, t := range tokens {
switch {
Expand Down Expand Up @@ -58,31 +61,17 @@ func lex(tokens []string) []operation {
} else {
panic("unmatched closing paren")
}
case t == ".": // WordVector literal (start/end)
if inside_word_vector {
inside_word_vector = false

pwv := newPushWordVector(t)
pwv.Contents = append(pwv.Contents, ops...)
ops = append(real_ops, pwv)
} else {
inside_word_vector = true

real_ops = ops
ops = []operation{}
}
case t == "..": // nested WordVector literal (start/end)
if inside_nested_word_vector {
inside_nested_word_vector = false

pwv := newPushWordVector(t)
case t == "[": // WordVector literal (start)
wv_stack.push(ops)
ops = []operation{}
case t == "]": // WordVector literal (end)
if wv_stack.depth() > 0 {
pwv := newPushWordVector("[" + fmt.Sprint(wv_stack.depth()+1) + "]")
wv_ops := wv_stack.pop()
pwv.Contents = append(pwv.Contents, ops...)
ops = append(wv_ops, pwv)
} else {
inside_nested_word_vector = true

wv_ops = ops
ops = []operation{}
panic("lexer: closing bracket without opening bracket")
}
case isWord(t):
op = newPushWord(t)
Expand All @@ -103,7 +92,7 @@ func lex(tokens []string) []operation {
}

switch {
case inside_word_vector:
case wv_stack.depth() > 0:
panic("unclosed WordVector literal")
case inside_vector:
panic("unclosed Vector literal")
Expand Down
19 changes: 19 additions & 0 deletions src/github.com/acook/blacklight/ops_fifo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package main

type ops_fifo struct {
items [][]operation
}

func (f *ops_fifo) push(ops []operation) {
f.items = append(f.items, ops)
}

func (f *ops_fifo) pop() []operation {
ops := f.items[f.depth()-1]
f.items = f.items[:f.depth()-1]
return ops
}

func (f *ops_fifo) depth() int {
return len(f.items)
}
6 changes: 6 additions & 0 deletions src/github.com/acook/blacklight/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ func parse(code string) []string {
case glyph == ")":
tokens = append(tokens, glyph)
tokens = ws(glyph, tokens)
case glyph == "[":
tokens = append(tokens, glyph)
tokens = ws(glyph, tokens)
case glyph == "]":
tokens = append(tokens, glyph)
tokens = ws(glyph, tokens)
case unicode.IsSpace(b):
tokens = ws(glyph, tokens)
case isComment(glyph, tokens):
Expand Down

0 comments on commit 2ea5d45

Please sign in to comment.