123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695 |
- package zygo
- import (
- "fmt"
- "reflect"
- "strconv"
- "strings"
- )
- // all Sexp are typed, and have a zero value corresponding to
- // the type of the Sexp.
- // Sexp is the central interface for all
- // S-expressions (Symbol expressions ala lisp).
- type Sexp interface {
- // SexpString: produce a string from our value.
- // Single-line strings can ignore indent.
- // Only multiline strings should follow every
- // newline with at least indent worth of spaces.
- SexpString(ps *PrintState) string
- // Type returns the type of the value.
- Type() *RegisteredType
- }
- type SexpPair struct {
- Head Sexp
- Tail Sexp
- }
- type SexpPointer struct {
- ReflectTarget reflect.Value
- Target Sexp
- PointedToType *RegisteredType
- MyType *RegisteredType
- }
- func NewSexpPointer(pointedTo Sexp) *SexpPointer {
- pointedToType := pointedTo.Type()
- var reftarg reflect.Value
- //Q("NewSexpPointer sees pointedTo of '%#v'", pointedTo)
- switch e := pointedTo.(type) {
- case *SexpReflect:
- //Q("SexpReflect.Val = '%#v'", e.Val)
- reftarg = e.Val
- default:
- reftarg = reflect.ValueOf(pointedTo)
- }
- ptrRt := GoStructRegistry.GetOrCreatePointerType(pointedToType)
- //Q("pointer type is ptrRt = '%#v'", ptrRt)
- p := &SexpPointer{
- ReflectTarget: reftarg,
- Target: pointedTo,
- PointedToType: pointedToType,
- MyType: ptrRt,
- }
- return p
- }
- func (p *SexpPointer) SexpString(ps *PrintState) string {
- return fmt.Sprintf("%p", &p.Target)
- //return fmt.Sprintf("(* %v) %p", p.PointedToType.RegisteredName, p.Target)
- }
- func (p *SexpPointer) Type() *RegisteredType {
- return p.MyType
- }
- type SexpInt struct {
- Val int64
- Typ *RegisteredType
- }
- type SexpUint64 struct {
- Val uint64
- Typ *RegisteredType
- }
- type SexpBool struct {
- Val bool
- Typ *RegisteredType
- }
- type SexpFloat struct {
- Val float64
- Typ *RegisteredType
- Scientific bool
- }
- type SexpChar struct {
- Val rune
- Typ *RegisteredType
- }
- type SexpStr struct {
- S string
- backtick bool
- Typ *RegisteredType
- }
- func (r SexpStr) Type() *RegisteredType {
- return GoStructRegistry.Registry["string"]
- }
- func (r *SexpInt) Type() *RegisteredType {
- return GoStructRegistry.Registry["int64"]
- }
- func (r *SexpUint64) Type() *RegisteredType {
- return GoStructRegistry.Registry["uint64"]
- }
- func (r *SexpFloat) Type() *RegisteredType {
- return GoStructRegistry.Registry["float64"]
- }
- func (r *SexpBool) Type() *RegisteredType {
- return GoStructRegistry.Registry["bool"]
- }
- func (r *SexpChar) Type() *RegisteredType {
- return GoStructRegistry.Registry["int32"]
- }
- func (r *RegisteredType) Type() *RegisteredType {
- return r
- }
- type SexpRaw struct {
- Val []byte
- Typ *RegisteredType
- }
- func (r *SexpRaw) Type() *RegisteredType {
- return r.Typ
- }
- type SexpReflect struct {
- Val reflect.Value
- }
- func (r *SexpReflect) Type() *RegisteredType {
- k := reflectName(reflect.Value(r.Val))
- //Q("SexpReflect.Type() looking up type named '%s'", k)
- ty, ok := GoStructRegistry.Registry[k]
- if !ok {
- //Q("SexpReflect.Type(): type named '%s' not found", k)
- return nil
- }
- //Q("SexpReflect.Type(): type named '%s' found as regtype '%v'", k, ty.SexpString(nil))
- return ty
- }
- type SexpError struct {
- error
- }
- func (r *SexpError) Type() *RegisteredType {
- return GoStructRegistry.Registry["error"]
- }
- func (r *SexpSentinel) Type() *RegisteredType {
- return nil // TODO what should this be?
- }
- type SexpClosureEnv Scope
- func (r *SexpClosureEnv) Type() *RegisteredType {
- return nil // TODO what should this be?
- }
- func (c *SexpClosureEnv) SexpString(ps *PrintState) string {
- scop := (*Scope)(c)
- s, err := scop.Show(scop.env, ps, "")
- if err != nil {
- panic(err)
- }
- return s
- }
- type SexpSentinel struct {
- Val int
- }
- // these are values now so that they also have addresses.
- var SexpNull = &SexpSentinel{Val: 0}
- var SexpEnd = &SexpSentinel{Val: 1}
- var SexpMarker = &SexpSentinel{Val: 2}
- type SexpSemicolon struct{}
- type SexpComma struct{}
- func (r *SexpSemicolon) Type() *RegisteredType {
- return nil // TODO what should this be?
- }
- func (s *SexpSemicolon) SexpString(ps *PrintState) string {
- return ";"
- }
- func (r *SexpComma) Type() *RegisteredType {
- return nil // TODO what should this be?
- }
- func (s *SexpComma) SexpString(ps *PrintState) string {
- return ","
- }
- func (sent *SexpSentinel) SexpString(ps *PrintState) string {
- if sent == SexpNull {
- return "nil"
- }
- if sent == SexpEnd {
- return "End"
- }
- if sent == SexpMarker {
- return "Marker"
- }
- return ""
- }
- func Cons(a Sexp, b Sexp) *SexpPair {
- return &SexpPair{a, b}
- }
- func (pair *SexpPair) SexpString(ps *PrintState) string {
- str := "("
- for {
- switch pair.Tail.(type) {
- case *SexpPair:
- str += pair.Head.SexpString(ps) + " "
- pair = pair.Tail.(*SexpPair)
- continue
- }
- break
- }
- str += pair.Head.SexpString(ps)
- if pair.Tail == SexpNull {
- str += ")"
- } else {
- str += " \\ " + pair.Tail.SexpString(ps) + ")"
- }
- return str
- }
- func (r *SexpPair) Type() *RegisteredType {
- return nil // TODO what should this be?
- }
- type SexpArray struct {
- Val []Sexp
- Typ *RegisteredType
- IsFuncDeclTypeArray bool
- Infix bool
- Env *Zlisp
- }
- func (r *SexpArray) Type() *RegisteredType {
- if r.Typ == nil {
- if len(r.Val) > 0 {
- // take type from first element
- ty := r.Val[0].Type()
- if ty != nil {
- r.Typ = GoStructRegistry.GetOrCreateSliceType(ty)
- }
- } else {
- // empty array
- r.Typ = GoStructRegistry.Lookup("[]")
- //P("lookup [] returned type %#v", r.Typ)
- }
- }
- return r.Typ
- }
- func (arr *SexpArray) SexpString(ps *PrintState) string {
- indInner := ""
- indent := ps.GetIndent()
- innerPs := ps.AddIndent(4) // generates a fresh new PrintState
- inner := indent + 4
- //prettyEnd := ""
- pretty := false
- if arr != nil && arr.Env != nil && arr.Env.Pretty {
- pretty = true
- //prettyEnd = "\n"
- indInner = strings.Repeat(" ", inner)
- ps = innerPs
- }
- opn := "["
- cls := "]"
- if arr.Infix {
- opn = "{"
- cls = "}"
- }
- if pretty {
- opn += "\n"
- indInner = strings.Repeat(" ", inner)
- }
- if len(arr.Val) == 0 {
- return opn + cls
- }
- ta := arr.IsFuncDeclTypeArray
- str := opn
- for i, sexp := range arr.Val {
- str += indInner + sexp.SexpString(ps)
- if ta && i%2 == 0 {
- str += ":"
- } else {
- str += " "
- }
- }
- m := len(str)
- str = str[:m-1] + indInner + cls
- return str
- }
- func (e *SexpError) SexpString(ps *PrintState) string {
- return e.error.Error()
- }
- type EmbedPath struct {
- ChildName string
- ChildFieldNum int
- }
- func GetEmbedPath(e []EmbedPath) string {
- r := ""
- last := len(e) - 1
- for i, s := range e {
- r += s.ChildName
- if i < last {
- r += ":"
- }
- }
- return r
- }
- type HashFieldDet struct {
- FieldNum int
- FieldType reflect.Type
- StructField reflect.StructField
- FieldName string
- FieldJsonTag string
- EmbedPath []EmbedPath // we are embedded if len(EmbedPath) > 0
- }
- type SexpHash struct {
- TypeName string
- Map map[int][]*SexpPair
- KeyOrder []Sexp
- GoStructFactory *RegisteredType
- NumKeys int
- GoMethods []reflect.Method
- GoFields []reflect.StructField
- GoMethSx SexpArray
- GoFieldSx SexpArray
- GoType reflect.Type
- NumMethod int
- GoShadowStruct interface{}
- GoShadowStructVa reflect.Value
- ShadowSet bool
- // json tag name -> pointers to example values, as factories for SexpToGoStructs()
- JsonTagMap map[string]*HashFieldDet
- DetOrder []*HashFieldDet
- // for using these as a scoping model
- DefnEnv *SexpHash
- SuperClass *SexpHash
- ZMain SexpFunction
- ZMethods map[string]*SexpFunction
- Env *Zlisp
- }
- var MethodNotFound = fmt.Errorf("method not found")
- func (h *SexpHash) RunZmethod(method string, args []Sexp) (Sexp, error) {
- f, ok := (h.ZMethods)[method]
- if !ok {
- return SexpNull, MethodNotFound
- }
- panic(fmt.Errorf("not done calling %s", f.name))
- //return SexpNull, nil
- }
- func CallZMethodOnRecordFunction(env *Zlisp, name string, args []Sexp) (Sexp, error) {
- narg := len(args)
- if narg < 2 {
- return SexpNull, WrongNargs
- }
- var hash *SexpHash
- switch h := args[0].(type) {
- case *SexpHash:
- hash = h
- default:
- return SexpNull, fmt.Errorf("can only _call on a record")
- }
- method := ""
- switch s := args[1].(type) {
- case *SexpSymbol:
- method = s.name
- case *SexpStr:
- method = s.S
- default:
- return SexpNull, fmt.Errorf("can only _call with a " +
- "symbol or string as the method name. example: (_call record method:)")
- }
- return hash.RunZmethod(method, args[2:])
- }
- func (h *SexpHash) SetMain(p *SexpFunction) {
- h.BindSymbol(h.Env.MakeSymbol(".main"), p)
- }
- func (h *SexpHash) SetDefnEnv(p *SexpHash) {
- h.DefnEnv = p
- h.BindSymbol(h.Env.MakeSymbol(".parent"), p)
- }
- func (h *SexpHash) Lookup(env *Zlisp, key Sexp) (expr Sexp, err error) {
- return h.HashGet(env, key)
- }
- func (h *SexpHash) BindSymbol(key *SexpSymbol, val Sexp) error {
- return h.HashSet(key, val)
- }
- func (h *SexpHash) SetGoStructFactory(factory *RegisteredType) {
- h.GoStructFactory = factory
- }
- var SexpIntSize = 64
- var SexpFloatSize = 64
- func (r *SexpReflect) SexpString(ps *PrintState) string {
- //Q("in SexpReflect.SexpString(indent); top; type = %T", r)
- if reflect.Value(r.Val).Type().Kind() == reflect.Ptr {
- iface := reflect.Value(r.Val).Interface()
- switch iface.(type) {
- case *string:
- return fmt.Sprintf("`%v`", reflect.Value(r.Val).Elem().Interface())
- default:
- return fmt.Sprintf("%v", reflect.Value(r.Val).Elem().Interface())
- }
- }
- iface := reflect.Value(r.Val).Interface()
- //Q("in SexpReflect.SexpString(indent); type = %T", iface)
- switch iface.(type) {
- default:
- return fmt.Sprintf("%v", iface)
- }
- }
- func (b *SexpBool) SexpString(ps *PrintState) string {
- if bool(b.Val) {
- return "true"
- }
- return "false"
- }
- func (i *SexpInt) SexpString(ps *PrintState) string {
- return strconv.Itoa(int(i.Val))
- }
- func (i *SexpUint64) SexpString(ps *PrintState) string {
- return strconv.FormatUint(i.Val, 10) + "ULL"
- }
- func (f *SexpFloat) SexpString(ps *PrintState) string {
- if f.Scientific {
- return strconv.FormatFloat(f.Val, 'e', -1, SexpFloatSize)
- }
- return strconv.FormatFloat(f.Val, 'f', -1, SexpFloatSize)
- }
- func (c *SexpChar) SexpString(ps *PrintState) string {
- return strconv.QuoteRune(c.Val)
- }
- func (s *SexpStr) SexpString(ps *PrintState) string {
- if s.backtick {
- return "`" + s.S + "`"
- }
- return strconv.Quote(string(s.S))
- }
- func (r *SexpRaw) SexpString(ps *PrintState) string {
- return fmt.Sprintf("%#v", []byte(r.Val))
- }
- type SexpSymbol struct {
- name string
- number int
- isDot bool
- isSigil bool
- colonTail bool
- sigil string
- }
- func (sym *SexpSymbol) RHS(env *Zlisp) (Sexp, error) {
- if sym.isDot && env != nil {
- return dotGetSetHelper(env, sym.name, nil)
- }
- return sym, nil
- }
- func (sym *SexpSymbol) AssignToSelection(env *Zlisp, rhs Sexp) error {
- if sym.isDot && env != nil {
- _, err := dotGetSetHelper(env, sym.name, &rhs)
- return err
- }
- panic("not implemented yet")
- }
- func (sym *SexpSymbol) SexpString(ps *PrintState) string {
- if sym.colonTail {
- // return sym.name + ":"
- }
- return sym.name
- }
- func (r *SexpSymbol) Type() *RegisteredType {
- return GoStructRegistry.Registry["symbol"]
- }
- func (sym SexpSymbol) Name() string {
- return sym.name
- }
- func (sym SexpSymbol) Number() int {
- return sym.number
- }
- // SexpInterfaceDecl
- type SexpInterfaceDecl struct {
- name string
- methods []*SexpFunction
- }
- func (r *SexpInterfaceDecl) SexpString(ps *PrintState) string {
- indent := ps.GetIndent()
- space := strings.Repeat(" ", indent)
- space4 := strings.Repeat(" ", indent+4)
- s := space + "(interface " + r.name + " ["
- if len(r.methods) > 0 {
- s += "\n"
- }
- for i := range r.methods {
- s += space4 + r.methods[i].SexpString(ps.AddIndent(4)) + "\n"
- }
- s += space + "])"
- return s
- }
- func (r *SexpInterfaceDecl) Type() *RegisteredType {
- // todo: how to register/what to register?
- return GoStructRegistry.Registry[r.name]
- }
- // SexpFunction
- type SexpFunction struct {
- name string
- user bool
- nargs int
- varargs bool
- fun ZlispFunction
- userfun ZlispUserFunction
- orig Sexp
- closingOverScopes *Closing
- parent *SexpFunction
- isBuilder bool // see defbuild; builders are builtins that receive un-evaluated expressions
- inputTypes *SexpHash
- returnTypes *SexpHash
- hasBody bool // could just be declaration in an interface, without a body
- }
- func (sf *SexpFunction) Type() *RegisteredType {
- return nil // TODO what goes here
- }
- func (sf *SexpFunction) Copy() *SexpFunction {
- cp := *sf
- return &cp
- }
- func (sf *SexpFunction) SetClosing(clos *Closing) {
- ps4 := NewPrintStateWithIndent(4)
- pre, err := sf.ShowClosing(clos.env, ps4, "prev")
- _ = pre
- panicOn(err)
- newnew, err := sf.ShowClosing(clos.env, ps4, "newnew")
- _ = newnew
- panicOn(err)
- //P("99999 for sfun = %p, in sfun.SetClosing(), prev value is %p = '%s'\n",
- // sf, sf.closingOverScopes, pre)
- //P("88888 in sfun.SetClosing(), new value is %p = '%s'\n", clos, newnew)
- sf.closingOverScopes = clos
- //P("in SetClosing() for '%s'/%p: my stack is: '%s'", sf.name, sf, clos.Stack.SexpString(nil))
- }
- func (sf *SexpFunction) ShowClosing(env *Zlisp, ps *PrintState, label string) (string, error) {
- if sf.closingOverScopes == nil {
- return sf.name + " has no captured scopes.", nil
- }
- return sf.closingOverScopes.Show(env, ps, label)
- }
- func (sf *SexpFunction) ClosingLookupSymbolUntilFunction(sym *SexpSymbol) (Sexp, error, *Scope) {
- if sf.closingOverScopes != nil {
- return sf.closingOverScopes.LookupSymbolUntilFunction(sym, nil, 1, false)
- }
- return SexpNull, SymNotFound, nil
- }
- func (sf *SexpFunction) ClosingLookupSymbol(sym *SexpSymbol, setVal *Sexp) (Sexp, error, *Scope) {
- if sf.closingOverScopes != nil {
- return sf.closingOverScopes.LookupSymbol(sym, setVal)
- }
- //P("sf.closingOverScopes was nil, no captured scopes. sf = '%v'", sf.SexpString(nil))
- return SexpNull, SymNotFound, nil
- }
- // chase parent pointers up the chain and check each of their immediate closures.
- func (sf *SexpFunction) LookupSymbolInParentChainOfClosures(sym *SexpSymbol, setVal *Sexp, env *Zlisp) (Sexp, error, *Scope) {
- cur := sf
- par := sf.parent
- for par != nil {
- //fmt.Printf(" parent chain: cur:%v -> parent:%v\n", cur.name, par.name)
- //fmt.Printf(" cur.closures = %s", ClosureToString(cur, env))
- exp, err, scope := cur.ClosingLookupSymbolUntilFunc(sym, setVal, 1, false)
- if err == nil {
- //P("LookupSymbolInParentChainOfClosures(sym='%s') found in scope '%s'\n", sym.name, scope.Name)
- return exp, err, scope
- }
- cur = par
- par = par.parent
- }
- return SexpNull, SymNotFound, nil
- }
- func (sf *SexpFunction) ClosingLookupSymbolUntilFunc(sym *SexpSymbol, setVal *Sexp, maximumFuncToSearch int, checkCaptures bool) (Sexp, error, *Scope) {
- if sf.closingOverScopes != nil {
- return sf.closingOverScopes.LookupSymbolUntilFunction(sym, setVal, maximumFuncToSearch, checkCaptures)
- }
- //P("sf.closingOverScopes was nil, no captured scopes. sf = '%v'", sf.SexpString(nil))
- return SexpNull, SymNotFound, nil
- }
- func (sf *SexpFunction) SexpString(ps *PrintState) string {
- if sf.orig == nil {
- return "fn [" + sf.name + "]"
- }
- return sf.orig.SexpString(ps)
- }
- func IsTruthy(expr Sexp) bool {
- switch e := expr.(type) {
- case *SexpBool:
- return e.Val
- case *SexpInt:
- return e.Val != 0
- case *SexpUint64:
- return e.Val != 0
- case *SexpChar:
- return e.Val != 0
- case *SexpSentinel:
- return e != SexpNull
- }
- return true
- }
- type SexpStackmark struct {
- sym *SexpSymbol
- }
- func (r *SexpStackmark) Type() *RegisteredType {
- return nil // TODO what should this be?
- }
- func (mark *SexpStackmark) SexpString(ps *PrintState) string {
- return "stackmark " + mark.sym.name
- }
|