Skip to content

Commit

Permalink
Merge pull request #63 from skx/61-stdlib
Browse files Browse the repository at this point in the history
61 stdlib
  • Loading branch information
skx authored Oct 21, 2022
2 parents ebadf37 + 1feefa0 commit 76140cd
Show file tree
Hide file tree
Showing 17 changed files with 701 additions and 580 deletions.
7 changes: 3 additions & 4 deletions PRIMITIVES.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,10 +188,9 @@ Things you'll find here include:

The standard library consists of routines, and helpers, which are written in 100% yal itself.

The implementation of these primitives can be found in the following two files:
The implementation of these primitives can be found in the following directory:

* [stdlib/stdlib.lisp](stdlib/stdlib.lisp)
* [stdlib/mal.lisp](stdlib/mal.lisp)
* [stdlib/stdlib/](stdlib/stdlib/)

The code in those files is essentially **prepended** to any script that is supplied upon the command-line.

Expand Down Expand Up @@ -282,7 +281,7 @@ Functions here include:
* `map`
* Return the results of applying the specified function to every element of the given list.
* `map-pairs`
* Return the results of applying the specified function to every pair of elements in the given list.
* Return the results of applying the specified function to every pair of elements in the given list.
* `max`
* Return the maximum value in the specified list.
* `min`
Expand Down
38 changes: 34 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

* [yet another lisp](#yet-another-lisp)
* [Building / Installing](#building--installing)
* [Standard Library](#standard-library)
* [Usage](#usage)
* [Examples](#examples)
* [Fuzz Testing](#fuzz-testing)
Expand Down Expand Up @@ -70,6 +71,36 @@ v0.11.0 f21d032e812ee6eadad5eac23f079a11f5e1041a
```



## Standard Library

When user-code is executed, whether a simple statement supplied via the command-line, or read from a file, a standard-library is loaded from beneath the directory:

* [stdlib/stdlib/](stdlib/stdlib/)


Our standard-library consists of primitive functions such as `(map..)`, `(min..)` and similar, is written in 100% yal-lisp.

The standard library may be entirely excluded via the use of the environmental varilable `YAL_STDLIB_EXCLUDE_ALL`:

```
$ yal -e "(print (hms))"
22:30:57
$ YAL_STDLIB_EXCLUDE_ALL=true yal -e "(print (hms))"
Error running: error expanding argument [hms] for call to (print ..):
ERROR{argument 'hms' not a function}
```

If you prefer you may exclude specific _parts_ of the standard library, by specify the filenames you wish to exclude separated by commas:

```
$ YAL_STDLIB_ECLUDE=date,type-checks yal -e "(print (hms))"
22:30:57
```



## Examples

A reasonable amount of sample code can be found in the various included examples:
Expand All @@ -79,12 +110,11 @@ A reasonable amount of sample code can be found in the various included examples
* [fizzbuzz.lisp](fizzbuzz.lisp) is a standalone sample of solving the fizzbuzz problem.
* [mtest.lisp](mtest.lisp) shows some macro examples.

As noted there is a standard-library of functions which are loaded along with any user-supplied script. These functions are implemented in lisp and also serve as a demonstration of syntax and features:
As noted there is a standard-library of functions which are loaded along with any user-supplied script - that library of functions may also provide a useful reference and example of yal-code:

* [stdlib/stdlib.lisp](stdlib/stdlib.lisp)
* [stdlib/mal.lisp](stdlib/mal.lisp)
* [stdlib/stdlib/](stdlib/stdlib/)

Running these example will produce output, for example:
Running any of our supplied examples should produce useful output for reference. For example here's the result of running the `fibonacci.lisp` file:

```lisp
$ yal fibonacci.lisp
Expand Down
73 changes: 64 additions & 9 deletions stdlib/stdlib.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,74 @@
// Package stdlib contains a simple/small standard-library, which
// is written in lisp itself.
// Package stdlib contains a simple/small standard-library, which is written in lisp itself.
//
// By default our standard library is loaded prior to the execution of any user-supplied
// code, however parts of it can be selectively ignored, or the whole thing.
//
// If the environmental varialbe "YAL_STDLIB_EXCLUDE_ALL" contains non-empty content then
// all of our standard-library is disabled.
//
// Otherwise if YAL_STDLIB_EXCLUDE is set to a non-empty string it will be assumed to be
// a comma-separated list of filename substrings to exclude.
package stdlib

import (
_ "embed" // embedded-resource magic
"embed" // embedded-resource magic
"fmt"
"os"
"path/filepath"
"strings"
)

//go:embed stdlib.lisp
var stdlib string

//go:embed mal.lisp
var mal string
//go:embed stdlib/*.lisp
var stdlib embed.FS

// Contents returns the embedded contents of our Lisp standard-library.
//
// We embed "*.lisp" when we build our binary
func Contents() []byte {

return []byte(stdlib + "\n" + mal + "\n")
// Result
result := []byte{}

// We can allow disabling the stdlib.
if os.Getenv("YAL_STDLIB_EXCLUDE_ALL") != "" {
return result
}

// We might exclude only one/two files
exclude := []string{}
if os.Getenv("YAL_STDLIB_EXCLUDE") != "" {
exclude = strings.Split(os.Getenv("YAL_STDLIB_EXCLUDE"), ",")
}

// Read the list of entries - can't fail
entries, _ := stdlib.ReadDir("stdlib")

// For each entry
for _, entry := range entries {

// Get the filename
fp := filepath.Join("stdlib", entry.Name())

// Does this match an excluded value?
skip := false

for _, tmp := range exclude {
if strings.Contains(fp, tmp) {
skip = true
}
}

if skip {
fmt.Printf("Skipping %s\n", fp)
continue
}

// Read the content - can't fail
data, _ := stdlib.ReadFile(fp)

// Append to our result
result = append(result, data...)
}

return result
}
Loading

0 comments on commit 76140cd

Please sign in to comment.