1
0
Эх сурвалжийг харах

приступил к новому стеку данных

kpmy 10 жил өмнө
parent
commit
b51f6257cc

+ 116 - 0
rt2/rules2/wrap/data/items/items.go

@@ -0,0 +1,116 @@
+package items
+
+import (
+	"container/list"
+	"ypk/assert"
+	"ypk/halt"
+)
+
+type Key interface {
+	EqualTo(Key) int
+}
+
+type Value interface {
+	KeyOf(...Key) Key
+}
+
+type Link interface {
+	To() Key
+	Value
+}
+
+type Item interface {
+	Data(...interface{}) interface{}
+	Value
+	Copy(Item)
+}
+
+type Data interface {
+	Set(Key, Item)
+	Link(Key, Key)
+	Get(Key) Item
+	Limit()
+	Drop()
+}
+
+func New() Data {
+	return &data{x: list.New()}
+}
+
+type data struct {
+	x *list.List
+}
+
+func (d *data) find(k Key, from *list.Element) (ret Value, elem *list.Element) {
+	if from == nil {
+		from = d.x.Front()
+	}
+	for x := from; x != nil && ret == nil; x = x.Next() {
+		if v, ok := x.Value.(Value); ok {
+			if z := v.KeyOf().EqualTo(k); z == 0 {
+				ret = v
+			}
+		}
+	}
+	return
+}
+
+func (d *data) Set(k Key, v Item) {
+	assert.For(v != nil, 20)
+	assert.For(v.KeyOf() == nil, 21)
+	x, _ := d.find(k, nil)
+	if x == nil {
+		v.KeyOf(k)
+		d.x.PushFront(v)
+	} else {
+		halt.As(123)
+	}
+}
+
+func (d *data) Get(k Key) (ret Item) {
+	for x, e := d.find(k, nil); x != nil && ret == nil; {
+		switch v := x.(type) {
+		case nil: //do nothing
+		case Item:
+			ret = v
+		case Link:
+			x, e = d.find(v.To(), e)
+		}
+	}
+	return
+}
+
+type link struct {
+	k, t Key
+}
+
+func (l *link) KeyOf(k ...Key) Key {
+	if len(k) == 1 {
+		l.k = k[0]
+	}
+	return l.k
+}
+
+func (l *link) To() Key {
+	return l.t
+}
+
+func (d *data) Link(key Key, to Key) {
+	v, _ := d.find(key, nil)
+	if v == nil {
+		d.x.PushFront(&link{k: key, t: to})
+	} else {
+		halt.As(123)
+	}
+}
+
+type limit struct{}
+type limit_key struct{}
+
+func (l *limit_key) EqualTo(Key) int { return -1 }
+func (l *limit) KeyOf(...Key) Key    { return &limit_key{} }
+
+func (d *data) Limit() { d.x.PushFront(&limit{}) }
+func (d *data) Drop() {
+	panic(0)
+}

+ 18 - 0
rt2/rules2/wrap/data/level.go

@@ -0,0 +1,18 @@
+package data
+
+import (
+	"fw/cp"
+	"fw/cp/node"
+	"fw/rt2/scope"
+)
+
+type level struct {
+	root   node.Node
+	k      map[cp.ID]int
+	v      map[int]scope.Variable
+	r      map[int]scope.Ref
+	l      map[int]*level
+	next   int
+	ready  bool
+	nested bool
+}

+ 72 - 0
rt2/rules2/wrap/data/stack.go

@@ -0,0 +1,72 @@
+package data
+
+import (
+	"fw/cp"
+	"fw/cp/node"
+	"fw/cp/object"
+	"fw/rt2/context"
+	"fw/rt2/scope"
+	"reflect"
+	"ypk/halt"
+)
+
+type area struct {
+	d   context.Domain
+	all scope.Allocator
+}
+
+type salloc struct {
+	area *area
+}
+
+func (a *area) Select(id cp.ID, val scope.ValueOf) {}
+
+func (a *salloc) Join(m scope.Manager) { a.area = m.(*area) }
+
+func (a *area) Target(all ...scope.Allocator) scope.Allocator {
+	if len(all) > 0 {
+		a.all = all[0]
+	}
+	if a.all == nil {
+		return &salloc{area: a}
+	} else {
+		a.all.Join(a)
+		return a.all
+	}
+}
+
+func (a *area) String() string { return "fixme" }
+
+func (a *area) Provide(x interface{}) scope.Value {
+	switch z := x.(type) {
+	case node.ConstantNode:
+		return newConst(z)
+	case object.ProcedureObject:
+		return newProc(z)
+	default:
+		halt.As(100, reflect.TypeOf(z))
+	}
+	panic(0)
+}
+
+func (a *area) Init(d context.Domain) { a.d = d }
+
+func (a *area) Domain() context.Domain { return a.d }
+
+func (a *area) Handle(msg interface{}) {}
+
+func nn(role string) scope.Manager {
+	if role == context.SCOPE {
+		return &area{all: &salloc{}}
+	} else if role == context.HEAP {
+		//return &area{all: &halloc{}}
+		panic(0)
+	} else {
+		panic(0)
+	}
+}
+
+func init() {
+	scope.New = nn
+	//scope.FindObjByName = fn
+}

+ 1874 - 0
rt2/rules2/wrap/data/val.go

@@ -0,0 +1,1874 @@
+package data
+
+import (
+	"fmt"
+	"fw/cp"
+	"fw/cp/node"
+	"fw/cp/object"
+	//	rtm "fw/rt2/module"
+	"fw/rt2/scope"
+	"fw/utils"
+	"math"
+	"math/big"
+	"reflect"
+	"strings"
+	"ypk/assert"
+	"ypk/halt"
+)
+
+type data struct {
+	link object.Object
+	val  interface{}
+}
+
+type arr struct {
+	link   object.Object
+	val    []interface{}
+	length int64
+}
+
+type dynarr struct {
+	link object.Object
+	val  []interface{}
+}
+
+type proc struct {
+	link object.Object
+}
+
+type rec struct {
+	link object.Object
+	scope.Record
+	l *level
+}
+
+type ptr struct {
+	link object.Object
+	scope.Pointer
+	val *ptrValue
+}
+
+type idx struct {
+	some scope.Array
+	idx  int
+}
+
+func (i *idx) link() object.Object {
+	switch a := i.some.(type) {
+	case *arr:
+		return a.link
+	case *dynarr:
+		return a.link
+	default:
+		panic(0)
+	}
+}
+
+func (i *idx) base() (object.Type, object.ComplexType) {
+	switch a := i.link().Complex().(type) {
+	case object.ArrayType:
+		return a.Base(), a.Complex()
+	case object.DynArrayType:
+		return a.Base(), nil
+	default:
+		panic(0)
+	}
+}
+
+func (i *idx) val() []interface{} {
+	switch a := i.some.(type) {
+	case *arr:
+		return a.val
+	case *dynarr:
+		return a.val
+	default:
+		panic(0)
+	}
+}
+
+func (r *rec) String() string {
+	return r.link.Name()
+}
+
+func (r *rec) Id() cp.ID {
+	return r.link.Adr()
+}
+
+func (r *rec) Set(v scope.Value) {
+	panic(0)
+}
+
+func (r *rec) Get(id cp.ID) scope.Value {
+	k := r.l.k[id]
+	if r.l.v[k] == nil { //ref
+		//fmt.Println(r.Id(), id)
+		assert.For(r.l.r[k] != nil, 20, id, k)
+		return r.l.r[k]
+	} else {
+		return r.l.v[k]
+	}
+}
+
+func newRec(o object.Object) *rec {
+	_, ok := o.Complex().(object.RecordType)
+	assert.For(ok, 20)
+	return &rec{link: o}
+}
+
+func (p *proc) String() string {
+	return fmt.Sprint(p.link.Adr(), p.link.Name())
+}
+
+func (x *data) Id() cp.ID { return x.link.Adr() }
+
+func (x *arr) Id() cp.ID { return x.link.Adr() }
+
+func (x *dynarr) Id() cp.ID { return x.link.Adr() }
+
+func (a *arr) Set(v scope.Value) {
+	switch x := v.(type) {
+	case *arr:
+		a.Set(STRING(x.tryString()))
+	case STRING:
+		v := make([]interface{}, int(a.length))
+		for i := 0; i < int(a.length) && i < len(x); i++ {
+			v[i] = CHAR(x[i])
+		}
+		a.val = v
+	case SHORTSTRING:
+		v := make([]interface{}, int(a.length))
+		for i := 0; i < int(a.length) && i < len(x); i++ {
+			v[i] = SHORTCHAR(x[i])
+		}
+		a.val = v
+	default:
+		halt.As(100, reflect.TypeOf(x))
+	}
+}
+
+func (a *dynarr) Set(v scope.Value) {
+	switch x := v.(type) {
+	case *data:
+		a.Set(vfrom(x))
+	case *arr:
+		a.val = x.val
+	case *dynarr:
+		a.val = x.val
+	case *idx:
+		a.Set(x.Get())
+	case STRING:
+		z := []rune(string(x))
+		v := make([]interface{}, len(z)+1)
+		for i := 0; i < len(z); i++ {
+			v[i] = CHAR(z[i])
+		}
+		if len(v) > 1 {
+			v[len(v)-1] = CHAR(0)
+		}
+		a.val = v
+	case SHORTSTRING:
+		z := []rune(string(x))
+		v := make([]interface{}, len(z)+1)
+		for i := 0; i < len(z); i++ {
+			v[i] = SHORTCHAR(z[i])
+		}
+		if len(v) > 0 {
+			v[len(v)-1] = SHORTCHAR(0)
+		}
+		a.val = v
+	case INTEGER:
+		a.val = make([]interface{}, int(x))
+	default:
+		halt.As(100, reflect.TypeOf(x))
+	}
+}
+
+func (a *arr) tryString() (ret string) {
+	stop := false
+	for i := 0; !stop && i < len(a.val) && a.val[i] != nil; i++ {
+		switch x := a.val[i].(type) {
+		case CHAR:
+			stop = int(x) == 0
+			if !stop {
+				ret = fmt.Sprint(ret, string([]rune{rune(x)}))
+			}
+		case SHORTCHAR:
+			stop = int(x) == 0
+			if !stop {
+				ret = fmt.Sprint(ret, string([]rune{rune(x)}))
+			}
+		default:
+			halt.As(100, reflect.TypeOf(x))
+		}
+	}
+	return ret
+}
+
+func (a *arr) String() (ret string) {
+	ret = fmt.Sprint("array", "[", a.length, "]")
+	for i := 0; i < len(a.val) && a.val[i] != nil; i++ {
+		switch x := a.val[i].(type) {
+		case CHAR:
+			ret = fmt.Sprint(ret, string([]rune{rune(x)}))
+		case SHORTCHAR:
+			ret = fmt.Sprint(ret, string([]rune{rune(x)}))
+		case REAL:
+			ret = fmt.Sprint(ret, ", ", x)
+		case *ptr:
+			ret = fmt.Sprintln(ret, ", ", x)
+		default:
+			halt.As(100, reflect.TypeOf(x))
+		}
+	}
+	return ret
+}
+
+//возвращает *idx
+func (a *arr) Get(id scope.Value) scope.Value {
+	switch i := id.(type) {
+	case *data:
+		return a.Get(i.val.(scope.Value))
+	case INTEGER:
+		assert.For(int64(i) < a.length, 20)
+		if len(a.val) == 0 {
+			a.val = make([]interface{}, int(a.length))
+		}
+		return &idx{some: a, idx: int(i)}
+	default:
+		halt.As(100, reflect.TypeOf(i))
+	}
+	panic(0)
+}
+
+//возвращает *idx
+func (a *dynarr) Get(id scope.Value) scope.Value {
+	switch i := id.(type) {
+	case *data:
+		return a.Get(i.val.(scope.Value))
+	case INTEGER:
+		assert.For(int(i) < len(a.val), 20)
+		if len(a.val) == 0 {
+			panic(0)
+		}
+		return &idx{some: a, idx: int(i)}
+	default:
+		halt.As(100, reflect.TypeOf(i))
+	}
+	panic(0)
+}
+
+func (i *idx) Id() cp.ID {
+	return i.some.Id()
+}
+
+func (i *idx) String() string {
+	return fmt.Sprint("@", i.Id(), "[", i.idx, "]")
+}
+
+func (i *idx) Set(v scope.Value) {
+	t := i.link().Complex()
+	switch x := v.(type) {
+	case *idx:
+		var comp object.Type = object.NOTYPE
+		switch xt := x.link().Complex().(type) {
+		case object.ArrayType:
+			comp = xt.Base()
+		case object.DynArrayType:
+			comp = xt.Base()
+		default:
+			halt.As(100, xt)
+		}
+		if comp != object.COMPLEX {
+			i.val()[i.idx] = x.val()[x.idx]
+		} else {
+			switch z := x.val()[x.idx].(type) {
+			case *arr:
+				t := z.link.Complex().(object.ArrayType).Base()
+				switch t {
+				case object.CHAR:
+					i.val()[i.idx].(*arr).Set(STRING(z.tryString()))
+				default:
+					halt.As(100, t)
+				}
+			default:
+				halt.As(100, reflect.TypeOf(z))
+			}
+		}
+	case *data:
+		i.Set(x.val.(scope.Value))
+	case CHAR:
+		i.val()[i.idx] = x
+	case STRING:
+		_ = t.(object.ArrayType)
+		i.val()[i.idx].(*arr).Set(x)
+	case REAL:
+		i.val()[i.idx] = x
+	case *ptrValue:
+		switch tt := t.(type) {
+		case object.DynArrayType:
+			_, ok := tt.Complex().(object.PointerType)
+			assert.For(ok, 20)
+			i.val()[i.idx] = &ptr{link: x.link, val: x}
+		default:
+			halt.As(100, reflect.TypeOf(tt))
+		}
+	default:
+		halt.As(100, reflect.TypeOf(x), x, t)
+	}
+}
+
+func (i *idx) Get() scope.Value {
+	x := i.val()[i.idx]
+	switch z := x.(type) {
+	case *arr:
+		return z
+	case *ptr:
+		return z
+	case CHAR:
+		return z
+	case nil:
+		b := i.link().Complex().(object.ArrayType).Base()
+		switch b {
+		case object.CHAR:
+			return CHAR(rune(0))
+		default:
+			halt.As(101, reflect.TypeOf(b))
+		}
+	default:
+		halt.As(100, i.idx, reflect.TypeOf(z))
+	}
+	panic(0)
+}
+
+func (a *dynarr) tryString() (ret string) {
+	stop := false
+	for i := 0; !stop && i < len(a.val) && a.val[i] != nil; i++ {
+		switch x := a.val[i].(type) {
+		case CHAR:
+			stop = int(x) == 0
+			if !stop {
+				ret = fmt.Sprint(ret, string([]rune{rune(x)}))
+			}
+		case SHORTCHAR:
+			stop = int(x) == 0
+			if !stop {
+				ret = fmt.Sprint(ret, string([]rune{rune(x)}))
+			}
+		default:
+			halt.As(100, reflect.TypeOf(x))
+		}
+	}
+	return ret
+}
+
+func (a *dynarr) String() (ret string) {
+	ret = fmt.Sprint("dyn array")
+	for i := 0; i < len(a.val) && a.val[i] != nil; i++ {
+		switch x := a.val[i].(type) {
+		case CHAR:
+			ret = fmt.Sprint(ret, string([]rune{rune(x)}))
+		case SHORTCHAR:
+			ret = fmt.Sprint(ret, string([]rune{rune(x)}))
+		case *ptr:
+			ret = fmt.Sprint(ret, ", ", x)
+		default:
+			halt.As(100, reflect.TypeOf(x))
+		}
+	}
+	return ret
+}
+
+func (d *data) Set(v scope.Value) {
+	utils.PrintScope("set data")
+	switch x := v.(type) {
+	case *data:
+		if d.link.Type() == x.link.Type() {
+			d.val = x.val
+		} else {
+			d.Set(x.val.(scope.Value))
+		}
+	case *proc:
+		assert.For(d.link.Type() == object.COMPLEX, 20)
+		t, ok := d.link.Complex().(object.BasicType)
+		assert.For(ok, 21, reflect.TypeOf(d.link.Complex()))
+		assert.For(t.Type() == object.PROCEDURE, 22)
+		d.val = x
+	case *idx:
+		d.val = x.val()[x.idx]
+	case INTEGER:
+		switch d.link.Type() {
+		case object.INTEGER:
+			d.val = x
+		case object.LONGINT:
+			d.val = LONGINT(x)
+		case object.REAL:
+			d.val = REAL(x)
+		default:
+			halt.As(20, d.link.Type())
+		}
+	case BOOLEAN:
+		assert.For(d.link.Type() == object.BOOLEAN, 20)
+		d.val = x
+	case SHORTCHAR:
+		assert.For(d.link.Type() == object.SHORTCHAR, 20)
+		d.val = x
+	case CHAR:
+		assert.For(d.link.Type() == object.CHAR, 20)
+		d.val = x
+	case SHORTINT:
+		assert.For(d.link.Type() == object.SHORTINT, 20)
+		d.val = x
+	case LONGINT:
+		assert.For(d.link.Type() == object.LONGINT, 20)
+		d.val = x
+	case BYTE:
+		assert.For(d.link.Type() == object.BYTE, 20)
+		d.val = x
+	case SET:
+		assert.For(d.link.Type() == object.SET, 20)
+		d.val = x
+	case REAL:
+		assert.For(d.link.Type() == object.REAL, 20)
+		d.val = x
+	case SHORTREAL:
+		assert.For(d.link.Type() == object.SHORTREAL, 20)
+		d.val = x
+	default:
+		panic(fmt.Sprintln(reflect.TypeOf(x)))
+	}
+}
+
+func (d *data) String() string {
+	return fmt.Sprint(d.link.Name(), "=", d.val)
+}
+
+func (p *ptr) String() string {
+	if p.link.Complex() != nil {
+		return fmt.Sprint("pointer ", p.link.Complex().(object.PointerType).Name(), "&", p.val)
+	} else {
+		return fmt.Sprint("pointer simple", p.link.Type())
+	}
+}
+
+func (p *ptr) Id() cp.ID { return p.link.Adr() }
+
+func (p *ptr) Set(v scope.Value) {
+	switch x := v.(type) {
+	case *ptr:
+		p.Set(x.val)
+	case *ptrValue:
+		p.val = x
+	case PTR:
+		assert.For(x == NIL, 40)
+		p.val = nil
+	default:
+		halt.As(100, reflect.TypeOf(x))
+	}
+}
+
+func (p *ptr) Get() scope.Value {
+	if p.val == nil {
+		return NIL
+	} else {
+		panic(0)
+		//return p.val.scope.Select(p.val.id)
+	}
+}
+
+func newPtr(o object.Object) scope.Variable {
+	_, ok := o.Complex().(object.PointerType)
+	assert.For(ok, 20)
+	return &ptr{link: o}
+}
+
+type ptrValue struct {
+	scope *area
+	id    cp.ID
+	link  object.Object
+}
+
+func (p *ptrValue) String() string {
+	return fmt.Sprint(p.id)
+}
+
+type PTR int
+
+func (p PTR) String() string {
+	return "NIL"
+}
+
+const NIL PTR = 0
+
+type INTEGER int32
+type BOOLEAN bool
+type BYTE int8
+type SHORTINT int16
+type LONGINT int64
+type SET struct {
+	bits *big.Int
+}
+type CHAR rune
+type REAL float64
+type SHORTREAL float32
+type SHORTCHAR rune
+type STRING string
+type SHORTSTRING string
+
+func (x SHORTSTRING) String() string { return string(x) }
+func (x STRING) String() string      { return string(x) }
+func (x SHORTCHAR) String() string   { return fmt.Sprint(rune(x)) }
+func (x SHORTREAL) String() string   { return fmt.Sprint(float32(x)) }
+func (x REAL) String() string        { return fmt.Sprint(float64(x)) }
+func (x CHAR) String() string        { return fmt.Sprint(rune(x)) }
+func (x SET) String() string         { return fmt.Sprint(x.bits) }
+func (x LONGINT) String() string     { return fmt.Sprint(int64(x)) }
+func (x SHORTINT) String() string    { return fmt.Sprint(int16(x)) }
+func (x BYTE) String() string        { return fmt.Sprint(int8(x)) }
+func (x INTEGER) String() string     { return fmt.Sprint(int32(x)) }
+func (x BOOLEAN) String() string     { return fmt.Sprint(bool(x)) }
+
+func newData(o object.Object) (ret scope.Variable) {
+	switch o.Type() {
+	case object.INTEGER:
+		ret = &data{link: o, val: INTEGER(0)}
+	case object.BOOLEAN:
+		ret = &data{link: o, val: BOOLEAN(false)}
+	case object.BYTE:
+		ret = &data{link: o, val: BYTE(0)}
+	case object.CHAR:
+		ret = &data{link: o, val: CHAR(0)}
+	case object.LONGINT:
+		ret = &data{link: o, val: LONGINT(0)}
+	case object.SHORTINT:
+		ret = &data{link: o, val: SHORTINT(0)}
+	case object.SET:
+		ret = &data{link: o, val: SET{bits: big.NewInt(0)}}
+	case object.REAL:
+		ret = &data{link: o, val: REAL(0)}
+	case object.SHORTREAL:
+		ret = &data{link: o, val: SHORTREAL(0)}
+	case object.SHORTCHAR:
+		ret = &data{link: o, val: SHORTCHAR(0)}
+	case object.COMPLEX:
+		switch t := o.Complex().(type) {
+		case object.BasicType:
+			switch t.Type() {
+			case object.PROCEDURE:
+				ret = &data{link: o, val: nil}
+			default:
+				halt.As(100, t.Type())
+			}
+		case object.ArrayType:
+			ret = &arr{link: o, length: t.Len()}
+			if a := ret.(*arr); t.Base() == object.COMPLEX {
+				a.val = make([]interface{}, int(t.Len()))
+				for i := 0; i < int(t.Len()); i++ {
+					fake := object.New(object.VARIABLE, cp.Some())
+					fake.SetName("[?]")
+					fake.SetType(object.COMPLEX)
+					fake.SetComplex(t.Complex())
+					a.val[i] = newData(fake)
+				}
+			}
+		case object.DynArrayType:
+			ret = &dynarr{link: o}
+		default:
+			halt.As(100, reflect.TypeOf(t))
+		}
+	case object.NOTYPE:
+		switch t := o.Complex().(type) {
+		case nil:
+			ret = &ptr{link: o}
+		default:
+			halt.As(100, reflect.TypeOf(t))
+		}
+	default:
+		panic(fmt.Sprintln("unsupported type", o, o.Type(), o.Complex()))
+	}
+	return ret
+}
+
+func fromg(x interface{}) scope.Value {
+	switch x := x.(type) {
+	case int32:
+		return INTEGER(x)
+	case bool:
+		return BOOLEAN(x)
+	case *big.Int:
+		return SET{bits: x}
+	case string:
+		return STRING(x)
+	case float64:
+		return REAL(x)
+	default:
+		halt.As(100, reflect.TypeOf(x))
+	}
+	panic(100)
+}
+
+func newProc(o object.Object) scope.Value {
+	p, ok := o.(object.ProcedureObject)
+	assert.For(ok, 20, reflect.TypeOf(o))
+	return &proc{link: p}
+}
+
+func newConst(n node.Node) scope.Value {
+	switch x := n.(type) {
+	case node.ConstantNode:
+		switch x.Type() {
+		case object.INTEGER:
+			return INTEGER(x.Data().(int32))
+		case object.REAL:
+			return REAL(x.Data().(float64))
+		case object.BOOLEAN:
+			return BOOLEAN(x.Data().(bool))
+		case object.SHORTCHAR:
+			return SHORTCHAR(x.Data().(rune))
+		case object.LONGINT:
+			return LONGINT(x.Data().(int64))
+		case object.SHORTINT:
+			return SHORTINT(x.Data().(int16))
+		case object.SHORTREAL:
+			return SHORTREAL(x.Data().(float32))
+		case object.BYTE:
+			return BYTE(x.Data().(int8))
+		case object.SET:
+			return SET{bits: x.Data().(*big.Int)}
+		case object.CHAR:
+			return CHAR(x.Data().(rune))
+		case object.STRING:
+			return STRING(x.Data().(string))
+		case object.SHORTSTRING:
+			return SHORTSTRING(x.Data().(string))
+		case object.NIL:
+			return NIL
+		case object.COMPLEX: //не может существовать в реальности, используется для передачи параметров от рантайма
+			switch d := x.Data().(type) {
+			case *ptrValue:
+				return d
+			default:
+				halt.As(100, reflect.TypeOf(d))
+			}
+		default:
+			panic(fmt.Sprintln(x.Type()))
+		}
+	}
+	panic(0)
+}
+
+func vfrom(v scope.Value) scope.Value {
+	switch n := v.(type) {
+	case *data:
+		switch n.link.Type() {
+		case object.INTEGER:
+			return n.val.(INTEGER)
+		case object.BYTE:
+			return n.val.(BYTE)
+		case object.CHAR:
+			return n.val.(CHAR)
+		case object.SET:
+			return n.val.(SET)
+		case object.BOOLEAN:
+			return n.val.(BOOLEAN)
+		case object.REAL:
+			return n.val.(REAL)
+		case object.LONGINT:
+			return n.val.(LONGINT)
+		default:
+			halt.As(100, n.link.Type())
+		}
+	case INTEGER, CHAR:
+		return n
+	default:
+		halt.As(100, reflect.TypeOf(n))
+	}
+	return nil
+}
+
+func gfrom(v scope.Value) interface{} {
+	switch n := v.(type) {
+	case *data:
+		if n.val == nil {
+			return nil
+		} else {
+			return gfrom(n.val.(scope.Value))
+		}
+	case *rec:
+		return n
+	case *ptr:
+		return n
+	case *proc:
+		return n.link
+	case *dynarr:
+		switch n.link.Complex().(object.DynArrayType).Base() {
+		case object.SHORTCHAR:
+			if n.val != nil {
+				return n.tryString()
+			} else {
+				return ""
+			}
+		case object.CHAR:
+			if n.val != nil {
+				return n.tryString()
+			} else {
+				return ""
+			}
+		case object.COMPLEX:
+			return n.val
+		default:
+			halt.As(100, n.link.Complex().(object.DynArrayType).Base())
+		}
+		panic(0)
+	case *arr:
+		switch n.link.Complex().(object.ArrayType).Base() {
+		case object.SHORTCHAR:
+			if n.val != nil {
+				return n.tryString()
+			} else {
+				return ""
+			}
+		case object.CHAR:
+			if n.val != nil {
+				return n.tryString()
+			} else {
+				return ""
+			}
+		case object.REAL:
+			ret := make([]float64, 0)
+			for i := 0; i < len(n.val) && n.val[i] != nil; i++ {
+				ret = append(ret, float64(n.val[i].(REAL)))
+			}
+			return ret
+		default:
+			halt.As(100, n.link.Complex().(object.ArrayType).Base())
+		}
+		panic(0)
+	case *idx:
+		switch t := n.link().Complex().(type) {
+		case object.ArrayType:
+			switch t.Base() {
+			case object.CHAR:
+				return rune(n.Get().(CHAR))
+			default:
+				halt.As(100, t.Base())
+			}
+		case object.DynArrayType:
+			switch t.Base() {
+			case object.CHAR:
+				return rune(n.Get().(CHAR))
+			default:
+				halt.As(100, t.Base())
+			}
+		default:
+			halt.As(100, reflect.TypeOf(t))
+		}
+		panic(0)
+	case PTR:
+		assert.For(n == NIL, 40)
+		return nil
+	case INTEGER:
+		return int32(n)
+	case BOOLEAN:
+		return bool(n)
+	case STRING:
+		return string(n)
+	case CHAR:
+		return rune(n)
+	default:
+		halt.As(100, reflect.TypeOf(n))
+	}
+	return nil
+}
+
+type ops struct{}
+
+func (o *ops) Sum(a, b scope.Value) scope.Value {
+	switch a.(type) {
+	case *data:
+		return o.Sum(vfrom(a), b)
+	default:
+		switch b.(type) {
+		case *data:
+			return o.Sum(a, vfrom(b))
+		default:
+			switch x := a.(type) {
+			case INTEGER:
+				switch y := b.(type) {
+				case INTEGER:
+					return INTEGER(int32(x) + int32(y))
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			case SET:
+				switch y := b.(type) {
+				case SET:
+					res := big.NewInt(0)
+					for i := 0; i < 64; i++ {
+						if x.bits.Bit(i) == 1 {
+							res.SetBit(res, i, 1)
+						}
+						if y.bits.Bit(i) == 1 {
+							res.SetBit(res, i, 1)
+						}
+					}
+					return SET{bits: res}
+				case INTEGER: // INCL(SET, INTEGER)
+					return SET{bits: x.bits.SetBit(x.bits, int(y), 1)}
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			case *arr:
+				switch y := b.(type) {
+				case *arr:
+					switch {
+					case x.link.Type() == y.link.Type() && x.link.Complex().(object.ArrayType).Base() == object.CHAR:
+						return STRING(x.tryString() + y.tryString())
+					default:
+						halt.As(100, x.link.Type(), y.link.Type())
+					}
+				case STRING:
+					switch {
+					case x.link.Complex().(object.ArrayType).Base() == object.CHAR:
+						return STRING(x.tryString() + string(y))
+					default:
+						halt.As(100, x.link.Type())
+					}
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			case *dynarr:
+				switch y := b.(type) {
+				case STRING:
+					switch {
+					case x.link.Complex().(object.DynArrayType).Base() == object.CHAR:
+						return STRING(x.tryString() + string(y))
+					default:
+						halt.As(100, x.link.Type())
+					}
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			case STRING:
+				switch y := b.(type) {
+				case STRING:
+					return STRING(string(x) + string(y))
+				default:
+					halt.As(100, reflect.TypeOf(y))
+				}
+			case REAL:
+				switch y := b.(type) {
+				case REAL:
+					return REAL(x + y)
+				default:
+					halt.As(100, reflect.TypeOf(y))
+				}
+			case LONGINT:
+				switch y := b.(type) {
+				case LONGINT:
+					return LONGINT(x + y)
+				default:
+					halt.As(100, reflect.TypeOf(y))
+				}
+			default:
+				panic(fmt.Sprintln(reflect.TypeOf(x)))
+			}
+		}
+	}
+	panic(0)
+}
+
+func (o *ops) Sub(a, b scope.Value) scope.Value {
+	switch a.(type) {
+	case *data:
+		return o.Sub(vfrom(a), b)
+	default:
+		switch b.(type) {
+		case *data:
+			return o.Sub(a, vfrom(b))
+		default:
+			switch x := a.(type) {
+			case INTEGER:
+				switch y := b.(type) {
+				case INTEGER:
+					return INTEGER(int32(x) - int32(y))
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			case REAL:
+				switch y := b.(type) {
+				case REAL:
+					return REAL(x - y)
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			case LONGINT:
+				switch y := b.(type) {
+				case LONGINT:
+					return INTEGER(int64(x) - int64(y))
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			case SET:
+				switch y := b.(type) {
+				case SET:
+					res := big.NewInt(0).Set(x.bits)
+					for i := 0; i < 64; i++ {
+						if y.bits.Bit(i) == 1 {
+							res.SetBit(res, i, 0)
+						}
+					}
+					return SET{bits: res}
+				case INTEGER:
+					null := big.NewInt(0)
+					res := null.SetBit(x.bits, int(y), 0)
+					return SET{bits: res}
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			default:
+				panic(fmt.Sprintln(reflect.TypeOf(x)))
+			}
+		}
+	}
+	panic(0)
+}
+
+func (o *ops) In(a, b scope.Value) scope.Value {
+	switch a.(type) {
+	case *data:
+		return o.In(vfrom(a), b)
+	default:
+		switch b.(type) {
+		case *data:
+			return o.In(a, vfrom(b))
+		default:
+			switch x := a.(type) {
+			case INTEGER:
+				switch y := b.(type) {
+				case SET:
+					assert.For(int(x) < 64, 20)
+					return BOOLEAN(y.bits.Bit(int(x)) == 1)
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			default:
+				panic(fmt.Sprintln(reflect.TypeOf(x)))
+			}
+		}
+	}
+	panic(0)
+}
+
+func (o *ops) Min(a, b scope.Value) scope.Value {
+	switch a.(type) {
+	case *data:
+		return o.Min(vfrom(a), b)
+	default:
+		switch b.(type) {
+		case *data:
+			return o.Min(a, vfrom(b))
+		default:
+			switch x := a.(type) {
+			case INTEGER:
+				switch y := b.(type) {
+				case INTEGER:
+					return INTEGER(int32(math.Min(float64(x), float64(y))))
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			default:
+				panic(fmt.Sprintln(reflect.TypeOf(x)))
+			}
+		}
+	}
+	panic(0)
+}
+
+func (o *ops) Max(a, b scope.Value) scope.Value {
+	switch a.(type) {
+	case *data:
+		return o.Max(vfrom(a), b)
+	default:
+		switch b.(type) {
+		case *data:
+			return o.Max(a, vfrom(b))
+		default:
+			switch x := a.(type) {
+			case INTEGER:
+				switch y := b.(type) {
+				case INTEGER:
+					return INTEGER(int32(math.Max(float64(x), float64(y))))
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			default:
+				panic(fmt.Sprintln(reflect.TypeOf(x)))
+			}
+		}
+	}
+	panic(0)
+}
+
+func (o *ops) And(a, b scope.Value) scope.Value {
+	switch a.(type) {
+	case *data:
+		return o.And(vfrom(a), b)
+	default:
+		switch b.(type) {
+		case *data:
+			return o.And(a, vfrom(b))
+		default:
+			switch x := a.(type) {
+			case BOOLEAN:
+				switch y := b.(type) {
+				case BOOLEAN:
+					return BOOLEAN(x && y)
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			default:
+				panic(fmt.Sprintln(reflect.TypeOf(x)))
+			}
+		}
+	}
+	panic(0)
+}
+
+func (o *ops) Or(a, b scope.Value) scope.Value {
+	switch a.(type) {
+	case *data:
+		return o.Or(vfrom(a), b)
+	default:
+		switch b.(type) {
+		case *data:
+			return o.Or(a, vfrom(b))
+		default:
+			switch x := a.(type) {
+			case BOOLEAN:
+				switch y := b.(type) {
+				case BOOLEAN:
+					return BOOLEAN(x || y)
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			default:
+				panic(fmt.Sprintln(reflect.TypeOf(x)))
+			}
+		}
+	}
+	panic(0)
+}
+
+func (o *ops) Ash(a, b scope.Value) scope.Value {
+	switch a.(type) {
+	case *data:
+		return o.Ash(vfrom(a), b)
+	default:
+		switch b.(type) {
+		case *data:
+			return o.Ash(a, vfrom(b))
+		default:
+			switch x := a.(type) {
+			case INTEGER:
+				switch y := b.(type) {
+				case INTEGER:
+					return INTEGER(x << uint(y))
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			default:
+				panic(fmt.Sprintln(reflect.TypeOf(x)))
+			}
+		}
+	}
+	panic(0)
+}
+
+func (o *ops) Div(a, b scope.Value) scope.Value {
+	switch a.(type) {
+	case *data:
+		return o.Div(vfrom(a), b)
+	default:
+		switch b.(type) {
+		case *data:
+			return o.Div(a, vfrom(b))
+		default:
+			switch x := a.(type) {
+			case INTEGER:
+				switch y := b.(type) {
+				case INTEGER:
+					return INTEGER(math.Floor(float64(x) / float64(y)))
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			case LONGINT:
+				switch y := b.(type) {
+				case LONGINT:
+					return LONGINT(x / y)
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			default:
+				panic(fmt.Sprintln(reflect.TypeOf(x)))
+			}
+		}
+	}
+	panic(0)
+}
+
+func (o *ops) Mod(a, b scope.Value) scope.Value {
+	switch a.(type) {
+	case *data:
+		return o.Mod(vfrom(a), b)
+	default:
+		switch b.(type) {
+		case *data:
+			return o.Mod(a, vfrom(b))
+		default:
+			switch x := a.(type) {
+			case INTEGER:
+				switch y := b.(type) {
+				case INTEGER:
+					z := x % y
+					switch {
+					case (x < 0) != (y < 0):
+						z = z + y
+					}
+					return INTEGER(z)
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			case LONGINT:
+				switch y := b.(type) {
+				case LONGINT:
+					z := x % y
+					switch {
+					case (x < 0) != (y < 0):
+						z = z + y
+					}
+					return LONGINT(z)
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			default:
+				panic(fmt.Sprintln(reflect.TypeOf(x)))
+			}
+		}
+	}
+	panic(0)
+}
+
+func (o *ops) Msk(a, b scope.Value) scope.Value {
+	switch a.(type) {
+	case *data:
+		return o.Msk(vfrom(a), b)
+	default:
+		switch b.(type) {
+		case *data:
+			return o.Msk(a, vfrom(b))
+		default:
+			switch x := a.(type) {
+			case INTEGER:
+				switch y := b.(type) {
+				case INTEGER:
+					y = -y
+					z := x % y
+					switch {
+					case (x < 0) != (y < 0):
+						z = z + y
+					}
+					return INTEGER(z)
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			case LONGINT:
+				switch y := b.(type) {
+				case LONGINT:
+					y = -y
+					z := x % y
+					switch {
+					case (x < 0) != (y < 0):
+						z = z + y
+					}
+					return LONGINT(z)
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			default:
+				panic(fmt.Sprintln(reflect.TypeOf(x)))
+			}
+		}
+	}
+	panic(0)
+}
+
+func (o *ops) Mult(a, b scope.Value) scope.Value {
+	switch a.(type) {
+	case *data:
+		return o.Mult(vfrom(a), b)
+	default:
+		switch b.(type) {
+		case *data:
+			return o.Mult(a, vfrom(b))
+		default:
+			switch x := a.(type) {
+			case INTEGER:
+				switch y := b.(type) {
+				case INTEGER:
+					return INTEGER(x * y)
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			case REAL:
+				switch y := b.(type) {
+				case REAL:
+					return REAL(x * y)
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			case SET:
+				switch y := b.(type) {
+				case SET:
+					res := big.NewInt(0)
+					for i := 0; i < 64; i++ {
+						if x.bits.Bit(i) == 1 && y.bits.Bit(i) == 1 {
+							res.SetBit(res, i, 1)
+						}
+					}
+					return SET{bits: res}
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			default:
+				panic(fmt.Sprintln(reflect.TypeOf(x)))
+			}
+		}
+	}
+	panic(0)
+}
+
+func (o *ops) Divide(a, b scope.Value) scope.Value {
+	switch a.(type) {
+	case *data:
+		return o.Divide(vfrom(a), b)
+	default:
+		switch b.(type) {
+		case *data:
+			return o.Divide(a, vfrom(b))
+		default:
+			switch x := a.(type) {
+			case INTEGER:
+				switch y := b.(type) {
+				case INTEGER:
+					return REAL(float64(x) / float64(y))
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			case REAL:
+				switch y := b.(type) {
+				case REAL:
+					return REAL(float64(x) / float64(y))
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			case SET:
+				switch y := b.(type) {
+				case SET:
+					res := big.NewInt(0)
+					for i := 0; i < 64; i++ {
+						if x.bits.Bit(i) != y.bits.Bit(i) {
+							res.SetBit(res, i, 1)
+						}
+					}
+					return SET{bits: res}
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			default:
+				panic(fmt.Sprintln(reflect.TypeOf(x)))
+			}
+		}
+	}
+	panic(0)
+}
+
+func (o *ops) Len(a object.Object, _a, _b scope.Value) (ret scope.Value) {
+	//assert.For(a != nil, 20)
+	assert.For(_b != nil, 21)
+	var b int32 = gfrom(_b).(int32)
+	assert.For(b == 0, 22)
+	if a != nil {
+		assert.For(a.Type() == object.COMPLEX, 23)
+		switch typ := a.Complex().(type) {
+		case object.ArrayType:
+			ret = INTEGER(int32(typ.Len()))
+		case object.DynArrayType:
+			switch t := _a.(type) {
+			case *arr:
+				ret = INTEGER(t.length)
+			case *dynarr:
+				ret = INTEGER(len(t.val))
+			default:
+				halt.As(100, "unsupported", reflect.TypeOf(t))
+			}
+		default:
+			panic(fmt.Sprintln("unsupported", reflect.TypeOf(a.Complex())))
+		}
+	} else {
+		switch a := _a.(type) {
+		case *arr:
+			ret = INTEGER(int32(a.length))
+		case *dynarr:
+			ret = INTEGER(int32(len(a.val)))
+		case STRING:
+			rs := []rune(string(a))
+			ln := len(rs)
+			ret = INTEGER(0)
+			for l := 0; l < ln && rs[l] != 0; l++ {
+				ret = INTEGER(l + 1)
+			}
+		default:
+			panic(fmt.Sprintln("unsupported", reflect.TypeOf(a)))
+		}
+	}
+	return ret
+}
+
+func (o *ops) Is(a scope.Value, typ object.ComplexType) scope.Value {
+	var compare func(x, a object.ComplexType) bool
+	compare = func(_x, _a object.ComplexType) bool {
+		switch x := _x.(type) {
+		case object.RecordType:
+			switch a := _a.(type) {
+			case object.RecordType:
+				switch {
+				case x.Name() == a.Name():
+					//	fmt.Println("eq")
+					//fmt.Println("qid ", _x.Qualident(), _a.Qualident(), "names ", x.Name(), a.Name())
+					return true //опасно сравнивать имена конеш
+				case x.Complex() != nil:
+					//	fmt.Println("go base")
+					return compare(x.Complex(), a)
+				default:
+					return false
+				}
+			case object.PointerType:
+				if a.Complex() != nil {
+					return compare(x, a.Complex())
+				} else {
+					fmt.Println("here")
+					return false
+				}
+			default:
+				halt.As(100, reflect.TypeOf(a))
+			}
+		case object.PointerType:
+			switch a := _a.(type) {
+			case object.PointerType:
+				switch {
+				case x.Name() == a.Name():
+					//	fmt.Println("eq")
+					return true //опасно сравнивать имена конеш
+				case x.Complex() != nil:
+					//	fmt.Println("go base")
+					return compare(x.Complex(), a)
+				default:
+					return false
+				}
+			default:
+				halt.As(100, reflect.TypeOf(a))
+			}
+		default:
+			halt.As(100, reflect.TypeOf(a))
+		}
+		panic(0)
+	}
+	switch x := a.(type) {
+	case *rec:
+		z, a := x.link.Complex().(object.RecordType)
+		y, b := typ.(object.RecordType)
+		//fmt.Println("compare rec", x.link.Complex(), typ, a, b, a && b && compare(z, y))
+		return BOOLEAN(a && b && compare(z, y))
+	case *ptr:
+		z, a := x.link.Complex().(object.PointerType)
+		if val := x.Get(); z.Name() == "ANYPTR" && val != NIL {
+			t, c := o.TypeOf(val)
+			assert.For(t == object.COMPLEX, 40)
+			z, a = c.(object.RecordType)
+		}
+		y, b := typ.(object.PointerType)
+		//fmt.Println("compare ptr", z, typ, a, b, a && b && compare(z, y))
+		return BOOLEAN(a && b && compare(z, y))
+	default:
+		halt.As(100, reflect.TypeOf(x))
+	}
+	panic(0)
+}
+
+func (o *ops) Conv(a scope.Value, typ object.Type, comp ...object.ComplexType) scope.Value {
+	switch typ {
+	case object.INTEGER:
+		switch x := a.(type) {
+		case *data:
+			return o.Conv(vfrom(x), typ, comp...)
+		case *idx:
+			//t, c := x.base()
+			return o.Conv(x.val()[x.idx].(scope.Value), typ, comp...)
+		case BYTE:
+			return INTEGER(x)
+		case SET:
+			return INTEGER(x.bits.Int64())
+		case REAL:
+			return INTEGER(x)
+		case LONGINT:
+			return INTEGER(x)
+		case CHAR:
+			return INTEGER(x)
+		default:
+			halt.As(100, reflect.TypeOf(x))
+		}
+	case object.LONGINT:
+		switch x := a.(type) {
+		case *data:
+			return o.Conv(vfrom(x), typ, comp...)
+		case INTEGER:
+			return LONGINT(x)
+		case REAL:
+			return LONGINT(math.Floor(float64(x)))
+		default:
+			halt.As(100, reflect.TypeOf(x))
+		}
+	case object.SET:
+		switch x := a.(type) {
+		case *data:
+			return o.Conv(vfrom(x), typ, comp...)
+		case INTEGER:
+			return SET{bits: big.NewInt(int64(x))}
+		default:
+			halt.As(100, reflect.TypeOf(x))
+		}
+	case object.REAL:
+		switch x := a.(type) {
+		case *data:
+			return o.Conv(vfrom(x), typ, comp...)
+		case INTEGER:
+			return REAL(float64(x))
+		default:
+			halt.As(100, reflect.TypeOf(x))
+		}
+	case object.CHAR:
+		switch x := a.(type) {
+		case *data:
+			return o.Conv(vfrom(x), typ, comp...)
+		case LONGINT:
+			return CHAR(rune(x))
+		case INTEGER:
+			return CHAR(rune(x))
+		case CHAR:
+			return x
+		default:
+			halt.As(100, reflect.TypeOf(x))
+		}
+	case object.NOTYPE:
+		assert.For(len(comp) > 0, 20)
+		switch t := comp[0].(type) {
+		case object.BasicType:
+			switch t.Type() {
+			case object.SHORTSTRING:
+				switch x := a.(type) {
+				case *dynarr:
+					return SHORTSTRING(x.tryString())
+				case *arr:
+					return SHORTSTRING(x.tryString())
+				case STRING:
+					return SHORTSTRING(x)
+				default:
+					halt.As(100, reflect.TypeOf(x))
+				}
+			default:
+				halt.As(100, t.Type())
+			}
+		default:
+			halt.As(100, reflect.TypeOf(t))
+		}
+	default:
+		halt.As(100, typ)
+	}
+	panic(100)
+}
+
+func (o *ops) Not(a scope.Value) scope.Value {
+	switch x := a.(type) {
+	case *data:
+		return o.Not(vfrom(x))
+	case BOOLEAN:
+		return BOOLEAN(!x)
+	default:
+		halt.As(100, reflect.TypeOf(x))
+	}
+	panic(100)
+}
+
+func (o *ops) Abs(a scope.Value) scope.Value {
+	switch x := a.(type) {
+	case *data:
+		return o.Abs(vfrom(x))
+	case INTEGER:
+		return INTEGER(int32(math.Abs(float64(x))))
+	default:
+		halt.As(100, reflect.TypeOf(x))
+	}
+	panic(100)
+}
+
+func (o *ops) Minus(a scope.Value) scope.Value {
+	switch x := a.(type) {
+	case *data:
+		return o.Minus(vfrom(x))
+	case INTEGER:
+		return INTEGER(-x)
+	case LONGINT:
+		return LONGINT(-x)
+	case REAL:
+		return REAL(-x)
+	default:
+		halt.As(100, reflect.TypeOf(x))
+	}
+	panic(100)
+}
+
+func (o *ops) Odd(a scope.Value) scope.Value {
+	switch x := a.(type) {
+	case *data:
+		return o.Odd(vfrom(x))
+	case INTEGER:
+		return BOOLEAN(int64(math.Abs(float64(x)))%2 == 1)
+	case LONGINT:
+		return BOOLEAN(int64(math.Abs(float64(x)))%2 == 1)
+	default:
+		halt.As(100, reflect.TypeOf(x))
+	}
+	panic(100)
+}
+
+func (o *ops) Cap(a scope.Value) scope.Value {
+	switch x := a.(type) {
+	case *data:
+		return o.Cap(vfrom(x))
+	case CHAR:
+		return CHAR([]rune(strings.ToUpper(string(x)))[0])
+	default:
+		halt.As(100, reflect.TypeOf(x))
+	}
+	panic(100)
+}
+
+func (o *ops) Bits(a scope.Value) scope.Value {
+	switch x := a.(type) {
+	case *data:
+		return o.Bits(vfrom(x))
+	case INTEGER:
+		return SET{bits: big.NewInt(0).SetBit(big.NewInt(0), int(x), 1)}
+	default:
+		halt.As(100, reflect.TypeOf(x))
+	}
+	panic(100)
+}
+func (o *ops) Eq(a, b scope.Value) scope.Value {
+	switch a.(type) {
+	case *data:
+		return o.Eq(vfrom(a), b)
+	default:
+		switch b.(type) {
+		case *data:
+			return o.Eq(a, vfrom(b))
+		default:
+			switch x := a.(type) {
+			case *ptr:
+				switch y := b.(type) {
+				case PTR:
+					assert.For(y == NIL, 40)
+					return BOOLEAN(x.val == nil || x.val.id == 0)
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			case INTEGER:
+				switch y := b.(type) {
+				case INTEGER:
+					return BOOLEAN(x == y)
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			case LONGINT:
+				switch y := b.(type) {
+				case LONGINT:
+					return BOOLEAN(x == y)
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			case CHAR:
+				switch y := b.(type) {
+				case CHAR:
+					return BOOLEAN(x == y)
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			default:
+				panic(fmt.Sprintln(reflect.TypeOf(x)))
+			}
+		}
+	}
+	panic(0)
+}
+
+func (o *ops) Neq(a, b scope.Value) scope.Value {
+	switch i := a.(type) {
+	case *data:
+		return o.Neq(vfrom(a), b)
+	case *idx:
+		return o.Neq(vfrom(i.Get()), b)
+	default:
+		switch b.(type) {
+		case *data:
+			return o.Neq(a, vfrom(b))
+		default:
+			switch x := a.(type) {
+			case *ptr:
+				switch y := b.(type) {
+				case PTR:
+					assert.For(y == NIL, 40)
+					return BOOLEAN(x.val != nil && x.val.id != 0)
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			case INTEGER:
+				switch y := b.(type) {
+				case INTEGER:
+					return BOOLEAN(x != y)
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			case REAL:
+				switch y := b.(type) {
+				case REAL:
+					return BOOLEAN(x != y)
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			case LONGINT:
+				switch y := b.(type) {
+				case LONGINT:
+					return BOOLEAN(x != y)
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			case SET:
+				switch y := b.(type) {
+				case SET:
+					return BOOLEAN(x.bits.Cmp(y.bits) != 0)
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			case BOOLEAN:
+				switch y := b.(type) {
+				case BOOLEAN:
+					return BOOLEAN(x != y)
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			case CHAR:
+				switch y := b.(type) {
+				case CHAR:
+					return BOOLEAN(x != y)
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			default:
+				panic(fmt.Sprintln(reflect.TypeOf(x)))
+			}
+		}
+	}
+	panic(0)
+}
+
+func (o *ops) Lss(a, b scope.Value) scope.Value {
+	switch a.(type) {
+	case *data:
+		return o.Lss(vfrom(a), b)
+	default:
+		switch b.(type) {
+		case *data:
+			return o.Lss(a, vfrom(b))
+		default:
+			switch x := a.(type) {
+			case INTEGER:
+				switch y := b.(type) {
+				case INTEGER:
+					return BOOLEAN(x < y)
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			case REAL:
+				switch y := b.(type) {
+				case REAL:
+					return BOOLEAN(x < y)
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			case LONGINT:
+				switch y := b.(type) {
+				case LONGINT:
+					return BOOLEAN(x < y)
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			case CHAR:
+				switch y := b.(type) {
+				case CHAR:
+					return BOOLEAN(x < y)
+				case INTEGER:
+					return BOOLEAN(uint(x) < uint(y))
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			default:
+				panic(fmt.Sprintln(reflect.TypeOf(x)))
+			}
+		}
+	}
+	panic(0)
+}
+
+func (o *ops) Gtr(a, b scope.Value) scope.Value {
+	switch a.(type) {
+	case *data:
+		return o.Gtr(vfrom(a), b)
+	default:
+		switch b.(type) {
+		case *data:
+			return o.Gtr(a, vfrom(b))
+		default:
+			switch x := a.(type) {
+			case INTEGER:
+				switch y := b.(type) {
+				case INTEGER:
+					return BOOLEAN(x > y)
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			case STRING:
+				switch y := b.(type) {
+				case STRING:
+					//fmt.Println(x, y, x > y)
+					return BOOLEAN(x > y)
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			case REAL:
+				switch y := b.(type) {
+				case REAL:
+					return BOOLEAN(x > y)
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			case LONGINT:
+				switch y := b.(type) {
+				case LONGINT:
+					return BOOLEAN(x > y)
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			default:
+				panic(fmt.Sprintln(reflect.TypeOf(x)))
+			}
+		}
+	}
+	panic(0)
+}
+
+func (o *ops) Leq(a, b scope.Value) scope.Value {
+	switch a.(type) {
+	case *data:
+		return o.Leq(vfrom(a), b)
+	default:
+		switch b.(type) {
+		case *data:
+			return o.Leq(a, vfrom(b))
+		default:
+			switch x := a.(type) {
+			case INTEGER:
+				switch y := b.(type) {
+				case INTEGER:
+					return BOOLEAN(x <= y)
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			default:
+				panic(fmt.Sprintln(reflect.TypeOf(x)))
+			}
+		}
+	}
+	panic(0)
+}
+
+func (o *ops) Geq(a, b scope.Value) scope.Value {
+	switch a.(type) {
+	case *data:
+		return o.Geq(vfrom(a), b)
+	default:
+		switch b.(type) {
+		case *data:
+			return o.Geq(a, vfrom(b))
+		default:
+			switch x := a.(type) {
+			case INTEGER:
+				switch y := b.(type) {
+				case INTEGER:
+					return BOOLEAN(x >= y)
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			case REAL:
+				switch y := b.(type) {
+				case REAL:
+					return BOOLEAN(x >= y)
+				default:
+					panic(fmt.Sprintln(reflect.TypeOf(y)))
+				}
+			default:
+				panic(fmt.Sprintln(reflect.TypeOf(x)))
+			}
+		}
+	}
+	panic(0)
+}
+
+func (o *ops) TypeOf(x scope.Value) (object.Type, object.ComplexType) {
+	switch v := x.(type) {
+	case *ptr:
+		//assert.For(v.val != nil, 20, v.Id())
+		if v.val != nil {
+			return v.val.link.Type(), v.val.link.Complex()
+		} else {
+			//return v.link.Type(), v.link.Complex()
+		}
+	case *rec:
+		return v.link.Type(), v.link.Complex()
+	case *dynarr:
+		return v.link.Type(), v.link.Complex()
+	case *arr:
+		return v.link.Type(), v.link.Complex()
+	case *data:
+		return v.link.Type(), v.link.Complex()
+	default:
+		halt.As(100, reflect.TypeOf(v))
+	}
+	return object.NOTYPE, nil
+}
+
+func init() {
+	scope.ValueFrom = vfrom
+	scope.GoTypeFrom = gfrom
+	scope.TypeFromGo = fromg
+	scope.Ops = &ops{}
+}