package macro import ( "fmt" "github.com/hellerve/argos/ast" ) type Macro struct { params []string transformer *ast.AST } type MacroEnv map[string]Macro func NewMacroEnv() MacroEnv { return make(MacroEnv) } func handleMac(l []*ast.AST, m MacroEnv) (*ast.AST, error) { if len(l) != 4 { return nil, fmt.Errorf("mac takes 3 arguments") } nameThunk := l[1] if nameThunk.Tag != ast.Symbol { return nil, fmt.Errorf("First argument to mac must be symbol, got %s", nameThunk.Pretty()) } name := nameThunk.Val.(string) paramsThunk := l[2] if paramsThunk.Tag != ast.List { return nil, fmt.Errorf("second argument to mac must be list, got %s", paramsThunk.Pretty()) } var params []string for _, elem := range paramsThunk.Val.([]*ast.AST) { if elem.Tag != ast.Symbol { return nil, fmt.Errorf("Invalid value in parameter list to mac: %s", elem.Pretty()) } params = append(params, elem.Val.(string)) } m[name] = Macro{params, l[2]} nilVal := ast.AST{ast.Symbol, "nil"} return &nilVal, nil } func traverse(l *ast.AST, m MacroEnv) (*ast.AST, error) { vals := l.Val.([]*ast.AST) if len(vals) == 0 { return l, nil } if vals[0].Tag == ast.Symbol && vals[0].Val.(string) == "mac" { return handleMac(vals, m) } return l, nil } func Expand(l *ast.AST, m MacroEnv) (*ast.AST, error) { if l.Tag != ast.List { return l, nil } return traverse(l, m) }