73 lines
1.4 KiB
Go
73 lines
1.4 KiB
Go
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)
|
|
}
|