Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
272 additions
and
140 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,23 +1,39 @@ | ||
# A basic implementation of tee | ||
module tee | ||
|
||
get sys | ||
get file | ||
|
||
fn main() | ||
if len(sys.args) == 2 | ||
newline := "\n" | ||
f := open(sys.args[1], "w") | ||
state := f.state | ||
match state | ||
is file.Open | ||
for line in readlines() | ||
print(line) | ||
write(f, line) | ||
write(f, newline) | ||
close(f) | ||
else | ||
print("Failed to open file " + sys.args[1]) | ||
sys.exit(-1) | ||
else | ||
for line in readlines() | ||
print(line) | ||
get argparse {parse, Parser, Some, Option} | ||
|
||
fn main() int { | ||
var options [str: Option] | ||
options["-a"] = Option("append", false /*has_arg*/, false) | ||
parser := Parser("tee", options, Some(0, 1)) | ||
|
||
with args := parse(parser, sys.args[1:len(sys.args)]) { | ||
newline := "\n" | ||
if len(args.positionals) != 0 { | ||
# There was a filename given, so check whether we need to append or create. | ||
with f := open(args.positionals[0], "-a" in args.options ? "a" : "w") { | ||
# Now pipe to both the file and stdout. | ||
for line in readlines() { | ||
print(line) | ||
write(f, line) | ||
write(f, newline) | ||
} | ||
} else { | ||
print("Failed to open file " + sys.args[1]) | ||
return 1 | ||
} | ||
} else { | ||
# There was no filename given, so just pipe it through | ||
for line in readlines() { | ||
print(line) | ||
} | ||
} | ||
} else parse_error { | ||
print("Command-line parse failed: " + parse_error.reason) | ||
print(parse_error.usage()) | ||
} | ||
return 0 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
# An implementation of Conway's Game of Life. | ||
# Stolen shamelessly from https://golang.org/ in order to | ||
# see how hard it would be to port to Zion. | ||
module conway | ||
|
||
# Field represents a two-dimensional field of cells. | ||
type Field has { | ||
s [[bool]] | ||
w int | ||
h int | ||
} | ||
|
||
# NewField returns an empty field of the specified width and height. | ||
fn NewField(w int, h int) Field { | ||
# TODO: make array allocation better. It was painful | ||
# to have to remove Go's `make` construct, and to | ||
# manually initialize this 2-d array. | ||
let s [[bool]] | ||
reserve(s, h) | ||
for y in range(h) { | ||
let row [bool] | ||
reserve(row, w) | ||
for x in range(w) { | ||
append(row, false) | ||
} | ||
append(s, row) | ||
} | ||
return Field(s, w, h) | ||
} | ||
|
||
# Set sets the state of the specified cell to the given value. | ||
fn Set(f Field, x int, y int, b bool) { | ||
f.s[y][x] = b | ||
} | ||
|
||
# Alive reports whether the specified cell is alive. | ||
# If the x or y coordinates are outside the field boundaries they are wrapped | ||
# toroidally. For instance, an x value of -1 is treated as width-1. | ||
fn Alive(f Field, x int, y int) bool { | ||
x += f.w | ||
# TODO: implement mod_assignment_t::render | ||
x = x % f.w | ||
y += f.h | ||
y = y % f.h | ||
return f.s[y][x] | ||
} | ||
|
||
# Next returns the state of the specified cell at the next time step. | ||
fn Next(f Field, x int, y int) bool { | ||
# Count the adjacent cells that are alive. | ||
var alive = 0 | ||
for i in range(-1, 2) { | ||
for j in range(-1, 2) { | ||
if (j != 0 or i != 0) and Alive(f, x+i, y+j) { | ||
alive += 1 | ||
} | ||
} | ||
} | ||
# Return next state according to the game rules: | ||
# exactly 3 neighbors: on, | ||
# exactly 2 neighbors: maintain current state, | ||
# otherwise: off. | ||
return alive == 3 or alive == 2 and Alive(f, x, y) | ||
} | ||
|
||
# Life stores the state of a round of Conway's Game of Life. | ||
type Life has { | ||
var a Field | ||
var b Field | ||
w int | ||
h int | ||
} | ||
|
||
# NewLife returns a new Life game state with a random initial state. | ||
fn NewLife(w int, h int) Life { | ||
a := NewField(w, h) | ||
for i in range(w * h / 4) { | ||
Set(a, rand(w), rand(h), true) | ||
} | ||
return Life(a, NewField(w, h), w, h) | ||
} | ||
|
||
# Step advances the game by one instant, recomputing and updating all cells. | ||
fn Step(l Life) { | ||
# Update the state of the next field (b) from the current field (a). | ||
for y in range(l.h) { | ||
for x in range(l.w) { | ||
Set(l.b, x, y, Next(l.a, x, y)) | ||
} | ||
} | ||
# Swap fields a and b. | ||
c := l.a | ||
l.a = l.b | ||
l.b = c | ||
} | ||
|
||
# String returns the game board as a str. | ||
[global] | ||
fn str(l Life) str { | ||
# TODO: make a better string builder type thing | ||
var buf str | ||
for y in range(l.h) { | ||
for x in range(l.w) { | ||
if Alive(l.a, x, y) { | ||
buf += "*" | ||
} else { | ||
buf += " " | ||
} | ||
} | ||
buf += "\n" | ||
} | ||
return buf | ||
} | ||
|
||
fn main() { | ||
l := NewLife(40, 15) | ||
for i in range(300) { | ||
Step(l) | ||
print("\x0c") | ||
posix.fflush(stdout) | ||
print(l) | ||
posix.sleep(1) | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
module fib_closure | ||
|
||
type Ref T has { | ||
var val T | ||
} | ||
|
||
# fib returns a function that returns | ||
# successive Fibonacci numbers. | ||
fn fib() fn() int { | ||
# Consider that in the Golang version of this, it's much more succinct, however that is because | ||
# Go's closure's capture by reference. This may require some consideration as to whether it is | ||
# permissible to allow capture by reference in Zion. Given that it can be simulated by creating | ||
# a user-defined reference type as follows, I'm not certain it's worth introducing more implicit | ||
# impurity. | ||
a := Ref(0) | ||
b := Ref(1) | ||
return fn() int { | ||
return match (b.val, a.val + b.val) { | ||
(next_a, next_b) { | ||
a.val = next_a | ||
b.val = next_b | ||
a.val | ||
} | ||
} | ||
} | ||
} | ||
|
||
fn main() { | ||
f := fib() | ||
# Function calls are evaluated left-to-right. | ||
print([f(), f(), f(), f(), f()]) | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.