go-scopes/forge/rep/rep.go

90 lines
1.7 KiB
Go

// Package rep implements representations of Forge code - internal ones
// as slices and maps and corresponding external ones using serialization
// formats like JSON and YAML.
package rep
import (
"fmt"
"strings"
"git.sr.ht/~cco/go-scopes/common/voc"
"git.sr.ht/~cco/go-scopes/forge"
"git.sr.ht/~cco/go-scopes/logging/log"
)
// may be: code, module, string, int, float
type citem interface{}
type coderep interface {
Compile(forge.FE) forge.FPtr
}
// code, represented by a slice
type code []citem
func Code(items ...citem) code {
return code(items)
}
func (ci code) Compile(f forge.FE) forge.FPtr {
c := f.Code()
for _, item := range ci {
switch i := item.(type) {
case int:
c.Append(i)
case float64:
c.Append(int(i))
case string:
if v, err := compStr(f, i); err == nil {
c.Append(v)
} else {
log.Error(err).Msg("rep.Compile")
}
case code:
c.Append(i.Compile(f))
case []interface{}:
c.Append(makeCode(i).Compile(f))
case module:
c.Append(i.Compile(f))
case map[string]interface{}:
c.Append(makeModule(i).Compile(f))
}
}
return c.Reset()
}
func compStr(f forge.FE, s string) (forge.FItem, error) {
if strings.HasPrefix(s, "'") {
return forge.FItem(strings.Trim(s, "'")), nil
}
if v, ok := f.Voc().Lookup(s); ok {
return forge.FItem(v), nil
}
return nil, fmt.Errorf("not found: '%s'", s)
}
func makeCode(ri []interface{}) code {
c := code{}
for _, it := range ri {
c = append(c, it)
}
return c
}
// module - code definitions, represented by a map
type module map[string]citem
func (m module) Compile(f forge.FE) forge.FPtr {
v := voc.NewVoc(f.Voc())
return f.Code(v)
}
func makeModule(ri map[string]interface{}) module {
m := module{}
for k, v := range ri {
m[k] = v
}
return m
}