1
0
forked from x/icebergs
icebergs/base/yac/type.go
2023-04-23 12:06:58 +08:00

237 lines
4.4 KiB
Go

package yac
import (
"strings"
ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/lex"
kit "shylinux.com/x/toolkits"
)
type Map struct {
value Any
key Any
}
type Slice struct {
value Any
}
type Interface struct {
index map[string]Function
sups []string
name string
stack *Stack
}
type Struct struct {
index map[string]Any
sups []string
name string
stack *Stack
Position
}
type Fields []Field
type Field struct {
types Any
name string
tags map[string]string
}
type Object struct {
value Operater
index Struct
}
func (s Fields) For(cb func(Field)) {
for _, v := range s {
cb(v)
}
}
func (s Field) MarshalJSON() ([]byte, error) {
return []byte(kit.Format("%q", s.Format())), nil
}
func (s Field) Format() string {
if types := ""; len(s.tags) == 0 {
switch t := s.types.(type) {
case string:
types = t
default:
types = Format(s.types)
}
return types
} else {
res := []string{}
kit.For(s.tags, func(k, v string) { res = append(res, kit.Format("%s:\"%s\"", k, v)) })
return kit.Format("%s `%s`", types, strings.Join(res, lex.SP))
}
}
func (s Function) Operate(op string, v Any) Any {
switch op {
case "==":
switch v := v.(type) {
case Function:
if len(s.arg) != len(v.arg) {
return false
}
if len(s.res) != len(v.res) {
return false
}
for i, field := range v.arg {
if s.arg[i].types == field.types {
continue
}
return false
}
for i, field := range v.res {
if s.res[i].types == field.types {
continue
}
return false
}
return true
default:
return ErrNotSupport(v)
}
default:
return ErrNotImplement(op)
}
}
func (s Struct) For(cb func(k string, v Any)) {
kit.For(s.index, cb)
kit.For(s.sups, func(sup string) {
if sup, ok := s.stack.value(ice.Pulse, sup).(Struct); ok {
sup.For(cb)
}
})
}
func (s Struct) Find(k string) Any {
if v, ok := s.index[k]; ok {
return v
}
for _, sup := range s.sups {
if sup, ok := s.stack.value(ice.Pulse, sup).(Struct); ok {
if v := sup.Find(k); v != nil {
return v
}
}
}
return ErrNotFound(k)
}
func (s Struct) Operate(op string, v Any) Any {
switch op {
case "==":
switch v := v.(type) {
case Struct:
return Boolean{s.name == v.name}
default:
return ErrNotSupport(v)
}
default:
return ErrNotImplement(op)
}
}
func (s Object) Operate(op string, v Any) Any {
switch op {
case "&", "*":
return s
case INSTANCEOF:
if t, ok := v.(Struct); ok {
return Value{list: []Any{s, Boolean{s.index.name == t.name}}}
}
return ErrNotSupport(v)
case IMPLEMENTS:
if t, ok := v.(Interface); ok {
for k, v := range t.index {
if v.Operate("==", s.index.Find(k)) == false {
return Value{list: []Any{s, Boolean{false}}}
}
}
return Value{list: []Any{s, Boolean{true}}}
}
return ErrNotSupport(v)
case SUBS:
switch v := s.index.Find(kit.Format(v)).(type) {
case string:
switch _v := s.value.Operate(op, v).(type) {
case nil:
return Object{Dict{kit.Dict()}, s.index.stack.value(ice.Pulse, v).(Struct)}
default:
return _v
}
case Function:
v.object = s
return v
}
fallthrough
default:
return s.value.Operate(op, v)
}
}
const (
MAP = "map"
SLICE = "slice"
STRUCT = "struct"
INTERFACE = "interface"
STRING = "string"
BOOL = "bool"
INT = "int"
INSTANCEOF = "instanceof"
IMPLEMENTS = "implements"
CONST = "const"
TYPE = "type"
VAR = "var"
)
func init() {
Index.MergeCommands(ice.Commands{
CONST: {Name: "const a = 1", Hand: func(m *ice.Message, arg ...string) {
if s := _parse_stack(m); s.next(m) == OPEN {
for s.token() != CLOSE {
s.nextLine(m)
s.skip--
s.cals(m, CLOSE)
}
} else {
s.skip--
s.cals(m)
}
}},
TYPE: {Name: "type student struct {", Hand: func(m *ice.Message, arg ...string) {
s := _parse_stack(m)
pos := s.Position
switch name := s.next(m); s.next(m) {
case ASSIGN:
s.next(m)
fallthrough
default:
switch t := s.types(m).(type) {
case Interface:
t.name = name
t.stack = s
s.value(m, name, t)
case Struct:
t.name = name
t.stack = s
t.Position = pos
s.value(m, name, t)
default:
s.value(m, name, t)
}
}
}},
VAR: {Name: "var a = 1", Hand: func(m *ice.Message, arg ...string) {
if s := _parse_stack(m); s.next(m) == OPEN {
for s.token() != CLOSE {
s.nextLine(m)
s.skip--
s.cals(m, CLOSE)
}
} else {
s.skip--
s.cals(m)
}
}},
})
}