Example #1
0
func Eval(x VValue, env *Environment, k *Continuation) {
	time := prof.GetTime()
	eval_loop(&Tail{x, env, k, time}, time, true)
}
Example #2
0
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]))
}