macro: defining macros works

This commit is contained in:
2018-05-15 00:00:30 +02:00
parent 702bd703b9
commit 616e531ddd
3 changed files with 91 additions and 4 deletions

72
macro/macro.go Normal file
View File

@@ -0,0 +1,72 @@
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)
}