func Eval(x VValue, env *Environment, k *Continuation) { time := prof.GetTime() eval_loop(&Tail{x, env, k, time}, time, true) }
func basicWrapper(internal Callable, eval Evaller, ctx *Tail, args *VPair) bool { if args == nil { return internal.Call(eval, ctx, VNil) } count, ok := 0, true for a := args; a != nil && ok; a, ok = a.Cdr.(*VPair) { count++ } if !ok { panic("Invalid Argument List") } sexpr, senv, sk := ctx.Expr, ctx.Env, ctx.K finished := false blocked := make(map[*Tail]struct{}) arglist := make([]VPair, count, count) f_lock := new(sync.RWMutex) make_reactivation := func(idx int) func(*Tail, *VPair) bool { reassign := func(nctx *Tail, vals *VPair) bool { nctx.Expr, nctx.Env, nctx.K = sexpr, senv, sk nargs, slot := copy_arglist(idx, &(arglist[0])) slot.Car = vals.Car return internal.Call(eval, nctx, nargs) } return func(nctx *Tail, vals *VPair) bool { f_lock.RLock() if finished { f_lock.RUnlock() return reassign(nctx, vals) } f_lock.RUnlock() blocked[&Tail{vals.Car, senv, &Continuation{"ArgK", reassign, []VValue{sexpr, senv, sk, &(arglist[0])}}, nctx.Time}] = struct{}{} nctx.K = nil return false } } make_argk := func(idx int) *Continuation { var k Continuation var reactivate func(*Tail, *VPair) bool k_lock := new(sync.Mutex) activated := false k.Name = "ArgK" k.Fn = func(nctx *Tail, vals *VPair) bool { k_lock.Lock() if activated { k_lock.Unlock() return reactivate(nctx, vals) } activated = true k_lock.Unlock() arglist[idx].Car = vals.Car reactivate = make_reactivation(idx) k.Fn = reactivate nctx.K = nil return false } k.Refs = []VValue{sexpr, senv, sk, &(arglist[0])} return &k } //randomize evaluation order //TODO: Somehow calculate optimal evaluation orders.... argset := make(map[int]VValue) for i := 0; i < count-1; i++ { arglist[i].Cdr = &(arglist[i+1]) argset[i] = args.Car args = args.Cdr.(*VPair) } arglist[count-1].Cdr = VNil argset[count-1] = args.Car time := ctx.Time for i, a := range argset { switch at := a.(type) { case *VPair: eval(&Tail{at, ctx.Env, make_argk(i), time}, time, true) case VSym: eval(&Tail{at, ctx.Env, make_argk(i), time}, time, true) default: arglist[i].Car = a } } f_lock.Lock() finished = true f_lock.Unlock() time = prof.GetTime() ctx.Time = time for context, _ := range blocked { delete(blocked, context) go eval(context, time, false) } return internal.Call(eval, ctx, &(arglist[0])) }