func ParseLambda(tuple *ast.Tuple) *ast.Lambda { // (lambda <formals> <body>) // switch <formals>: // (<variable1> ...) // <variable> // (<variable1> ... <variablen> . <variablen+1>) elements := tuple.Elements if len(elements) < 3 { panic(fmt.Sprint("lambda: bad syntax: ", tuple)) } pattern := elements[1] body := ast.NewBlock(ParseList(elements[2:])) switch pattern.(type) { case *ast.Name: return ast.NewLambda(pattern, body) case *ast.Tuple: formals := ExpandFormals(pattern.(*ast.Tuple).Elements) _, ok := formals.(*ast.Pair) if ok || formals == ast.NilPair { return ast.NewLambda(formals, body) } else { // (. <variable>) is not allowed panic(fmt.Sprint("lambda: illegal use of `.'")) } default: panic(fmt.Sprint("unsupported parser type ", pattern)) } }
func ParseFunction(tuple *ast.Tuple, tail ast.Node) *ast.Function { // expand definition: e.g. // ((f x) y) <body> => // (lambda (x) // (lambda (y) <body>)) lambda := ast.NewLambda(nil, tail) for { elements := tuple.Elements lambda.Params = ExpandFormals(elements[1:]) // len(elements) must be greater than 0 switch elements[0].(type) { case *ast.Name: return ast.NewFunction(elements[0].(*ast.Name), lambda) case *ast.Tuple: tuple = elements[0].(*ast.Tuple) lambda = ast.NewLambda(nil, lambda) default: panic(fmt.Sprint("unsupported parser type ", elements[0])) } } }