Beispiel #1
0
func primFunctionParams(e Env, head ast.Node, args []ast.Node) ast.Node {
	arg := args[0]
	switch val := arg.(type) {
	case *Function:
		return ast.NewList(val.Parameters)
	default:
		panicEvalError(args[0], "Argument to 'function-params' not a function: "+arg.String())
	}

	return nil
}
Beispiel #2
0
func primNow(e Env, head ast.Node, args []ast.Node) ast.Node {

	t := time.Now()
	year, month, day := t.Date()
	hour, minute, second := t.Clock()

	result := ast.NewList([]ast.Node{
		&ast.Number{Value: float64(year)},
		&ast.Number{Value: float64(month)},
		&ast.Number{Value: float64(day)},
		&ast.Number{Value: float64(hour)},
		&ast.Number{Value: float64(minute)},
		&ast.Number{Value: float64(second)},
	})

	return result
}
Beispiel #3
0
func evalFunctionApplication(dynamicEnv Env, f *Function, head ast.Node, unevaledArgs []ast.Node, shouldEvalMacros bool) packet {

	// Validate parameters
	isVariableNumberOfParams := false
	for _, param := range f.Parameters {
		paramName := toSymbolName(param)
		if paramName == "&rest" {
			isVariableNumberOfParams = true
		}
	}
	if !isVariableNumberOfParams {
		if len(unevaledArgs) != len(f.Parameters) {
			panicEvalError(head, fmt.Sprintf(
				"Function '%v' expects %v argument(s), but was given %v",
				f.Name,
				len(f.Parameters),
				len(unevaledArgs)))
		}
	}

	// Create the lexical environment based on the function's lexical parent
	lexicalEnv := NewMapEnv(f.Name, f.ParentEnv)

	// Prepare the arguments for application
	var args []ast.Node
	if f.IsMacro {
		args = unevaledArgs
	} else {
		args = evalEachNode(dynamicEnv, unevaledArgs)
	}

	// Map arguments to parameters
	isMappingRestArgs := false
	iarg := 0
	for iparam, param := range f.Parameters {
		paramName := toSymbolName(param)
		if isMappingRestArgs {
			restArgs := args[iarg:]
			restList := ast.NewList(restArgs)
			lexicalEnv.Set(paramName, restList)
		} else if paramName == "&rest" {
			isMappingRestArgs = true
		} else {
			lexicalEnv.Set(paramName, args[iparam])
			iarg++
		}
	}

	if f.IsMacro {
		expandedMacro := trampoline(func() packet {
			return evalNode(lexicalEnv, f.Body)
		})

		if shouldEvalMacros {
			return bounce(func() packet {
				// This is executed in the environment of its application, not the
				// environment of its definition
				return evalNode(dynamicEnv, expandedMacro)
			})
		} else {
			return respond(expandedMacro)
		}
	} else {
		// Evaluate the body in the new lexical environment
		return bounce(func() packet {
			return evalNode(lexicalEnv, f.Body)
		})
	}
}