Пример #1
0
Файл: eval.go Проект: jbert/gol
func (np NodeProcedure) Apply(e *Evaluator, argVals *gol.NodeList) (gol.Node, error) {
	if argVals.Len() != np.Args.Len() {
		return nil, gol.NodeErrorf(argVals, "Arg mismatch")
	}

	f := gol.Frame{}
	z := np.Args.Zip(argVals)
	err := z.Foreach(func(n gol.Node) error {
		pair, ok := n.(*gol.NodePair)
		if !ok {
			return gol.NodeErrorf(argVals, "Internal error - zip returns non-pair")
		}
		id := pair.Car
		val := pair.Cdr
		idStr := id.String()

		f[idStr] = val
		return nil
	})
	if err != nil {
		return nil, err
	}

	oldEnv := e.Env
	defer func() {
		e.Env = oldEnv
	}()
	e.Env = np.Env.WithFrame(f)
	value, err := e.Eval(np.Body)
	return value, err
}
Пример #2
0
func (gb *GolangBackend) compileFuncCall(funcNameNode *gol.NodeIdentifier, argNodes *gol.NodeList) (string, error) {

	funcName := mangleIdentifier(funcNameNode.String())
	args := []string{}
	err := argNodes.Foreach(func(n gol.Node) error {
		nStr, err := gb.compile(n)
		if err != nil {
			return err
		}
		args = append(args, nStr)
		return nil
	})
	if err != nil {
		return "", err
	}
	s := funcName + "(" + strings.Join(args, ", ") + ")"
	return s, nil
}
Пример #3
0
Файл: eval.go Проект: jbert/gol
func (e *Evaluator) evalList(nl *gol.NodeList) (gol.Node, error) {
	nodes, err := nl.Map(func(child gol.Node) (gol.Node, error) {
		newVal, err := e.Eval(child)
		if err != nil {
			return nil, err
		}
		return newVal, nil
	})
	if err != nil {
		return nil, err
	}

	if e.Quoting() {
		return nodes, nil
	}

	return e.Apply(nodes)
}
Пример #4
0
func (gb *GolangBackend) compileLambdaApplication(nl *gol.NodeLambda, vals *gol.NodeList) (string, error) {
	bindings := make(map[string]gol.Node)

	args := nl.Args

	if args.Len() != vals.Len() {
		return "", fmt.Errorf("Wrong number of args for lambda. [%s] != [%s]",
			args.String(), vals.String())
	}

	for vals.Len() > 0 {
		id := args.First().String()
		bindings[id] = vals.First()

		vals = vals.Rest()
		args = args.Rest()
	}

	letForLambda := &gol.NodeLet{
		//		NodeList: nl.NodeList,
		Bindings: bindings,
		Body:     nl.Body,
	}
	lambdaVarType, ok := nl.Type().(*typ.Var)
	if !ok {
		// Not an error if it's a functype, but we assign vars to all nodes....
		return "", fmt.Errorf("Odd - not a var, instead a %T: %s\n", nl.Type(), nl.Type())
	}
	lambdaType, err := lambdaVarType.Lookup()
	if err != nil {
		return "", fmt.Errorf("Can't look up lambda var: %s [%T]\n", lambdaVarType, lambdaVarType)
	}
	funcType, ok := lambdaType.(typ.Func)
	if !ok {
		return "", fmt.Errorf("Lambda doesn't have function type: %s [%T]\n", nl.Type(), nl.Type())
	}

	letForLambda.NodeList = gol.NewNodeListType(funcType.Result)
	return gb.compileLet(letForLambda)
}
Пример #5
0
func (gb *GolangBackend) compileList(nl *gol.NodeList) (string, error) {
	if nl.Len() == 0 {
		return "", gol.NodeErrorf(nl, "empty application")
	}
	switch fst := nl.First().(type) {
	case *gol.NodeIdentifier:
		return gb.compileFuncCall(fst, nl.Rest())
	case *gol.NodeLambda:
		return gb.compileLambdaApplication(fst, nl.Rest())
	default:
		return "", fmt.Errorf("Non-applicable in head position: %T", fst)
	}
}
Пример #6
0
Файл: eval.go Проект: jbert/gol
func (e *Evaluator) Apply(nl *gol.NodeList) (gol.Node, error) {
	if nl.Len() == 0 {
		return nil, gol.NodeErrorf(nl, "Empty application")
	}
	applicable, ok := nl.First().(NodeApplicable)
	if !ok {
		return nil, gol.NodeErrorf(nl, "Can't evaluate list with non-applicable head: %T [%s]", nl.First(), nl)
	}

	node, err := applicable.Apply(e, nl.Rest())
	if err != nil {
		return nil, err
	}

	return node, nil
}