Skip to content

Instantly share code, notes, and snippets.

@cryptorick
Created September 2, 2018 01:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cryptorick/ee5d2f50dd61bef9edcf8f775d73d07f to your computer and use it in GitHub Desktop.
Save cryptorick/ee5d2f50dd61bef9edcf8f775d73d07f to your computer and use it in GitHub Desktop.
Print a tree of include filenames in depth-first order and indented
#!/usr/bin/env oh
#--------------------------------------------------------------------------
# Utilities
define defun: syntax (name args: body) e = {
e::eval: list define $name : list method (list @$args) = @$body
}
define fn: syntax (args: body) e = {
# Example: `fn (x): add 42 x` is a method (function object) that
# you can pass around
e::eval: list method (list @$args) = @$body
}
defun I (x) : return $x # The identity function.
define mapl: syntax (f) e = {
e::eval: list while (list define ln (list readline)) (list $f (quote $ln))
}
define maplp: syntax (f) e = {
e::eval: list while (list define ln (list readline)) (list echo (list $f (quote $ln)))
}
defun string-last (s) {
s::slice : sub (s::length) 1
}
defun string-but-last (s) {
s::slice 0 : sub (s::length) 1
}
defun strip-CR (s) {
if (eq "\r" : string-last $s) {
string-but-last $s
} else {
return $s
}
}
defun nth-word (n s) {
(" "::split $s)::get $n
}
defun member (x xs) {
if (or (is-null $xs) (eq $x : xs::head)) {
return $xs
} else {
member $x : xs::tail
}
}
defun member? (:args) : boolean : member @$args
defun file-readable? (File): boolean: test -r $File
#--------------------------------------------------------------------------
# Application
define things-seen: method () =: object {
define what-seen: list
export show: method self () = {
echo $self::what-seen
}
export seen-this?: method self (this) = {
member? $this $self::what-seen
}
export see-this: method self (this) = {
if (not: seen-this? $this) {
set $self::what-seen: cons $this $self::what-seen
}
return $this
}
}
defun indent-by (n s) {
if (gt $n 0) {
return: ("%%%ss$s"::sprintf $n)::sprintf " "
} else: return $s
}
defun print-includes (File) {
grep -E '^[ \t]*include(_once)* ' $File |
maplp strip-CR |
maplp: fn (ln): nth-word 1 $ln
}
defun print-tree (File) {
define Indent 4
define seen: things-seen
defun loop (File Depth) {
define outstr: indent-by (mul $Indent $Depth) $File
if (not: file-readable? $File) {
echo $outstr "(FILE NOT FOUND!)"
} else: if (seen::seen-this? $File) {
echo $outstr "(ALREADY SAW THIS EARLIER; Skipping ...)"
} else {
echo $outstr
echo $File |
maplp seen::see-this |
mapl print-includes |
mapl: fn (Dep): loop $Dep (add 1 $Depth)
}
}
loop $File 0
}
print-tree @$_args_
@cryptorick
Copy link
Author

What a super-fun programming/scripting language! (I'm sure I'm not doing some things correctly, but I learned a lot.)

@cryptorick
Copy link
Author

Here are the function versions of mapl and maplp:

defun mapl (f): while (define ln: readline): $f $ln
defun maplp (f): while (define ln: readline): echo: $f $ln

They're less noisy than their syntax counter parts, but I was getting a subtle error using them in the function print-tree at the expression maplp seen::see-this (and of course, when you replace maplp with the function/method version, the call has to be changed to maplp $seen::see-this). Here's the error I would get.

$ print-include-tree.oh foo.src
foo.src
print-include-tree.oh: 72: error/runtime: 'what-seen' undefined

It's really wigged out: it's lost track of its own slot in the object. idk.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment