snoc

package module
v0.0.0-...-89d1eee Latest Latest
Warning

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

Go to latest
Published: Sep 21, 2020 License: MIT Imports: 14 Imported by: 0

README

go-snoc

Simple LISP written in Go.

Currently uses a simple environment list for local variables, no fancy lexical bindng. NO I'M CHANGING THAT....

work in progress...

Right now go test should work:

[0]<---- (def pos 1)
---->   nil
[0]<---- (def neg -1)
---->   nil
[0]<---- (def zero 0)
---->   nil
[0]<---- (defun signum (x) (if (< x 0) neg (> x 0) pos zero))
---->   nil
[0]<---- (list (signum -888) (signum 0) (signum 123))
---->   (-1 0 1)
[0]<---- (list (list 1 2 3) (list 4 5 6))
---->   ((1 2 3) (4 5 6))
[0]<---- (let A (list 1 2 3) B (list 4 5 6) C (list A B) (list A B C))
---->   ((1 2 3) (4 5 6) ((1 2 3) (4 5 6)))
[0]<---- (defun my-triangle (x) (if (< x 1) 0 (+ x (my-triangle (- x 1)))))
---->   nil
[0]<---- (my-triangle 6)
---->   21
[0]<---- (defun my-length (x) (if (null? x) 0 (+ 1 (my-length (tail x)))))
---->   nil
[0]<---- (my-length (list 9 7 5 3 1))
---->   5
[0]<---- (defun my-descending (n) (if (<= n 0) (list) (cons n (my-descending (- n 1)))))
---->   nil
[0]<---- (my-descending 7)
---->   (7 6 5 4 3 2 1)
[0]<---- (defun my-descending (n) (if (<= n 0) (list) (cons n (my-descending (- n 1)))))
---->   nil
[0]<---- (defun my-sum (aList) (if (null? aList) 0 (+ (head aList) (my-sum (tail aList)))))
---->   nil
[0]<---- 111
[1]<---- 222
[2]<---- 333
---->   333
[0]<---- (my-sum (my-descending 100))
---->   5050

You can also use snoc.go to evaluate stdin:

$ echo '(defun !(x) (if (< x 1) 1 (* x (! (- x 1))))) (! 10)' | go run snoc.go 
[0]<---- (defun ! (x) (if (< x 1) 1 (* x (! (- x 1)))))
[1]<---- (! 10)
---->   3.6288e+06
2020/09/13 17:33:18 ==> result[0] = 3.6288e+06

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// Traditionally NIL would be a special *Sym,
	// but in this Lisp it will be a special *Pair.
	// It is not Interned.  The parser will have to know
	// about this special name.  AtomP(NIL) is still true,
	// although it cannot be used as an environment key.
	NIL   = &Pair{}         // Address matters; contents do not.
	FN    = Intern("fn")    // In other Lisps, this is lambda.
	TRUE  = Intern("true")  // In other Lisps, this is T or *T*.
	DEF   = Intern("def")   // Special to the REPL; it modifies the env.
	DEFUN = Intern("defun") // Special to the REPL; it modifies the env.
)
View Source
var BuiltinFloatingBinaryOps = map[string]func(float64, float64) float64{
	"+":   func(a, b float64) float64 { return a + b },
	"-":   func(a, b float64) float64 { return a - b },
	"*":   func(a, b float64) float64 { return a * b },
	"div": func(a, b float64) float64 { return a / b },
	"mod": func(a, b float64) float64 { return math.Mod(a, b) },
}
View Source
var BuiltinFloatingRelOps = map[string]func(float64, float64) bool{
	"<":  func(a, b float64) bool { return a < b },
	"<=": func(a, b float64) bool { return a <= b },
	"==": func(a, b float64) bool { return a == b },
	"!=": func(a, b float64) bool { return a != b },
	">":  func(a, b float64) bool { return a > b },
	">=": func(a, b float64) bool { return a >= b },
}
View Source
var BuiltinPrims = map[string]func([]Any, *Env) Any{
	"call/cc": CallCC,
	"list": func(args []Any, env *Env) Any {
		z := NIL
		for i := len(args) - 1; i >= 0; i-- {
			z = Snoc(z, args[i])
		}
		return z
	},
	"null?": func(args []Any, env *Env) Any {
		MustLen(args, 1)
		return LispyBool(NullP(args[0]))
	},
	"atom?": func(args []Any, env *Env) Any {
		MustLen(args, 1)
		return LispyBool(AtomP(args[0]))
	},
	"eq": func(args []Any, env *Env) Any {
		MustLen(args, 2)
		return LispyBool(Eq(args[0], args[1]))
	},
	"head": func(args []Any, env *Env) Any {
		MustLen(args, 1)
		return Head(args[0])
	},
	"tail": func(args []Any, env *Env) Any {
		MustLen(args, 1)
		return Tail(args[0])
	},
	"1st": func(args []Any, env *Env) Any {
		MustLen(args, 1)
		return Head(args[0])
	},
	"2nd": func(args []Any, env *Env) Any {
		MustLen(args, 1)
		return Head(Tail(args[0]))
	},
	"3rd": func(args []Any, env *Env) Any {
		MustLen(args, 1)
		return Head(Head(Tail(args[0])))
	},
	"4th": func(args []Any, env *Env) Any {
		MustLen(args, 1)
		return Head(Head(Tail(Tail(args[0]))))
	},
	"5th": func(args []Any, env *Env) Any {
		MustLen(args, 1)
		return Head(Head(Tail(Tail(Tail(args[0])))))
	},
	"eval": func(args []Any, env *Env) Any {
		MustLen(args, 1)
		return Eval(args[0], env)
	},
	"apply": func(args []Any, env *Env) Any {
		MustLen(args, 2)
		return Apply(args[0], ListToVec(args[1]), env)
	},
	"snoc": func(args []Any, env *Env) Any {
		MustLen(args, 2)
		p, ok := args[0].(*Pair)
		if !ok {
			Throw(args[0], "cannot Snoc")
		}
		return Snoc(p, args[1])
	},
	"cons": func(args []Any, env *Env) Any {
		MustLen(args, 2)
		p, ok := args[1].(*Pair)
		if !ok {
			Throw(args[1], "cannot Cons")
		}
		return Snoc(p, args[0])
	},
	"sum": func(args []Any, env *Env) Any {
		sum := 0.0
		for _, a := range args {
			sum += ToFloat(a)
		}
		return sum
	},
	"product": func(args []Any, env *Env) Any {
		product := 1.0
		for _, a := range args {
			product *= ToFloat(a)
		}
		return product
	},
}
View Source
var BuiltinSpecials = map[string]func([]Any, *Env) Any{
	"quote": func(args []Any, env *Env) Any {
		MustLen(args, 1)
		return args[0]
	},
	"and": func(args []Any, env *Env) Any {
		z := Any(TRUE)
		for _, a := range args {
			x := Eval(a, env)
			if NullP(x) {
				return NIL
			}
			z = x
		}
		return z
	},
	"or": func(args []Any, env *Env) Any {
		for _, a := range args {
			x := Eval(a, env)
			if Bool(x) {
				return x
			}
		}
		return NIL
	},
	"all": func(args []Any, env *Env) Any {
		for _, a := range args {
			if NullP(Eval(a, env)) {
				return NIL
			}
		}
		return TRUE
	},
	"any": func(args []Any, env *Env) Any {
		for _, a := range args {
			if Bool(Eval(a, env)) {
				return TRUE
			}
		}
		return NIL
	},
	"if": func(args []Any, env *Env) Any {
		for len(args) >= 2 {
			pred := Eval(args[0], env)
			if Bool(pred) {
				return Eval(args[1], env)
			}
			args = args[2:]
		}
		MustEq(len(args), 1)
		return Eval(args[0], env)
	},
}
View Source
var FlagVerbose = flag.Bool("v", false, "verbosity")
View Source
var InternTable = make(map[string]*Sym)

var Globals = make(map[string]Any)

Functions

func AtomP

func AtomP(o Any) bool

func Bool

func Bool(o Any) bool

func Eq

func Eq(o Any, a Any) bool

func ListLen

func ListLen(a Any) int

func Log

func Log(format string, args ...interface{})

func NullP

func NullP(o Any) bool

func ParseExprs

func ParseExprs(toks []Tok) (string, []Tok, []Any)

func Serial

func Serial(prefix string) string

func Stringify

func Stringify(o Any) string

func ToFloat

func ToFloat(o Any) float64

func ToInt

func ToInt(o Any) int

func ToStr

func ToStr(o Any) string

Types

type Any

type Any interface{}

func Apply

func Apply(o Any, args []Any, env *Env) Any

func ApplyFunc

func ApplyFunc(o *Func, args []Any, env *Env) Any

func ApplyPrim

func ApplyPrim(o *Prim, args []Any, env *Env) Any

func ApplySpecial

func ApplySpecial(o *Special, args []Any, env *Env) Any

func CallCC

func CallCC(args []Any, env *Env) Any

func Eval

func Eval(o Any, env *Env) Any

func EvalLambda

func EvalLambda(params []Any, body Any, env *Env) Any

func Get

func Get(o *Pair, key *Sym) (Any, bool)
func Head(o Any) Any

func LispyBool

func LispyBool(b bool) Any

func ListToVec

func ListToVec(a Any) []Any

func ParseFile

func ParseFile(filename string) []Any

func ParseText

func ParseText(text, filename string) []Any

func Repl

func Repl(terp *Terp, r io.Reader) []Any

func Tail

func Tail(o Any) Any

func Throw

func Throw(o Any, format string, args ...interface{}) Any

func TryReplEval

func TryReplEval(terp *Terp, xs []Any) (result Any, err interface{})

func TryReplParse

func TryReplParse(s string) (xs []Any, ok bool)

func VecToList

func VecToList(a []Any) Any

type ContinuationUsed

type ContinuationUsed string // for exiting thread.

type Env

type Env struct {
	Proto *ProtoFunc
	Up    *Env
	Slots []Any
	Terp  *Terp
}

func (*Env) String

func (env *Env) String() string

type Func

type Func struct {
	Outer  *Env
	Params []*Sym
	Values []Any // Only for Let
	Body   Any
	Name   string
	IsLet  bool
	Proto  *ProtoFunc
}

func (*Func) String

func (o *Func) String() string

type Pair

type Pair struct {
	H Any
	T *Pair
}

func Snoc

func Snoc(o *Pair, a Any) *Pair

func (*Pair) String

func (o *Pair) String() string

type Prim

type Prim struct {
	Name string
	F    func(args []Any, env *Env) Any // args are evaluated.
}

func (*Prim) String

func (o *Prim) String() string

type ProtoFunc

type ProtoFunc struct {
	Outer  *ProtoFunc
	Params []*Sym
	Values []Any // Only for Let
	Body   Any
	Name   string
	IsLet  bool
}

func PreprocessFunc

func PreprocessFunc(name string, params []*Sym, body Any, outer *ProtoFunc) (pf *ProtoFunc)

func (*ProtoFunc) String

func (o *ProtoFunc) String() string

type Special

type Special struct {
	Name string
	F    func(args []Any, env *Env) Any // args are unevaluated.
}

func (*Special) String

func (o *Special) String() string

type Sym

type Sym struct {
	S string
}

func Intern

func Intern(s string) *Sym

func ListToVecOfSym

func ListToVecOfSym(a Any) []*Sym

func (*Sym) String

func (o *Sym) String() string

type Terp

type Terp struct {
	Globals map[*Sym]Any
}

func NewTerp

func NewTerp() *Terp

type Tok

type Tok struct {
	Pos  scanner.Position
	Text string
}

func Lex

func Lex(text, filename string) (z []Tok)

type Var

type Var struct {
	Proto *ProtoFunc
	Slot  int
	Sym   *Sym
}

func (*Var) String

func (o *Var) String() string

Jump to

Keyboard shortcuts

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