Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

61 stdlib #63

Merged
merged 8 commits into from
Oct 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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