goal

package module
v0.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 16, 2023 License: ISC Imports: 14 Imported by: 2

README

Goal

pkg.go.dev godocs.io

Goal is an embeddable array programming language with a bytecode interpreter, written in Go. It provides both a command line intepreter (that can be used in the REPL), and a library interface. Though the language is still young, its core features are mostly there and tested, so it is usable both for writing useful short scripts and playing with the REPL. The library interface might still experiment some changes.

Like in most array programming languages, Goal's builtins vectorize operations on immutable arrays, and encourage a functional style for control and data transformations, supported by a simple dynamic type system with little abstraction, and mutable variables (but no mutable values).

It's main distinctive features are as follows:

  • Syntax inspired mainly from the K language, but with quite a few deviations. For example, backquotes produce Go-like raw strings instead of symbols, rx/[a-z]/ is a regular expression literal (checked and processed at compile-time), and there are no tacit compositions, and digraph operator verbs and adverbs are gone or done differently (except for global assignment with ::).
  • Primitive semantics are both inspired from the ngn/k variant of the K language and BQN. For example, group, classify, shifts, windows, find (index of) and occurrence count take after BQN's semantics. Multi-dimensional versions, when present in BQN, have been left out, though, as Goal has only free-form immutable arrays, like K. Some primitives use words instead of symbols (like ocount for occurrence count). Also, K-like dictionnaries are supported, but not tables.
  • Unlike in typical array languages, strings are atoms, and common string handling functions (like index, substr or trim) have been integrated into the primitives, including regular expression functions.
  • Error handling makes a distinction between fatal errors (panics) and recoverable errors which are handled as values.
  • Easily embeddable and extensible in Go, meaning easy access to the standard library.
  • Integrated support for csv and time handling.
  • Array performance is unsurprising and good enough most of the time, with basic (but good in code with limited branching) variable liveness analysis to reduce cloning by reusing dead immutable arrays, though it is not a goal to reach state-of-the-art (no SIMD, and there is still room for more special code and specialized algorithms). Scalar performance is typical for a bytecode-compiled interpreter (without JIT), somewhat slower than a C bytecode interpreter (value representation in Go is somewhat less compact than how it can be done in C).

If this list is not enough to satisfy your curiosity, there's also a Why.md text for you. You can also read the Credits.md to know about main inspiration sources for the language. Last, but not least, there are some implementation notes too.

Install

To install the command line interpreter, first do the following:

  • Install the go compiler.
  • Add $(go env GOPATH)/bin to your $PATH (for example export PATH="$PATH:$(go env GOPATH)/bin").

Then you can build the intepreter with:

go install ./cmd/goal

Alternatively, you may type go build -o /path/to/bin/goal ./cmd/goal to put the resulting binary in a custom location in your $PATH.

The goal command should now be available. Type goal --help for command-line usage.

Typing just goal opens the REPL. For a better experience using the REPL (to get typical keyboard shortcuts), you can install the readline wrapper rlwrap program (available as a package in most systems), and then use instead rlwrap goal.

Editor support

Examples

A few short examples can be found in the testdata/scripts directory. Because they're used for testing, they come along an expected result after a /RESULT: comment.

Also, various code generation scripts in the toplevel scripts directory are written in Goal.

Documentation

Currently, documentation consists of the REPL help system with usage summary and examples for all implemented features, so some prior knowledge of another array language, in particular K, can be useful. The full contents are replicated below.

TOPICS HELP
Type help TOPIC or h TOPIC where TOPIC is one of:

"syn"   syntax
"types" types
"+"     verbs (like +*-%,)
"nv"    named verbs (like in, sign)
"'"     adverbs ('/\)
"io"    io functions (slurp, say)
"time"  time functions

Notations:
        s (string) f (function) F (2-args function)
        n (number) i (integer) r (regexp) d (dict)
        x,y (any other)

SYNTAX HELP
numbers         1     1.5     0b0110     1.7e-3
strings         "text\xff\u00F\n"  "\""  "\u65e5"  (backquotes for raw strings)
operators       :  +  -  *  %  !  &  |  ^  #  _  $  ?  @  .  ::
regexps         rx/[a-z]/     (see https://pkg.go.dev/regexp/syntax for syntax)
arrays          1 2 -3 4      1 "ab" -2 "cd"      (1 2;"a";3 "b";(4 2;"c");*)
variables       a   b   f   data    (any word matching rx/[a-zA-Z][a-zA-Z0-9]*/)
assign          a:2 (local within lambda, global otherwise)    a::2 (global)    
op assign       a+:1 (sugar for a:a+1)       a+::2 (sugar for a::a+2)
list assign     (a;b;c):x   (where 2<#x)     (a;b):1 2;b -> 2
expressions     2*3+4 -> 14 (no priority)    1+|1 2 3 -> 4 3 2     +/1 2 3 -> 6
index           x[y] is sugar for x@y (apply); x[] ~ x[*] ~ x[!#x] ~ x (arrays)
index deep      x[y;z;...] is sugar for x.(y;z;...) (except for x in (?;and;or))
index assign    x[y]:z is sugar for x:@[x;y;:;z]    (or . for x[y;...]:z)
index op assign x[y]op:z is sugar for x:@[x;y;op;z] (for symbol operator)
lambdas         {x+y+z}[2;3;0] -> 5     {[a;b;c]a+b+c}[1;2;3] -> 6
projections     {x+y}[2;] 3 -> 5        (2+) 3 -> 5
cond            ?[1;2;3] -> 2     ?[0;2;3] -> 3    ?[0;2;"";3;4] -> 4
and/or          and[1;2] -> 2   and[1;0;3] -> 0   or[0;2] -> 2   or[0;0;0] -> 0
sequence        [a:2;b:a+3;a+10] -> 12 (bracket block [] at start of expression)
return          [1;:2;3] -> 2 (a : at start of expression)
try             'x is sugar for ?["e"~@x;:x;x] (return if it's an error)

TYPES HELP
atom    array   name            examples
n       N       number          0      1.5      !5      1.2 3 1.8
s       S       string          "abc"   "d"     "a" "b" "c"
r               regexp          rx/[a-z]/       rx/\s+/
d               dictionnary     "a" "b"!1 2
f               function        +      {x*2}   (1-)    %[;2]
e               error           error "msg"
        A       generic array   ("a" 1;"b" 2;"c" 3)     (+;-;*;"any")

VERBS HELP
:x  identity    :[42] -> 42 (recall that : is also syntax for return)
x:y right       2:3 -> 3
+x  flip        +(1 2;3 4) -> (1 3;2 4)
n+n add         2+3 -> 5            2+3 4 -> 5 6
s+s concat      "a"+"b" -> "ab"     "a" "b"+"c" -> "ac" "bc"
-x  negate      - 2 3 -> -2 -3      -(1 2.5;3 4) -> (-1 -2.5;-3 -4)
n-n subtract    5-3 -> 2            5 4-3 -> 2 1
s-s trim suffix "file.txt"-".txt" -> "file"
*x  first       *3 2 4 -> 3     *"ab" -> "ab"    *(+;*) -> +
n*n multiply    2*3 -> 6            1 2 3*3 -> 3 6 9
s*x repeat      "a"*3 2 1 0 -> "aaa" "aa" "a" ""
%x  classify    %1 2 3 1 2 3 -> 0 1 2 0 1 2     %"a" "b" "a" -> 0 1 0
x%y divide      3%2 -> 1.5          3 4%2 -> 2 1.5
!i  enum        !5 -> 0 1 2 3 4
!d  keys        !"a" "b"!1 2 -> "a" "b"
!x  odometer    !2 3 -> (0 0 0 1 1 1;0 1 2 0 1 2)
x!y dict        d:"a" "b"!1 2;d "a" -> 1
&x  where       &0 0 1 0 0 0 1 -> 2 6
x&y min         2&3 -> 2        4&3 -> 3
|x  reverse     |!5 -> 4 3 2 1 0
x|y max         2|3 -> 3        4|3 -> 4
<x  ascend      <2 4 3 -> 0 2 1 (index permutation for ascending order)
x<y less        2<3 -> 1        "c" < "a" -> 0
>x  descend     >2 4 3 -> 1 2 0 (index permutation for descending order)
x>y greater     2>3 -> 0        "c" > "a" -> 1
=x  group       =1 0 2 1 2 -> (,1;0 3;2 4)      =-1 2 -1 2 -> (!0;!0;1 3)
f=x group by    {1=2!x}=!10 -> (0 2 4 6 8;1 3 5 7 9)
x=y equal       2 3 4=3 -> 0 1 0        "ab" = "ba" -> 0
~x  not         ~0 1 2 -> 1 0 0         ~"a" "" "0" -> 0 1 0
x~y match       3~3 -> 1        2 3~3 2 -> 0       ("a";%)~("b";%) -> 0 1
,x  enlist      ,1 -> ,1 (list with one element)
x,y join        1,2 -> 1 2      "ab" "c","d" -> "ab" "c" "d"
^x  sort        ^3 5 0 -> 0 3 5       ^"ca" "ab" "bc" -> "ab" "bc" "ca"
i^s windows     2^"abcd" -> "ab" "bc" "cd"      (2-bytes strings)
i^y windows     2^!4 -> (0 1;1 2;2 3)
s^y trim        " []"^"  [text]  " -> "text"    "\n"^"\nline\n" -> "line"
x^y without     2 3^1 1 2 3 3 4 -> 1 1 4
#x  length      #2 4 5 -> 3       #"ab" "cd" -> 2
i#y take        2#4 1 5 -> 4 1    4#3 1 5 -> 3 1 5 3 (cyclic)    3#1 -> 1 1 1
s#y count       "ab"#"cabdab" "cd" "deab" -> 2 0 1
f#y replicate   {0 1 1 0}#4 1 5 3 -> 1 5    {x>0}#2 -3 1 -> 2 1
x#y keep only   2 3^1 1 2 3 3 4 -> 2 3 3
_N  floor       _2.3 -> 2           _1.5 3.7 -> 1 3
_S  to lower    _"ABC" -> "abc"     _"AB" "CD" -> "ab" "cd"
i_s drop bytes  2_"abcde" -> "cde"  -2_"abcde" -> "abc" 
i_x drop        2_3 4 5 6 -> 5 6    -2_3 4 5 6 -> 3 4
s_x trim prefix "pref-"_"pref-name" -> "name"
I_s cut string  1 3_"abcdef" -> "bc" "def"
I_y cut         2 5_!10 -> (2 3 4;5 6 7 8 9)
f_x weed out    {0 1 1 0}_4 1 5 3 -> 4 3    {x>0}_2 -3 1 -> ,-3
$x  string      $2 3 -> "2 3"     $"text" -> "\"text\""
i$x split       2$!6 -> (0 1;2 3;4 5)   2$"a" "b" "c" -> ("a" "b";,"c")
s$y cast        "i"$2.3 -> 2    "i"$"ab" -> 97 98   "s"$97 98 -> "ab"
s$y parse num   "n"$"1.5" -> 1.5
x$y binsearch   2 3 5 7$8 2 7 5 5.5 3 0 -> 4 1 4 3 3 2 0
?i  uniform     ?2 -> 0.6046602879796196 0.9405090880450124
?x  uniq        ?2 2 3 4 3 3 -> 2 3 4
i?y roll        5?100 -> 10 51 21 51 37
i?y deal        -5?100 -> 19 26 0 73 94 (always distinct)
s?r rindex      "abcde"?rx/b../ -> 1 4
s?s index       "a = a + 1"?"=" "+" -> 2 6
x?y find        3 2 1?2 -> 1    3 2 1?0 -> 3
@x  type        @2 -> "n"    @"ab" -> "s"    @2 3 -> "N"
s@y substr      "abcdef"@2  -> "cdef" (s[offset])
r@y match       rx/[a-z]/"abc" -> 1     rx/\s/"abc" -> 0
r@y find        rx/[a-z](.)/"abc" -> "ab" "b"
f@y apply       (|)@1 2 -> 2 1 (like |[1 2] -> 2 1 or |1 2)
x@y at          1 2 3@2 -> 3    1 2 3[2 0] -> 3 1
.s  reval       ."2+3" -> 5     a:1;."a" -> panic ".s : undefined global: a"
.e  get error   .error "msg" -> "msg"
.d  values      ."a" "b"!1 2 -> 1 2
s.y substr      "abcdef"[2;3] -> "cde" (s[offset;length])
r.y findN       rx/[a-z]/["abc";2] -> "a" "b" (stop at 2 matches; -1 for all)
x.y applyN      {x+y}.2 3 -> 5    {x+y}[2;3] -> 5    (1 2;3 4)[0;1] -> 2

::x         get global  a:3;::"a" -> 3
::[x;y]     set global  ::["a";3];a -> 3
@[x;y;f]    amend       @[1 2 3;0 1;10+] -> 11 12 3
@[x;y;F;z]  amend       @[8 4 5;(1 2;0);+;(10 5;-2)] -> 6 14 10
.[x;y;f]    deep amend  .[(1 2;3 4);0 1;-] -> (1 -2;3 4)
.[x;y;F;z]  deep amend  .[(1 2;3 4);(0 1 0;1);+;1] -> (1 4;3 5)
                        .[(1 2;3 4);(*;1);:;42] -> (1 42;3 42)
.[f;x;f]    try         .[+;2 3;{"msg"}] -> 5   .[+;2 "a";{"msg"}] -> "msg"

NAMED VERBS HELP
abs x     abs value     abs -3 -1.5 2 -> 3 1.5 2
bytes x   byte-count    bytes "abc" -> 3
ceil x    ceil          ceil 1.5 -> 2   ceil "ab" -> "AB"
error x   error         r:{?[~x=0;1%x;error "zero"]}0;?["e"~@r;.r;r] -> "zero"
eval s    eval          a:5;eval "a+2" -> 7 (unrestricted eval)
firsts x  mark firsts   firsts 0 0 2 3 0 2 3 4 -> 1 0 1 1 0 0 0 1
icount x  index-count   icount 0 0 1 -1 0 1 2 3 2 -> 3 2 2 1 (same as #'=x)
ocount x  occur-count   ocount 3 2 5 3 2 2 7 -> 0 0 0 1 1 2 0
panic s   panic         panic "msg" (for fatal programming-errors)
rshift x  right shift   rshift 1 2 -> 0 1       rshift "a" "b" -> "" "a"
rx s      comp. regex   rx "[a-z]"  (like rx/[a-z]/ but compiled at runtime)
seed i    rand seed     seed 42 (for non-secure pseudo-rand with ?)
shift x   shift         shift 1 2 -> 2 0        shift "a" "b" -> "b" ""
sign x    sign          sign -3 -1 0 1.5 5 -> -1 -1 0 1 1

x csv y     csv read    csv "1,2,3" -> ,"1" "2" "3"
                        " " csv "1 2 3" -> ,"1" "2" "3" (" " as separator)
            csv write   csv ,"1" "2" "3" -> "1,2,3\n"
                        " " csv ,"1" "2" "3" -> "1 2 3\n"
x in s      contained   "bc" "ac" in "abcd" -> 1 0
x in y      member of   2 3 in 0 2 4 -> 1 0
x nan y     fill NaNs   42 nan (1.5;sqrt -1) -> 1.5 42
n mod n     modulus     3 mod 5 4 3 -> 2 1 0
x rotate y  rotate      2 rotate 1 2 3 4 -> 3 4 1 2
x rshift y  right shift "a" "b" rshift 1 2 3 -> "a" "b" 1
x shift y   shift       "a" "b" shift 1 2 3 -> 3 "a" "b"

sub[r;s]    regsub      sub[rx/[a-z]/;"Z"] "aBc" -> "ZBZ"
sub[r;f]    regsub      sub[rx/[A-Z]/;_] "aBc" -> "abc"
sub[s;s]    replace     sub["b";"B"] "abc" -> "aBc"
sub[s;s;i]  replaceN    sub["a";"b";2] "aaa" -> "bba" (stop after 2 times)
sub[S]      replace     sub["b" "d" "c" "e"] "abc" -> "ade"
sub[S;S]    replace     sub["b" "c";"d" "e"] "abc" -> "ade"

eval[x;y;z] eval        like eval x, but provide name y as location and prefix
                        z for globals

MATH: acos, asin, atan, cos, exp, log, round, sin, sqrt, tan, nan
UTF-8: utf8.rcount (number of code points), utf8.valid

ADVERBS HELP
f'x    each      #'(4 5;6 7 8) -> 2 3
x F'y  each      2 3#'1 2 -> (1 1;2 2 2)    {(x;y;z)}'[1;2 4;3] -> (1 2 3;1 4 3)
F/x    fold      +/!10 -> 45                         
F\x    scan      +\!10 -> 0 1 3 6 10 15 21 28 36 45
x F/y  fold      1 2+/!10 -> 46 47                 {x+y-z}/[9;3 4;2 7] -> 7
x F\y  scan      5 6+\1 2 3 -> (6 7;8 9;11 12)     {x+y-z}\[9;3 4;2 7] -> 10 7
i f/x  do        3{x*2}/4 -> 32
i f\x  dos       3{x*2}\4 -> 4 8 16 32
f f/x  while     {x<100}{x*2}/4 -> 128
f f\x  whiles    {x<100}{x*2}\4 -> 4 8 16 32 64 128
f/x    converge  {1+1.0%x}/1 -> 1.618033988749895     {-x}/1 -> -1
f\x    converges {_x%2}\10 -> 10 5 2 1 0              {-x}\1 -> 1 -1
s/x    join      ","/"a" "b" "c" -> "a,b,c"
s\x    split     ","\"a,b,c" -> "a" "b" "c"
i s\x  splitN    (2) ","\"a,b,c" -> "a" "b,c"
I/x    encode    24 60 60/1 2 3 -> 3723  2/1 1 0 -> 6
I\x    decode    24 60 60\3723 -> 1 2 3  2\6 -> 1 1 0

IO/OS HELP
import s        eval file s+".goal" and import globals with prefix s+"."
print x         print "Hello, world!\n"
say x           same as print, but appends a newline    say !5
shell s         run a command string s as-is through the shell
slurp s         read file named s       lines:"\n"\slurp["/path/to/file"]

pfx import s    like import s but with prefix pfx+"." for globals
w print x       print x to writer or filename     "filename" print "content"
w say x         same as print, but appends a newline

os.ARGS         command-line arguments, starting with script name
os.ENV          keys!values strings dictionnary representing environment

TIME HELP
time cmd                time command with current time
cmd time t              time command with time t
time[cmd;t;format]      time command with time t in given format
time[cmd;t;format;loc]  time command with time t in given format and location

Time t should be either an integer representing unix epochtime, or a string
in the given format (RFC3339 format layout "2006-01-02T15:04:05Z07:00" is the
default). See https://pkg.go.dev/time for information on layouts and locations,
as goal uses the same conventions as Go's time package.

Currently available commands:
        "day"           day number (i)
        "date"          year, month, day (I)
        "clock"         hour, minute, second (I)
        "hour"          0-23 hour (i)
        "minute"        0-59 minute (i)
        "second"        0-59 second (i)
        "unix"          unix epoch time (i)
        "unixmilli"     unix (millisecond version, only for current time) (i)
        "unixmicro"     unix (microsecond version, only for current time) (i)
        "unixnano"      unix (nanosecond version, only for current time) (i)
        "year"          year (i)
        "yearday"       1-365/6 year day (i)
        "week"          year, week (I)
        "weekday"       0-7 weekday (starts from Sunday) (i)
        format (s)      format time using given layout (s)

Documentation

Overview

Package goal provides an API to goal's interpreter.

In order to evaluate code in the goal programming language, first a new context has to be created.

ctx := goal.NewContext()

This context can then be used to Compile some code, and then Run it. It is possible to customize the context by registering new unary and binary operators using the RegisterMonad and RegisterDyad methods.

See tests in context_test.go, as well as cmd/goal/main.go, for usage examples.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Length

func Length(x V) int

Length returns the length of a value like in #x.

func Match

func Match(x, y V) bool

Match returns true if the two values match like in x~y.

Types

type AB

type AB struct {
	Slice []bool
	// contains filtered or unexported fields
}

AB represents an array of booleans.

func (*AB) At

func (x *AB) At(i int) bool

At returns array value at the given index.

func (*AB) CloneWithRC added in v0.2.0

func (x *AB) CloneWithRC(rc *int) Value

func (*AB) DecrRC

func (x *AB) DecrRC()

func (*AB) Fprint

func (x *AB) Fprint(ctx *Context, w ValueWriter) (n int, err error)

func (*AB) IncrRC

func (x *AB) IncrRC()

func (*AB) InitWithRC added in v0.2.0

func (x *AB) InitWithRC(rc *int)

func (*AB) Len

func (x *AB) Len() int

Len returns the length of the array.

func (*AB) Less added in v0.4.0

func (xv *AB) Less(y Value) bool

func (*AB) Matches

func (x *AB) Matches(y Value) bool

func (*AB) RC added in v0.2.0

func (x *AB) RC() *int

RC returns the array's reference count pointer.

func (*AB) Type

func (x *AB) Type() string

Type returns a string representation of the array's type.

type AF

type AF struct {
	Slice []float64
	// contains filtered or unexported fields
}

AF represents an array of reals.

func (*AF) At

func (x *AF) At(i int) float64

At returns array value at the given index.

func (*AF) CloneWithRC added in v0.2.0

func (x *AF) CloneWithRC(rc *int) Value

func (*AF) DecrRC

func (x *AF) DecrRC()

func (*AF) Fprint

func (x *AF) Fprint(ctx *Context, w ValueWriter) (n int, err error)

func (*AF) IncrRC

func (x *AF) IncrRC()

func (*AF) InitWithRC added in v0.2.0

func (x *AF) InitWithRC(rc *int)

func (*AF) Len

func (x *AF) Len() int

Len returns the length of the array.

func (*AF) Less added in v0.4.0

func (xv *AF) Less(y Value) bool

func (*AF) Matches

func (x *AF) Matches(y Value) bool

func (*AF) RC added in v0.2.0

func (x *AF) RC() *int

RC returns the array's reference count pointer.

func (*AF) Type

func (x *AF) Type() string

Type returns a string representation of the array's type.

type AI

type AI struct {
	Slice []int64
	// contains filtered or unexported fields
}

AI represents an array of integers.

func (*AI) At

func (x *AI) At(i int) int64

At returns array value at the given index.

func (*AI) CloneWithRC added in v0.2.0

func (x *AI) CloneWithRC(rc *int) Value

func (*AI) DecrRC

func (x *AI) DecrRC()

func (*AI) Fprint

func (x *AI) Fprint(ctx *Context, w ValueWriter) (n int, err error)

func (*AI) IncrRC

func (x *AI) IncrRC()

func (*AI) InitWithRC added in v0.2.0

func (x *AI) InitWithRC(rc *int)

func (*AI) Len

func (x *AI) Len() int

Len returns the length of the array.

func (*AI) Less added in v0.4.0

func (xv *AI) Less(y Value) bool

func (*AI) Matches

func (x *AI) Matches(y Value) bool

func (*AI) RC added in v0.2.0

func (x *AI) RC() *int

RC returns the array's reference count pointer.

func (*AI) Type

func (x *AI) Type() string

Type returns a string representation of the array's type.

type AS

type AS struct {
	Slice []string // string array
	// contains filtered or unexported fields
}

AS represents an array of strings.

func (*AS) At

func (x *AS) At(i int) string

At returns array value at the given index.

func (*AS) CloneWithRC added in v0.2.0

func (x *AS) CloneWithRC(rc *int) Value

func (*AS) DecrRC

func (x *AS) DecrRC()

func (*AS) Fprint

func (x *AS) Fprint(ctx *Context, w ValueWriter) (n int, err error)

func (*AS) IncrRC

func (x *AS) IncrRC()

func (*AS) InitWithRC added in v0.2.0

func (x *AS) InitWithRC(rc *int)

func (*AS) Len

func (x *AS) Len() int

Len returns the length of the array.

func (*AS) Less added in v0.4.0

func (xv *AS) Less(y Value) bool

func (*AS) Matches

func (x *AS) Matches(y Value) bool

func (*AS) RC added in v0.2.0

func (x *AS) RC() *int

RC returns the array's reference count pointer.

func (*AS) Type

func (x *AS) Type() string

Type returns a string representation of the array's type.

type AV

type AV struct {
	Slice []V
	// contains filtered or unexported fields
}

AV represents a generic array.

func (*AV) At

func (x *AV) At(i int) V

At returns array value at the given index.

func (*AV) CloneWithRC added in v0.2.0

func (x *AV) CloneWithRC(rc *int) Value

func (*AV) DecrRC

func (x *AV) DecrRC()

func (*AV) Fprint

func (x *AV) Fprint(ctx *Context, w ValueWriter) (n int, err error)

func (*AV) IncrRC

func (x *AV) IncrRC()

func (*AV) InitWithRC added in v0.2.0

func (x *AV) InitWithRC(rc *int)

func (*AV) Len

func (x *AV) Len() int

Len returns the length of the array.

func (*AV) Less added in v0.4.0

func (xv *AV) Less(y Value) bool

func (*AV) Matches

func (x *AV) Matches(y Value) bool

func (*AV) RC added in v0.2.0

func (x *AV) RC() *int

RC returns the array's reference count pointer.

func (*AV) Type

func (x *AV) Type() string

Type returns a string representation of the array's type.

type Context

type Context struct {
	// contains filtered or unexported fields
}

Context holds the state of the interpreter.

func NewContext

func NewContext() *Context

NewContext returns a new context for compiling and interpreting code.

func (*Context) Apply

func (ctx *Context) Apply(x, y V) V

Apply calls a value with a single argument.

func (*Context) Apply2

func (ctx *Context) Apply2(x, y, z V) V

Apply2 calls a value with two arguments.

func (*Context) ApplyN

func (ctx *Context) ApplyN(x V, args []V) V

ApplyN calls a value with one or more arguments. The arguments should be provided in reverse order, given the stack-based right to left semantics used by the language.

func (*Context) AssignGlobal

func (ctx *Context) AssignGlobal(name string, x V)

AssignGlobal assigns a value to a global variable name.

func (*Context) AssignedLast

func (ctx *Context) AssignedLast() bool

AssignedLast returns true if the last compiled expression was an assignment.

func (*Context) Compile

func (ctx *Context) Compile(name string, s string) error

Compile parses and compiles code from the given source string. The name argument is used for error reporting and represents, usually, the filename.

func (*Context) Eval

func (ctx *Context) Eval(s string) (V, error)

Eval calls Compile with the given string as unnamed source, and then Run. You cannot call it within a variadic function, as it the evaluation is done on the current context, so it would interrupt compilation of current file. Use EvalPackage for that.

func (*Context) EvalPackage

func (ctx *Context) EvalPackage(s, name, prefix string) (V, error)

EvalPackage calls Compile with the string as source, name (for error location and caching, usually a filename), prefix (for global variables, usually a filename without the extension), and then Run. If a package with same name has already been evaluated, it returns ErrPackageImported. Current implementation has the following limitation: if a prefix is provided, it is only used the first time a same package is evaluated (so all imports have to share the same prefix). The package is evaluated in a derived context that is then merged on successful completion, so this function can be called within a variadic function.

func (*Context) GetGlobal

func (ctx *Context) GetGlobal(name string) (V, bool)

GetGlobal returns the value attached to a global variable with the given name.

func (*Context) RegisterDyad

func (ctx *Context) RegisterDyad(name string, vf VariadicFun) V

RegisterDyad adds a variadic function to the context, and generates a new dyadic keyword for that variadic (parsing will search for a left argument). The variadic is also returned as a value.

func (*Context) RegisterMonad

func (ctx *Context) RegisterMonad(name string, vf VariadicFun) V

RegisterMonad adds a variadic function to the context, and generates a new monadic keyword for that variadic (parsing will not search for a left argument). The variadic is also returned as a value. Note that while that a keyword defined in such a way will not take a left argument, it is still possible to pass several arguments to it with bracket indexing, like for any value.

func (*Context) Run

func (ctx *Context) Run() (V, error)

Run runs compiled code, if not already done, and returns the result value.

func (*Context) Show

func (ctx *Context) Show() string

Show returns a string representation with debug information about the context.

type Dict added in v0.5.0

type Dict struct {
	// contains filtered or unexported fields
}

Dict represents a dictionnary.

func (*Dict) CloneWithRC added in v0.5.0

func (d *Dict) CloneWithRC(rc *int) Value

func (*Dict) DecrRC added in v0.5.0

func (d *Dict) DecrRC()

func (*Dict) Fprint added in v0.5.0

func (d *Dict) Fprint(ctx *Context, w ValueWriter) (n int, err error)

func (*Dict) IncrRC added in v0.5.0

func (d *Dict) IncrRC()

func (*Dict) InitWithRC added in v0.5.0

func (d *Dict) InitWithRC(rc *int)

func (*Dict) Keys added in v0.5.0

func (d *Dict) Keys() V

Keys returns the keys of the dictionnary.

func (*Dict) Len added in v0.5.0

func (d *Dict) Len() int

func (*Dict) Less added in v0.5.0

func (d *Dict) Less(y Value) bool

func (*Dict) Matches added in v0.5.0

func (d *Dict) Matches(y Value) bool

func (*Dict) Type added in v0.5.0

func (d *Dict) Type() string

func (*Dict) Values added in v0.5.0

func (d *Dict) Values() V

Values returns the values of the dictionnary.

type ErrPackageImported

type ErrPackageImported struct{}

ErrPackageImported is returned by EvalPackage for packages that have already been processed.

func (ErrPackageImported) Error

func (e ErrPackageImported) Error() string

type NameType

type NameType int

NameType represents the different kinds of special roles for alphanumeric identifiers that act as keywords.

const (
	NameIdent NameType = iota // a normal identifier (default zero value)
	NameMonad                 // a builtin monad (cannot have left argument)
	NameDyad                  // a builtin dyad (can have left argument)
)

These constants represent the different kinds of special names.

type PanicError

type PanicError struct {
	Msg string // error message (without location)
	// contains filtered or unexported fields
}

PanicError represents a fatal error returned by any Context method.

func (*PanicError) Error

func (e *PanicError) Error() string

Error returns the default string representation. It makes uses of position information obtained from its running context.

type RefCountHolder added in v0.2.0

type RefCountHolder interface {
	RefCounter

	// RC returns the value's root reference count pointer.
	RC() *int
}

RefCountHolder is a RefCounter that has a root refcount pointer. When such values are returned from a variadic function, if the refcount pointer is still nil, InitWithRC is automatically called with a newly allocated refcount pointer to a zero count.

type RefCounter

type RefCounter interface {
	Value

	// IncrRC increments the reference count by one. It can panic if the
	// value's refcount pointer has not been properly initialized.
	IncrRC()

	// DecrRC decrements the reference count by one, or zero if it is
	// already zero.
	DecrRC()

	// InitWithRC recursively sets the refcount pointer for reusable
	// values, and increments by 2 the refcount of non-reusable values, to
	// ensure immutability of non-reusable children without cloning them.
	InitWithRC(rc *int)

	// CloneWithRC returns a clone of the value, with rc as new refcount
	// pointer.  If the current value's current refcount pointer is nil or
	// equal to the passed one, the same value is returned after updating
	// the refcount pointer as needed, instead of doing a full clone.
	CloneWithRC(rc *int) Value
}

RefCounter is implemented by values that use a reference count. In goal the refcount is not used for memory management, but only for optimization of memory allocations. Refcount is increased by each assignement, and each push operation on the stack, except for pushes corresponding to the last use of a variable (as approximated conservatively). It is reduced after each drop. If refcount is equal or less than one, then the value is considered reusable.

When defining a new type implementing the Value interface, it is only necessary to also implement RefCounter if the type definition makes use of a type implementing it (for example an array type or a generic V).

type S

type S string

S represents (immutable) strings of bytes.

func (S) Fprint

func (s S) Fprint(ctx *Context, w ValueWriter) (n int, err error)

Fprint writes a properly quoted string.

func (S) Less added in v0.4.0

func (xv S) Less(y Value) bool

func (S) Matches

func (s S) Matches(y Value) bool

func (S) Type

func (s S) Type() string

Type retuns "s" for string atoms.

type Scanner

type Scanner struct {
	// contains filtered or unexported fields
}

Scanner represents the state of the scanner.

func NewScanner

func NewScanner(names map[string]NameType, source string) *Scanner

NewScanner returns a scanner for the given source string.

func (*Scanner) Next

func (s *Scanner) Next() Token

Next produces the next token from the input reader.

type Token

type Token struct {
	Type TokenType // token type
	Pos  int       // token's offset in the source
	Text string    // content text (identifier, string, number)
}

Token represents a token information.

func (Token) String

func (t Token) String() string

type TokenType

type TokenType int

TokenType represents the different kinds of tokens.

const (
	NONE TokenType = iota
	EOF
	ERROR
	ADVERB
	DYAD
	DYADASSIGN
	IDENT
	LEFTBRACE
	LEFTBRACKET
	LEFTPAREN
	NEWLINE
	NUMBER
	MONAD
	REGEXP
	RIGHTBRACE
	RIGHTBRACKET
	RIGHTPAREN
	SEMICOLON
	STRING
)

These constants describe the possible kinds of tokens.

func (TokenType) String

func (i TokenType) String() string

type V

type V struct {
	// contains filtered or unexported fields
}

V contains a boxed or unboxed value.

func Canonical

func Canonical(x V) V

Canonical returns the canonical form of a given value, that is the most specialized form, assuming it's already canonical at depth > 1. In practice, if the value is a generic array, but a more specialized version could represent the value, it returns the specialized value. All goal variadic functions have to return results in canonical form, so this function can be used to ensure that.

func CanonicalRec added in v0.2.0

func CanonicalRec(x V) V

CanonicalRec returns the canonical form of a given value, that is the most specialized form. In practice, if the value is a generic array, but a more specialized version could represent the value, it returns the specialized value. All goal variadic functions have to return results in canonical form, so this function can be used to ensure that.

func Errorf

func Errorf(format string, a ...interface{}) V

Errorf returns a formatted recoverable error value.

func NewAB

func NewAB(x []bool) V

NewAB returns a new boolean array. It does not initialize the reference counter.

func NewABWithRC added in v0.2.0

func NewABWithRC(x []bool, rc *int) V

NewABWithRC returns a new boolean array.

func NewAF

func NewAF(x []float64) V

NewAF returns a new array of reals. It does not initialize the reference counter.

func NewAFWithRC added in v0.2.0

func NewAFWithRC(x []float64, rc *int) V

NewAFWithRC returns a new array of reals.

func NewAI

func NewAI(x []int64) V

NewAI returns a new int array. It does not initialize the reference counter.

func NewAIWithRC added in v0.2.0

func NewAIWithRC(x []int64, rc *int) V

NewAIWithRC returns a new int array.

func NewAS

func NewAS(x []string) V

NewAS returns a new array of strings. It does not initialize the reference counter.

func NewASWithRC added in v0.2.0

func NewASWithRC(x []string, rc *int) V

NewASWithRC returns a new array of strings.

func NewAV

func NewAV(x []V) V

NewAV returns a new generic array. It does not initialize the reference counter.

func NewAVWithRC added in v0.2.0

func NewAVWithRC(x []V, rc *int) V

NewAVWithRC returns a new generic array.

func NewDict added in v0.5.0

func NewDict(keys, values V) V

NewDict returns a dictionnary. Both keys and values should be arrays, and they should have the same length.

func NewError

func NewError(x V) V

NewError returns a new recoverable error value.

func NewF

func NewF(f float64) V

NewF returns a new float64 value.

func NewI

func NewI(i int64) V

NewI returns a new int64 value.

func NewPanic

func NewPanic(s string) V

NewPanic returns a fatal error value.

func NewS

func NewS(s string) V

NewS returns a new string value.

func NewV

func NewV(bv Value) V

NewV returns a new boxed value.

func Panicf

func Panicf(format string, a ...interface{}) V

Panicf returns a formatted fatal error value.

func VAbs

func VAbs(ctx *Context, args []V) V

VAbs implements the "abs" variadic verb.

func VAcos

func VAcos(ctx *Context, args []V) V

VAcos implements the acos variadic.

func VAdd

func VAdd(ctx *Context, args []V) V

VAdd implements the + variadic verb.

func VAnd

func VAnd(ctx *Context, args []V) V

VAnd implements the "and" variadic verb.

func VApply

func VApply(ctx *Context, args []V) V

VApply implements the @ variadic verb.

func VApplyN

func VApplyN(ctx *Context, args []V) V

VApplyN implements the . variadic verb.

func VAsin

func VAsin(ctx *Context, args []V) V

VAsin implements the asin variadic.

func VAtan

func VAtan(ctx *Context, args []V) V

VAtan implements the atan variadic.

func VBytes

func VBytes(ctx *Context, args []V) V

VBytes implements the "bytes" variadic verb.

func VCSV

func VCSV(ctx *Context, args []V) V

VCSV implements the "csv" variadic verb.

func VCast

func VCast(ctx *Context, args []V) V

VCast implements the $ variadic verb.

func VCeil

func VCeil(ctx *Context, args []V) V

VCeil implements the "ceil" variadic verb.

func VCos

func VCos(ctx *Context, args []V) V

VCos implements the cos variadic.

func VDivide

func VDivide(ctx *Context, args []V) V

VDivide implements the % variadic verb.

func VDrop

func VDrop(ctx *Context, args []V) V

VDrop implements the _ variadic verb.

func VEach

func VEach(ctx *Context, args []V) V

VEach implements the ' variadic adverb.

func VEqual

func VEqual(ctx *Context, args []V) V

VEqual implements the = variadic verb.

func VError

func VError(ctx *Context, args []V) V

VError implements the "error" variadic verb.

func VEval

func VEval(ctx *Context, args []V) V

VEval implements the "eval" variadic verb.

func VExp

func VExp(ctx *Context, args []V) V

VExp implements the exp variadic.

func VFind

func VFind(ctx *Context, args []V) V

VFind implements the ? variadic verb.

func VFirsts

func VFirsts(ctx *Context, args []V) V

VFirsts implements the "firsts" variadic verb.

func VFold

func VFold(ctx *Context, args []V) V

VFold implements the / variadic adverb.

func VICount

func VICount(ctx *Context, args []V) V

VICount implements the "icount" variadic verb.

func VIn

func VIn(ctx *Context, args []V) V

VIn implements the "in" variadic verb.

func VJoin

func VJoin(ctx *Context, args []V) V

VJoin implements the , variadic verb.

func VKey added in v0.5.0

func VKey(ctx *Context, args []V) V

VKey implements the ! variadic verb.

func VLess

func VLess(ctx *Context, args []V) V

VLess implements the < variadic verb.

func VList

func VList(ctx *Context, args []V) V

VList implements (x;y;...) array constructor variadic verb.

func VLog

func VLog(ctx *Context, args []V) V

VLog implements the log variadic.

func VMatch

func VMatch(ctx *Context, args []V) V

VMatch implements the ~ variadic verb.

func VMax

func VMax(ctx *Context, args []V) V

VMax implements the | variadic verb.

func VMin

func VMin(ctx *Context, args []V) V

VMin implements the & variadic verb.

func VMod

func VMod(ctx *Context, args []V) V

VMod implements the mod variadic verb.

func VMore

func VMore(ctx *Context, args []V) V

VMore implements the > variadic verb.

func VMultiply

func VMultiply(ctx *Context, args []V) V

VMultiply implements the * variadic verb.

func VNaN

func VNaN(ctx *Context, args []V) V

VNaN implements the nan variadic verb.

func VOCount

func VOCount(ctx *Context, args []V) V

VOCount implements the "ocount" variadic verb.

func VOr

func VOr(ctx *Context, args []V) V

VOr implements the "or" variadic verb.

func VPanic

func VPanic(ctx *Context, args []V) V

VPanic implements the "panic" variadic verb.

func VRShift

func VRShift(ctx *Context, args []V) V

VRShift implements the rshift variadic verb.

func VRight

func VRight(ctx *Context, args []V) V

VRight implements the : variadic verb.

func VRotate

func VRotate(ctx *Context, args []V) V

VRotate implements the rotate variadic verb.

func VRoundToEven

func VRoundToEven(ctx *Context, args []V) V

VRoundToEven implements the round variadic.

func VRx

func VRx(ctx *Context, args []V) V

VRx implements the rx variadic.

func VScan

func VScan(ctx *Context, args []V) V

VScan implements the \ variadic adverb.

func VSeed

func VSeed(ctx *Context, args []V) V

VSeed implements the "seed" variadic verb.

func VSet

func VSet(ctx *Context, args []V) V

VSet implements the "set" variadic verb.

func VShift

func VShift(ctx *Context, args []V) V

VShift implements the shift variadic verb.

func VSign

func VSign(ctx *Context, args []V) V

VSign implements the "sign" variadic verb.

func VSin

func VSin(ctx *Context, args []V) V

VSin implements the sin variadic.

func VSqrt

func VSqrt(ctx *Context, args []V) V

VSqrt implements the sqrt variadic.

func VSub

func VSub(ctx *Context, args []V) V

VSub implements the sub variadic verb.

func VSubtract

func VSubtract(ctx *Context, args []V) V

VSubtract implements the - variadic verb.

func VTake

func VTake(ctx *Context, args []V) V

VTake implements the # variadic verb.

func VTan

func VTan(ctx *Context, args []V) V

VTan implements the tan variadic.

func VTime

func VTime(ctx *Context, args []V) V

VTime implements the time variadic verb.

func VUTF8RCount

func VUTF8RCount(ctx *Context, args []V) V

VUTF8RCount implements the "utf8.rcount" variadic verb.

func VUTF8Valid

func VUTF8Valid(ctx *Context, args []V) V

VUTF8Valid implements the "utf8.valid" variadic verb.

func VWithout

func VWithout(ctx *Context, args []V) V

VWithout implements the ^ variadic verb.

func (V) Clone added in v0.2.0

func (x V) Clone() V

Clone creates an identical deep copy of a value, or the value itself if it is reusable. It initializes refcount if necessary.

func (V) CloneWithRC added in v0.2.0

func (x V) CloneWithRC(rc *int) V

func (V) DecrRC

func (x V) DecrRC()

DecrRC decrements the value reference count (if it has any).

func (V) Error

func (x V) Error() V

Error retrieves the error value. It assumes IsError(v).

func (V) F

func (x V) F() float64

F retrieves the unboxed float64 value. It assumes isF(v).

func (V) Fprint

func (v V) Fprint(ctx *Context, w ValueWriter) (n int, err error)

Fprint writes a matching program string representation of the value.

func (V) HasRC added in v0.2.0

func (x V) HasRC() bool

HasRC returns true if the value is boxed and implements RefCounter.

func (V) I

func (x V) I() int64

I retrieves the unboxed integer value from N field. It assumes IsI(v).

func (V) IncrRC

func (x V) IncrRC()

IncrRC increments the value reference count (if it has any).

func (V) InitRC added in v0.2.0

func (x V) InitRC()

InitRC initializes refcount if the value is a RefCountHolder with nil refcount.

func (V) InitWithRC added in v0.2.0

func (x V) InitWithRC(rc *int)

InitWithRC calls the method of the same name on boxed values.

func (V) IsError

func (x V) IsError() bool

IsError returns true if the value is a recoverable error.

func (V) IsF

func (x V) IsF() bool

IsF returns true if the value is a float.

func (V) IsFunction

func (x V) IsFunction() bool

IsFunction returns true if the value is some kind of function.

func (V) IsI

func (x V) IsI() bool

IsI returns true if the value is an integer.

func (V) IsPanic

func (x V) IsPanic() bool

IsPanic returns true if the value is a fatal error.

func (V) IsValue

func (x V) IsValue() bool

IsValue returns true if the value is a boxed value satisfying the Value interface. You can then get the value with the Value method.

func (V) Less added in v0.4.0

func (x V) Less(y V) bool

Less returns true if x is ordered before y. It represents a strict total order. Values are ordered as follows: unboxed atoms first (nums, variadics, then lambdas), then boxed values. Otherwise, values are compared with < and > when comparable, and otherwise using their Type string value. As a special case, comparable arrays are compared first by length, or lexicographically if they are of equal length.

func (V) Rank

func (x V) Rank(ctx *Context) int

Rank returns the default rank of the value, that is the number of arguments it normally takes. It returns 0 for non-function values. This default rank is used when a function is used in an adverbial expression that has different semantics depending on the function arity. Currently, ranks are as follows:

variadic	2
lambda		number of arguments
projections	number of gaps
derived verb	1

func (V) Sprint

func (v V) Sprint(ctx *Context) string

Sprint returns a matching program string representation of the value.

func (V) Type

func (x V) Type() string

Type returns the name of the value's type.

func (V) Value

func (x V) Value() Value

Value retrieves the boxed value, or nil if the value is not boxed. You can check whether the value is boxed with IsValue(v).

type Value

type Value interface {
	// Matches returns true if the value matches another (in the sense of
	// the ~ operator).
	Matches(Value) bool
	// Fprint writes a unique program string representation of the value.
	Fprint(*Context, ValueWriter) (n int, err error)
	// Type returns the name of the value's type. It may be used by Less to
	// sort non-comparable values using lexicographic order.  This means
	// Type should return different values for non-comparable values.
	Type() string
	// Less returns true if the value should be orderer before the given
	// one. It is used for sorting values, but not for element-wise
	// comparison with < and >. It should produce a strict total order, so,
	// in particular, if x < y, then we do not have y > x, and one of them
	// should hold unless both values match.
	Less(Value) bool
}

Value is the interface satisfied by all boxed values.

type ValueWriter

type ValueWriter interface {
	io.Writer
	io.ByteWriter
	io.StringWriter
}

ValueWriter is the interface used when formatting values with Fprint.

type VariadicFun

type VariadicFun func(*Context, []V) V

VariadicFun represents a variadic function.

Directories

Path Synopsis
cmd
Package cmd provides a quick way to create derived interpreters.
Package cmd provides a quick way to create derived interpreters.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL